<commit_before>// hurry mod panel to get it faaaaaaaaaaaast

package router

import (
	"html/template"
	"net/http"
	"path/filepath"
	"strconv"
	"fmt"

	"github.com/ewhal/nyaa/service/comment"
	"github.com/ewhal/nyaa/service/torrent"
	"github.com/ewhal/nyaa/service/torrent/form"
	"github.com/ewhal/nyaa/service/user"
	form "github.com/ewhal/nyaa/service/user/form"
	"github.com/ewhal/nyaa/service/user/permission"
	"github.com/ewhal/nyaa/util/languages"
	"github.com/ewhal/nyaa/util/modelHelper"
)

var panelIndex, panelTorrentList, panelUserList, panelCommentList, panelTorrentEd *template.Template

func init() {
	panelTorrentList = template.Must(template.New("torrentlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/torrentlist.html")))
	panelUserList = template.Must(template.New("userlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/userlist.html")))
	panelCommentList = template.Must(template.New("commentlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/commentlist.html")))
	panelIndex = template.Must(template.New("indexPanel").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/panelindex.html")))
	panelTorrentEd = template.Must(template.New("indexPanel").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/paneltorrentedit.html")))
}

func IndexModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		offset := 10

		torrents, _, _ := torrentService.GetAllTorrents(0, offset)
		users := userService.RetrieveUsersForAdmin(0, offset)
		comments := commentService.GetAllComments(0, offset)
		languages.SetTranslationFromRequest(panelIndex, r, "en-us")
		htv := PanelIndexVbs{torrents, users, comments}
		_ = panelIndex.ExecuteTemplate(w, "admin_index.html", htv)
	}

}
func TorrentsListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		torrents, _, _ := torrentService.GetAllTorrents(offset, page * offset)
		languages.SetTranslationFromRequest(panelTorrentList, r, "en-us")
		htv := PanelTorrentListVbs{torrents}
		err := panelTorrentList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	}
}
func UsersListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		users := userService.RetrieveUsersForAdmin(offset, page*offset)
		languages.SetTranslationFromRequest(panelUserList, r, "en-us")
		htv := PanelUserListVbs{users}
		err := panelUserList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	}
}
func CommentsListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		comments := commentService.GetAllComments(offset, page * offset)
		languages.SetTranslationFromRequest(panelCommentList, r, "en-us")
		htv := PanelCommentListVbs{comments}
		err := panelCommentList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	}

}
func TorrentEditModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		id := r.URL.Query().Get("id")
		torrent, _ := torrentService.GetTorrentById(id)
		languages.SetTranslationFromRequest(panelTorrentEd, r, "en-us")
		htv := PanelTorrentEdVbs{torrent}
		err := panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	}

}
func TorrentPostEditModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		b := torrentform.PanelPost{}
		err := form.NewErrors()
		infos := form.NewInfos()
		modelHelper.BindValueForm(&b, r)
		err = modelHelper.ValidateForm(&b, err)
		id := r.URL.Query().Get("id")
		torrent, _ := torrentService.GetTorrentById(id)
		if torrent.ID > 0 {
			modelHelper.AssignValue(&torrent, &b)
			if len(err) == 0 {
				_, errorT := torrentService.UpdateTorrent(torrent)
				if errorT != nil {
					err["errors"] = append(err["errors"], errorT.Error())
				}
				if len(err) == 0 {
					infos["infos"] = append(infos["infos"], "torrent_updated")
				}
			}
		}
		languages.SetTranslationFromRequest(panelTorrentEd, r, "en-us")
		htv := PanelTorrentEdVbs{torrent}
		_ = panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
	}
}

func CommentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	id := r.URL.Query().Get("id")

	if userPermission.HasAdmin(currentUser) {
		_ = form.NewErrors()
		_, _ = userService.DeleteComment(id)
		url, _ := Router.Get("mod_comment_list").URL()
		http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
	}
}
func TorrentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	id := r.URL.Query().Get("id")
	if userPermission.HasAdmin(currentUser) {
		_ = form.NewErrors()
		_, _ = torrentService.DeleteTorrent(id)
		url, _ := Router.Get("mod_torrent_list").URL()
		http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
	}
}
<commit_msg>add some 403s man<commit_after>// hurry mod panel to get it faaaaaaaaaaaast

package router

import (
	"html/template"
	"net/http"
	"path/filepath"
	"strconv"
	"fmt"

	"github.com/ewhal/nyaa/service/comment"
	"github.com/ewhal/nyaa/service/torrent"
	"github.com/ewhal/nyaa/service/torrent/form"
	"github.com/ewhal/nyaa/service/user"
	form "github.com/ewhal/nyaa/service/user/form"
	"github.com/ewhal/nyaa/service/user/permission"
	"github.com/ewhal/nyaa/util/languages"
	"github.com/ewhal/nyaa/util/modelHelper"
)

var panelIndex, panelTorrentList, panelUserList, panelCommentList, panelTorrentEd *template.Template

func init() {
	panelTorrentList = template.Must(template.New("torrentlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/torrentlist.html")))
	panelUserList = template.Must(template.New("userlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/userlist.html")))
	panelCommentList = template.Must(template.New("commentlist").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/commentlist.html")))
	panelIndex = template.Must(template.New("indexPanel").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/panelindex.html")))
	panelTorrentEd = template.Must(template.New("indexPanel").Funcs(FuncMap).ParseFiles(filepath.Join(TemplateDir, "admin_index.html"), filepath.Join(TemplateDir, "admin/paneltorrentedit.html")))
}

func IndexModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		offset := 10

		torrents, _, _ := torrentService.GetAllTorrents(0, offset)
		users := userService.RetrieveUsersForAdmin(0, offset)
		comments := commentService.GetAllComments(0, offset)
		languages.SetTranslationFromRequest(panelIndex, r, "en-us")
		htv := PanelIndexVbs{torrents, users, comments}
		_ = panelIndex.ExecuteTemplate(w, "admin_index.html", htv)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}
}
func TorrentsListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		torrents, _, _ := torrentService.GetAllTorrents(offset, page * offset)
		languages.SetTranslationFromRequest(panelTorrentList, r, "en-us")
		htv := PanelTorrentListVbs{torrents}
		err := panelTorrentList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	} else {

		http.Error(w, "admins only", http.StatusForbidden)
	}
}
func UsersListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		users := userService.RetrieveUsersForAdmin(offset, page*offset)
		languages.SetTranslationFromRequest(panelUserList, r, "en-us")
		htv := PanelUserListVbs{users}
		err := panelUserList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}
}
func CommentsListPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		page, _ := strconv.Atoi(r.URL.Query().Get("p"))
		offset := 100

		comments := commentService.GetAllComments(offset, page * offset)
		languages.SetTranslationFromRequest(panelCommentList, r, "en-us")
		htv := PanelCommentListVbs{comments}
		err := panelCommentList.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}

}
func TorrentEditModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		id := r.URL.Query().Get("id")
		torrent, _ := torrentService.GetTorrentById(id)
		languages.SetTranslationFromRequest(panelTorrentEd, r, "en-us")
		htv := PanelTorrentEdVbs{torrent}
		err := panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
		fmt.Println(err)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}

}
func TorrentPostEditModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	if userPermission.HasAdmin(currentUser) {
		b := torrentform.PanelPost{}
		err := form.NewErrors()
		infos := form.NewInfos()
		modelHelper.BindValueForm(&b, r)
		err = modelHelper.ValidateForm(&b, err)
		id := r.URL.Query().Get("id")
		torrent, _ := torrentService.GetTorrentById(id)
		if torrent.ID > 0 {
			modelHelper.AssignValue(&torrent, &b)
			if len(err) == 0 {
				_, errorT := torrentService.UpdateTorrent(torrent)
				if errorT != nil {
					err["errors"] = append(err["errors"], errorT.Error())
				}
				if len(err) == 0 {
					infos["infos"] = append(infos["infos"], "torrent_updated")
				}
			}
		}
		languages.SetTranslationFromRequest(panelTorrentEd, r, "en-us")
		htv := PanelTorrentEdVbs{torrent}
		_ = panelTorrentEd.ExecuteTemplate(w, "admin_index.html", htv)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}
}

func CommentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	id := r.URL.Query().Get("id")

	if userPermission.HasAdmin(currentUser) {
		_ = form.NewErrors()
		_, _ = userService.DeleteComment(id)
		url, _ := Router.Get("mod_comment_list").URL()
		http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}
}
func TorrentDeleteModPanel(w http.ResponseWriter, r *http.Request) {
	currentUser := GetUser(r)
	id := r.URL.Query().Get("id")
	if userPermission.HasAdmin(currentUser) {
		_ = form.NewErrors()
		_, _ = torrentService.DeleteTorrent(id)
		url, _ := Router.Get("mod_torrent_list").URL()
		http.Redirect(w, r, url.String()+"?deleted", http.StatusSeeOther)
	} else {
		http.Error(w, "admins only", http.StatusForbidden)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/kube-etcd-controller/test/e2e/framework"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/util/wait"
)

const etcdTPRURL = "/apis/coreos.com/v1/etcdclusters"

func main() {
	kubeconfig := flag.String("kubeconfig", "", "kube config path, e.g. $HOME/.kube/config")
	flag.Parse()
	f, err := framework.New(*kubeconfig)
	if err != nil {
		panic(err)
	}
	if err := SetupEtcdController(f); err != nil {
		panic(err)
	}
	logrus.Info("setup finished successfully")
}

func SetupEtcdController(f *framework.Framework) error {
	// TODO: unify this and the yaml file in example/
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:   "kube-etcd-controller",
			Labels: map[string]string{"name": "kube-etcd-controller"},
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:  "kube-etcd-controller",
					Image: "gcr.io/coreos-k8s-scale-testing/kubeetcdctrl:latest",
				},
			},
		},
	}
	_, err := f.KubeClient.Pods("default").Create(pod)
	if err != nil {
		return err
	}
	err = waitTPRReady(f)
	if err != nil {
		return err
	}
	logrus.Info("etcd controller created successfully")
	return nil
}

func waitTPRReady(f *framework.Framework) error {
	return wait.Poll(time.Second*20, time.Minute*5, func() (bool, error) {
		resp, err := f.KubeClient.Client.Get(f.MasterHost + etcdTPRURL)
		if err != nil {
			logrus.Errorf("http GET failed: %v", err)
			return false, err
		}
		switch resp.StatusCode {
		case http.StatusOK:
			return true, nil
		case http.StatusNotFound: // not set up yet. wait.
			logrus.Info("TPR not set up yet. Keep waiting...")
			return false, nil
		default:
			return false, fmt.Errorf("unexpected status code: %v", resp.Status)
		}
	})
}
<commit_msg>make internal func private<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/kube-etcd-controller/test/e2e/framework"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/util/wait"
)

const etcdTPRURL = "/apis/coreos.com/v1/etcdclusters"

func main() {
	kubeconfig := flag.String("kubeconfig", "", "kube config path, e.g. $HOME/.kube/config")
	flag.Parse()
	f, err := framework.New(*kubeconfig)
	if err != nil {
		panic(err)
	}
	if err := setupEtcdController(f); err != nil {
		panic(err)
	}
	logrus.Info("setup finished successfully")
}

func setupEtcdController(f *framework.Framework) error {
	// TODO: unify this and the yaml file in example/
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:   "kube-etcd-controller",
			Labels: map[string]string{"name": "kube-etcd-controller"},
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:  "kube-etcd-controller",
					Image: "gcr.io/coreos-k8s-scale-testing/kubeetcdctrl:latest",
				},
			},
		},
	}
	_, err := f.KubeClient.Pods("default").Create(pod)
	if err != nil {
		return err
	}
	err = waitTPRReady(f)
	if err != nil {
		return err
	}
	logrus.Info("etcd controller created successfully")
	return nil
}

func waitTPRReady(f *framework.Framework) error {
	return wait.Poll(time.Second*20, time.Minute*5, func() (bool, error) {
		resp, err := f.KubeClient.Client.Get(f.MasterHost + etcdTPRURL)
		if err != nil {
			logrus.Errorf("http GET failed: %v", err)
			return false, err
		}
		switch resp.StatusCode {
		case http.StatusOK:
			return true, nil
		case http.StatusNotFound: // not set up yet. wait.
			logrus.Info("TPR not set up yet. Keep waiting...")
			return false, nil
		default:
			return false, fmt.Errorf("unexpected status code: %v", resp.Status)
		}
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 e2e_node

import (
	goerrors "errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/uuid"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/test/e2e/framework"

	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
	imageutils "k8s.io/kubernetes/test/utils/image"
)

var _ = framework.KubeDescribe("MirrorPod", func() {
	f := framework.NewDefaultFramework("mirror-pod")
	ginkgo.Context("when create a mirror pod ", func() {
		var ns, podPath, staticPodName, mirrorPodName string
		ginkgo.BeforeEach(func() {
			ns = f.Namespace.Name
			staticPodName = "static-pod-" + string(uuid.NewUUID())
			mirrorPodName = staticPodName + "-" + framework.TestContext.NodeName

			podPath = framework.TestContext.KubeletConfig.StaticPodPath

			ginkgo.By("create the static pod")
			err := createStaticPod(podPath, staticPodName, ns,
				imageutils.GetE2EImage(imageutils.Nginx), v1.RestartPolicyAlways)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be running")
			gomega.Eventually(func() error {
				return checkMirrorPodRunning(f.ClientSet, mirrorPodName, ns)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, update
			Description: Updating a static Pod MUST recreate an updated mirror Pod. Create a static pod, verify that a mirror pod is created. Update the static pod by changing the container image, the mirror pod MUST be re-created and updated with the new image.
		*/
		ginkgo.It("should be updated when static pod updated [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("update the static pod container image")
			image := imageutils.GetPauseImageName()
			err = createStaticPod(podPath, staticPodName, ns, image, v1.RestartPolicyAlways)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be updated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())

			ginkgo.By("check the mirror pod container image is updated")
			pod, err = f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			framework.ExpectEqual(len(pod.Spec.Containers), 1)
			framework.ExpectEqual(pod.Spec.Containers[0].Image, image)
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, delete
			Description:  When a mirror-Pod is deleted then the mirror pod MUST be re-created. Create a static pod, verify that a mirror pod is created. Delete the mirror pod, the mirror pod MUST be re-created and running.
		*/
		ginkgo.It("should be recreated when mirror pod gracefully deleted [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("delete the mirror pod with grace period 30s")
			err = f.ClientSet.CoreV1().Pods(ns).Delete(mirrorPodName, metav1.NewDeleteOptions(30))
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be recreated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, force delete
			Description: When a mirror-Pod is deleted, forcibly, then the mirror pod MUST be re-created. Create a static pod, verify that a mirror pod is created. Delete the mirror pod with delete wait time set to zero forcing immediate deletion, the mirror pod MUST be re-created and running.
		*/
		ginkgo.It("should be recreated when mirror pod forcibly deleted [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("delete the mirror pod with grace period 0s")
			err = f.ClientSet.CoreV1().Pods(ns).Delete(mirrorPodName, metav1.NewDeleteOptions(0))
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be recreated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		ginkgo.AfterEach(func() {
			ginkgo.By("delete the static pod")
			err := deleteStaticPod(podPath, staticPodName, ns)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to disappear")
			gomega.Eventually(func() error {
				return checkMirrorPodDisappear(f.ClientSet, mirrorPodName, ns)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
	})
})

func staticPodPath(dir, name, namespace string) string {
	return filepath.Join(dir, namespace+"-"+name+".yaml")
}

func createStaticPod(dir, name, namespace, image string, restart v1.RestartPolicy) error {
	template := `
apiVersion: v1
kind: Pod
metadata:
  name: %s
  namespace: %s
spec:
  containers:
  - name: test
    image: %s
    restartPolicy: %s
`
	file := staticPodPath(dir, name, namespace)
	podYaml := fmt.Sprintf(template, name, namespace, image, string(restart))

	f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.WriteString(podYaml)
	return err
}

func deleteStaticPod(dir, name, namespace string) error {
	file := staticPodPath(dir, name, namespace)
	return os.Remove(file)
}

func checkMirrorPodDisappear(cl clientset.Interface, name, namespace string) error {
	_, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if errors.IsNotFound(err) {
		return nil
	}
	return goerrors.New("pod not disappear")
}

func checkMirrorPodRunning(cl clientset.Interface, name, namespace string) error {
	pod, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
	}
	if pod.Status.Phase != v1.PodRunning {
		return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
	}
	return nil
}

func checkMirrorPodRecreatedAndRunning(cl clientset.Interface, name, namespace string, oUID types.UID) error {
	pod, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
	}
	if pod.UID == oUID {
		return fmt.Errorf("expected the uid of mirror pod %q to be changed, got %q", name, pod.UID)
	}
	if pod.Status.Phase != v1.PodRunning {
		return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
	}
	return nil
}
<commit_msg>Add mirror pod e2e test<commit_after>/*
Copyright 2016 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 e2e_node

import (
	goerrors "errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	v1 "k8s.io/api/core/v1"
	apiequality "k8s.io/apimachinery/pkg/api/equality"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/uuid"
	clientset "k8s.io/client-go/kubernetes"
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

	"github.com/google/go-cmp/cmp"
	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
)

var _ = framework.KubeDescribe("MirrorPod", func() {
	f := framework.NewDefaultFramework("mirror-pod")
	ginkgo.Context("when create a mirror pod ", func() {
		var ns, podPath, staticPodName, mirrorPodName string
		ginkgo.BeforeEach(func() {
			ns = f.Namespace.Name
			staticPodName = "static-pod-" + string(uuid.NewUUID())
			mirrorPodName = staticPodName + "-" + framework.TestContext.NodeName

			podPath = framework.TestContext.KubeletConfig.StaticPodPath

			ginkgo.By("create the static pod")
			err := createStaticPod(podPath, staticPodName, ns,
				imageutils.GetE2EImage(imageutils.Nginx), v1.RestartPolicyAlways)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be running")
			gomega.Eventually(func() error {
				return checkMirrorPodRunning(f.ClientSet, mirrorPodName, ns)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, update
			Description: Updating a static Pod MUST recreate an updated mirror Pod. Create a static pod, verify that a mirror pod is created. Update the static pod by changing the container image, the mirror pod MUST be re-created and updated with the new image.
		*/
		ginkgo.It("should be updated when static pod updated [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("update the static pod container image")
			image := imageutils.GetPauseImageName()
			err = createStaticPod(podPath, staticPodName, ns, image, v1.RestartPolicyAlways)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be updated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())

			ginkgo.By("check the mirror pod container image is updated")
			pod, err = f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			framework.ExpectEqual(len(pod.Spec.Containers), 1)
			framework.ExpectEqual(pod.Spec.Containers[0].Image, image)
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, delete
			Description:  When a mirror-Pod is deleted then the mirror pod MUST be re-created. Create a static pod, verify that a mirror pod is created. Delete the mirror pod, the mirror pod MUST be re-created and running.
		*/
		ginkgo.It("should be recreated when mirror pod gracefully deleted [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("delete the mirror pod with grace period 30s")
			err = f.ClientSet.CoreV1().Pods(ns).Delete(mirrorPodName, metav1.NewDeleteOptions(30))
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be recreated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		/*
			Release : v1.9
			Testname: Mirror Pod, force delete
			Description: When a mirror-Pod is deleted, forcibly, then the mirror pod MUST be re-created. Create a static pod, verify that a mirror pod is created. Delete the mirror pod with delete wait time set to zero forcing immediate deletion, the mirror pod MUST be re-created and running.
		*/
		ginkgo.It("should be recreated when mirror pod forcibly deleted [NodeConformance]", func() {
			ginkgo.By("get mirror pod uid")
			pod, err := f.ClientSet.CoreV1().Pods(ns).Get(mirrorPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			uid := pod.UID

			ginkgo.By("delete the mirror pod with grace period 0s")
			err = f.ClientSet.CoreV1().Pods(ns).Delete(mirrorPodName, metav1.NewDeleteOptions(0))
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to be recreated")
			gomega.Eventually(func() error {
				return checkMirrorPodRecreatedAndRunning(f.ClientSet, mirrorPodName, ns, uid)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
		ginkgo.AfterEach(func() {
			ginkgo.By("delete the static pod")
			err := deleteStaticPod(podPath, staticPodName, ns)
			framework.ExpectNoError(err)

			ginkgo.By("wait for the mirror pod to disappear")
			gomega.Eventually(func() error {
				return checkMirrorPodDisappear(f.ClientSet, mirrorPodName, ns)
			}, 2*time.Minute, time.Second*4).Should(gomega.BeNil())
		})
	})
})

func staticPodPath(dir, name, namespace string) string {
	return filepath.Join(dir, namespace+"-"+name+".yaml")
}

func createStaticPod(dir, name, namespace, image string, restart v1.RestartPolicy) error {
	template := `
apiVersion: v1
kind: Pod
metadata:
  name: %s
  namespace: %s
spec:
  containers:
  - name: test
    image: %s
    restartPolicy: %s
`
	file := staticPodPath(dir, name, namespace)
	podYaml := fmt.Sprintf(template, name, namespace, image, string(restart))

	f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.WriteString(podYaml)
	return err
}

func deleteStaticPod(dir, name, namespace string) error {
	file := staticPodPath(dir, name, namespace)
	return os.Remove(file)
}

func checkMirrorPodDisappear(cl clientset.Interface, name, namespace string) error {
	_, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if errors.IsNotFound(err) {
		return nil
	}
	return goerrors.New("pod not disappear")
}

func checkMirrorPodRunning(cl clientset.Interface, name, namespace string) error {
	pod, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
	}
	if pod.Status.Phase != v1.PodRunning {
		return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
	}
	return validateMirrorPod(cl, pod)
}

func checkMirrorPodRecreatedAndRunning(cl clientset.Interface, name, namespace string, oUID types.UID) error {
	pod, err := cl.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
	}
	if pod.UID == oUID {
		return fmt.Errorf("expected the uid of mirror pod %q to be changed, got %q", name, pod.UID)
	}
	if pod.Status.Phase != v1.PodRunning {
		return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
	}
	return validateMirrorPod(cl, pod)
}

func validateMirrorPod(cl clientset.Interface, mirrorPod *v1.Pod) error {
	hash, ok := mirrorPod.Annotations[kubetypes.ConfigHashAnnotationKey]
	if !ok || hash == "" {
		return fmt.Errorf("expected mirror pod %q to have a hash annotation", mirrorPod.Name)
	}
	mirrorHash, ok := mirrorPod.Annotations[kubetypes.ConfigMirrorAnnotationKey]
	if !ok || mirrorHash == "" {
		return fmt.Errorf("expected mirror pod %q to have a mirror pod annotation", mirrorPod.Name)
	}
	if hash != mirrorHash {
		return fmt.Errorf("expected mirror pod %q to have a matching mirror pod hash: got %q; expected %q", mirrorPod.Name, mirrorHash, hash)
	}
	source, ok := mirrorPod.Annotations[kubetypes.ConfigSourceAnnotationKey]
	if !ok {
		return fmt.Errorf("expected mirror pod %q to have a source annotation", mirrorPod.Name)
	}
	if source == kubetypes.ApiserverSource {
		return fmt.Errorf("expected mirror pod %q source to not be 'api'; got: %q", mirrorPod.Name, source)
	}

	if len(mirrorPod.OwnerReferences) != 1 {
		return fmt.Errorf("expected mirror pod %q to have a single owner reference: got %d", mirrorPod.Name, len(mirrorPod.OwnerReferences))
	}
	node, err := cl.CoreV1().Nodes().Get(framework.TestContext.NodeName, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("failed to fetch test node: %v", err)
	}

	controller := true
	expectedOwnerRef := metav1.OwnerReference{
		APIVersion: "v1",
		Kind:       "Node",
		Name:       framework.TestContext.NodeName,
		UID:        node.UID,
		Controller: &controller,
	}
	ref := mirrorPod.OwnerReferences[0]
	if !apiequality.Semantic.DeepEqual(ref, expectedOwnerRef) {
		return fmt.Errorf("unexpected mirror pod %q owner ref: %v", mirrorPod.Name, cmp.Diff(expectedOwnerRef, ref))
	}

	return nil
}
<|endoftext|>


<commit_before>package class

var (
	_shimClass  = &Class{name: "~shim"}
	_returnCode = []byte{0xb1} // return
	_athrowCode = []byte{0xbf} // athrow

	_shimMethod = &Method{
		ClassMember: ClassMember{
			AccessFlags: AccessFlags{ACC_STATIC},
			name:        "<return>",
			class:       _shimClass,
		},
		code: _returnCode,
	}

	_athrowMethod = &Method{
		ClassMember: ClassMember{
			AccessFlags: AccessFlags{ACC_STATIC},
			name:        "<athrow>",
			class:       _shimClass,
		},
		code: _athrowCode,
	}
)

func ReturnMethod() *Method {
	return _shimMethod
}

func AthrowMethod() *Method {
	return _athrowMethod
}
<commit_msg>rename var<commit_after>package class

var (
	_shimClass  = &Class{name: "~shim"}
	_returnCode = []byte{0xb1} // return
	_athrowCode = []byte{0xbf} // athrow

	_returnMethod = &Method{
		ClassMember: ClassMember{
			AccessFlags: AccessFlags{ACC_STATIC},
			name:        "<return>",
			class:       _shimClass,
		},
		code: _returnCode,
	}

	_athrowMethod = &Method{
		ClassMember: ClassMember{
			AccessFlags: AccessFlags{ACC_STATIC},
			name:        "<athrow>",
			class:       _shimClass,
		},
		code: _athrowCode,
	}
)

func ReturnMethod() *Method {
	return _returnMethod
}

func AthrowMethod() *Method {
	return _athrowMethod
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zanzibar

import (
	"context"
	"time"

	"github.com/uber-go/tally"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type contextFieldKey string

// ContextScopeTagsExtractor defines func where extracts tags from context
type ContextScopeTagsExtractor func(context.Context) map[string]string

// ContextLogFieldsExtractor defines func where extracts log fields from context
type ContextLogFieldsExtractor func(context.Context) []zap.Field

const (
	endpointKey           = contextFieldKey("endpoint")
	requestUUIDKey        = contextFieldKey("requestUUID")
	routingDelegateKey    = contextFieldKey("rd")
	endpointRequestHeader = contextFieldKey("endpointRequestHeader")
	requestLogFields      = contextFieldKey("requestLogFields")
	scopeTags             = contextFieldKey("scopeTags")
)

const (
	// thrift service::method of endpoint thrift spec
	logFieldRequestMethod       = "endpointThriftMethod"
	logFieldRequestURL          = "url"
	logFieldRequestStartTime    = "timestamp-started"
	logFieldRequestFinishedTime = "timestamp-finished"
	logFieldResponseStatusCode  = "statusCode"
	logFieldRequestUUID         = "requestUUID"
	logFieldEndpointID          = "endpointID"
	logFieldEndpointHandler     = "endpointHandler"
	logFieldClientHTTPMethod    = "clientHTTPMethod"

	logFieldClientRequestHeaderPrefix    = "Client-Req-Header"
	logFieldClientResponseHeaderPrefix   = "Client-Res-Header"
	logFieldEndpointResponseHeaderPrefix = "Res-Header"
)

const (
	scopeTagClientMethod    = "clientmethod"
	scopeTagEndpointMethod  = "endpointmethod"
	scopeTagClient          = "clientid"
	scopeTagEndpoint        = "endpointid"
	scopeTagHandler         = "handlerid"
	scopeTagError           = "error"
	scopeTagStatus          = "status"
	scopeTagProtocol        = "protocol"
	scopeTagHTTP            = "HTTP"
	scopeTagTChannel        = "TChannel"
	scopeTagsTargetService  = "targetservice"
	scopeTagsTargetEndpoint = "targetendpoint"
)

// WithEndpointField adds the endpoint information in the
// request context.
func WithEndpointField(ctx context.Context, endpoint string) context.Context {
	return context.WithValue(ctx, endpointKey, endpoint)
}

// GetRequestEndpointFromCtx returns the endpoint, if it exists on context
func GetRequestEndpointFromCtx(ctx context.Context) string {
	if val := ctx.Value(endpointKey); val != nil {
		endpoint, _ := val.(string)
		return endpoint
	}
	return ""
}

// WithEndpointRequestHeadersField adds the endpoint request header information in the
// request context.
func WithEndpointRequestHeadersField(ctx context.Context, requestHeaders map[string]string) context.Context {
	headers := GetEndpointRequestHeadersFromCtx(ctx)
	for k, v := range requestHeaders {
		headers[k] = v
	}

	return context.WithValue(ctx, endpointRequestHeader, headers)
}

// GetEndpointRequestHeadersFromCtx returns the endpoint request headers, if it exists on context
func GetEndpointRequestHeadersFromCtx(ctx context.Context) map[string]string {
	requestHeaders := make(map[string]string)
	if val := ctx.Value(endpointRequestHeader); val != nil {
		headers, _ := val.(map[string]string)
		for k, v := range headers {
			requestHeaders[k] = v
		}
	}

	return requestHeaders
}

// withRequestUUID returns a context with request uuid.
func withRequestUUID(ctx context.Context, reqUUID string) context.Context {
	return context.WithValue(ctx, requestUUIDKey, reqUUID)
}

// RequestUUIDFromCtx returns the RequestUUID, if it exists on context
func RequestUUIDFromCtx(ctx context.Context) string {
	if val := ctx.Value(requestUUIDKey); val != nil {
		uuid, _ := val.(string)
		return uuid
	}
	return ""
}

// WithRoutingDelegate adds the tchannel routing delegate information in the
// request context.
func WithRoutingDelegate(ctx context.Context, rd string) context.Context {
	return context.WithValue(ctx, routingDelegateKey, rd)
}

// GetRoutingDelegateFromCtx returns the tchannel routing delegate info
// extracted from context.
func GetRoutingDelegateFromCtx(ctx context.Context) string {
	if val := ctx.Value(routingDelegateKey); val != nil {
		rd, _ := val.(string)
		return rd
	}
	return ""
}

// GetShardKeyFromCtx returns the tchannel shardkey info
// extracted from context.
func GetShardKeyFromCtx(ctx context.Context) string {
	if val := ctx.Value(shardKey); val != nil {
		sk, _ := val.(string)
		return sk
	}
	return ""
}

// WithLogFields returns a new context with the given log fields attached to context.Context
func WithLogFields(ctx context.Context, newFields ...zap.Field) context.Context {
	return context.WithValue(ctx, requestLogFields, accumulateLogFields(ctx, newFields))
}

// GetLogFieldsFromCtx returns the log fields attached to the context.Context
func GetLogFieldsFromCtx(ctx context.Context) []zap.Field {
	var fields []zap.Field
	v := ctx.Value(requestLogFields)
	if v != nil {
		fields = v.([]zap.Field)
	}
	return fields
}

// WithScopeTags returns a new context with the given scope tags attached to context.Context
func WithScopeTags(ctx context.Context, newFields map[string]string) context.Context {
	tags := GetScopeTagsFromCtx(ctx)
	for k, v := range newFields {
		tags[k] = v
	}

	return context.WithValue(ctx, scopeTags, tags)
}

// GetScopeTagsFromCtx returns the tag info extracted from context.
func GetScopeTagsFromCtx(ctx context.Context) map[string]string {
	tags := make(map[string]string)
	if val := ctx.Value(scopeTags); val != nil {
		headers, _ := val.(map[string]string)
		for k, v := range headers {
			tags[k] = v
		}
	}

	return tags
}

func accumulateLogFields(ctx context.Context, newFields []zap.Field) []zap.Field {
	previousFields := GetLogFieldsFromCtx(ctx)
	return append(previousFields, newFields...)
}

// ContextExtractor is a extractor that extracts some log fields from the context
type ContextExtractor interface {
	ExtractScopeTags(ctx context.Context) map[string]string
	ExtractLogFields(ctx context.Context) []zap.Field
}

// ContextExtractors warps extractors for context, implements ContextExtractor interface
type ContextExtractors struct {
	ScopeTagsExtractors []ContextScopeTagsExtractor
	LogFieldsExtractors []ContextLogFieldsExtractor
}

// ExtractScopeTags extracts scope fields from a context into a tag.
func (c *ContextExtractors) ExtractScopeTags(ctx context.Context) map[string]string {
	tags := make(map[string]string)
	for _, fn := range c.ScopeTagsExtractors {
		sc := fn(ctx)
		for k, v := range sc {
			tags[k] = v
		}
	}

	return tags
}

// ExtractLogFields extracts log fields from a context into a field.
func (c *ContextExtractors) ExtractLogFields(ctx context.Context) []zap.Field {
	var fields []zap.Field
	for _, fn := range c.LogFieldsExtractors {
		logFields := fn(ctx)
		fields = append(fields, logFields...)
	}

	return fields
}

// ContextLogger is a logger that extracts some log fields from the context before passing through to underlying zap logger.
type ContextLogger interface {
	Debug(ctx context.Context, msg string, fields ...zap.Field)
	Error(ctx context.Context, msg string, fields ...zap.Field)
	Info(ctx context.Context, msg string, fields ...zap.Field)
	Panic(ctx context.Context, msg string, fields ...zap.Field)
	Warn(ctx context.Context, msg string, fields ...zap.Field)

	// Other utility methods on the logger
	Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry
}

// NewContextLogger returns a logger that extracts log fields a context before passing through to underlying zap logger.
func NewContextLogger(log *zap.Logger) ContextLogger {
	return &contextLogger{
		log: log,
	}
}

type contextLogger struct {
	log *zap.Logger
}

func (c *contextLogger) Debug(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Debug(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Error(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Error(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Info(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Info(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Panic(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Panic(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Warn(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Warn(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
	return c.log.Check(lvl, msg)
}

// Logger is a generic logger interface that zap.Logger implements.
type Logger interface {
	Debug(msg string, fields ...zap.Field)
	Error(msg string, fields ...zap.Field)
	Info(msg string, fields ...zap.Field)
	Panic(msg string, fields ...zap.Field)
	Warn(msg string, fields ...zap.Field)
	Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry
}

// ContextMetrics emit metrics with tags extracted from context.
type ContextMetrics interface {
	IncCounter(ctx context.Context, name string, value int64)
	RecordTimer(ctx context.Context, name string, d time.Duration)
}

type contextMetrics struct {
	scope tally.Scope
}

// NewContextMetrics create ContextMetrics to emit metrics with tags extracted from context.
func NewContextMetrics(scope tally.Scope) ContextMetrics {
	return &contextMetrics{
		scope: scope,
	}
}

// IncCounter increments the counter with current tags from context
func (c *contextMetrics) IncCounter(ctx context.Context, name string, value int64) {
	tags := GetScopeTagsFromCtx(ctx)
	c.scope.Tagged(tags).Counter(name).Inc(value)
}

// RecordTimer records the duration with current tags from context
func (c *contextMetrics) RecordTimer(ctx context.Context, name string, d time.Duration) {
	tags := GetScopeTagsFromCtx(ctx)
	c.scope.Tagged(tags).Timer(name).Record(d)
}
<commit_msg>Set ShardKey from the context if its available<commit_after>// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zanzibar

import (
	"context"
	"time"

	"github.com/uber-go/tally"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type contextFieldKey string

// ContextScopeTagsExtractor defines func where extracts tags from context
type ContextScopeTagsExtractor func(context.Context) map[string]string

// ContextLogFieldsExtractor defines func where extracts log fields from context
type ContextLogFieldsExtractor func(context.Context) []zap.Field

const (
	endpointKey           = contextFieldKey("endpoint")
	requestUUIDKey        = contextFieldKey("requestUUID")
	routingDelegateKey    = contextFieldKey("rd")
	shardKey              = contextFieldKey("sk")
	endpointRequestHeader = contextFieldKey("endpointRequestHeader")
	requestLogFields      = contextFieldKey("requestLogFields")
	scopeTags             = contextFieldKey("scopeTags")
)

const (
	// thrift service::method of endpoint thrift spec
	logFieldRequestMethod       = "endpointThriftMethod"
	logFieldRequestURL          = "url"
	logFieldRequestStartTime    = "timestamp-started"
	logFieldRequestFinishedTime = "timestamp-finished"
	logFieldResponseStatusCode  = "statusCode"
	logFieldRequestUUID         = "requestUUID"
	logFieldEndpointID          = "endpointID"
	logFieldEndpointHandler     = "endpointHandler"
	logFieldClientHTTPMethod    = "clientHTTPMethod"

	logFieldClientRequestHeaderPrefix    = "Client-Req-Header"
	logFieldClientResponseHeaderPrefix   = "Client-Res-Header"
	logFieldEndpointResponseHeaderPrefix = "Res-Header"
)

const (
	scopeTagClientMethod    = "clientmethod"
	scopeTagEndpointMethod  = "endpointmethod"
	scopeTagClient          = "clientid"
	scopeTagEndpoint        = "endpointid"
	scopeTagHandler         = "handlerid"
	scopeTagError           = "error"
	scopeTagStatus          = "status"
	scopeTagProtocol        = "protocol"
	scopeTagHTTP            = "HTTP"
	scopeTagTChannel        = "TChannel"
	scopeTagsTargetService  = "targetservice"
	scopeTagsTargetEndpoint = "targetendpoint"
)

// WithEndpointField adds the endpoint information in the
// request context.
func WithEndpointField(ctx context.Context, endpoint string) context.Context {
	return context.WithValue(ctx, endpointKey, endpoint)
}

// GetRequestEndpointFromCtx returns the endpoint, if it exists on context
func GetRequestEndpointFromCtx(ctx context.Context) string {
	if val := ctx.Value(endpointKey); val != nil {
		endpoint, _ := val.(string)
		return endpoint
	}
	return ""
}

// WithEndpointRequestHeadersField adds the endpoint request header information in the
// request context.
func WithEndpointRequestHeadersField(ctx context.Context, requestHeaders map[string]string) context.Context {
	headers := GetEndpointRequestHeadersFromCtx(ctx)
	for k, v := range requestHeaders {
		headers[k] = v
	}

	return context.WithValue(ctx, endpointRequestHeader, headers)
}

// GetEndpointRequestHeadersFromCtx returns the endpoint request headers, if it exists on context
func GetEndpointRequestHeadersFromCtx(ctx context.Context) map[string]string {
	requestHeaders := make(map[string]string)
	if val := ctx.Value(endpointRequestHeader); val != nil {
		headers, _ := val.(map[string]string)
		for k, v := range headers {
			requestHeaders[k] = v
		}
	}

	return requestHeaders
}

// withRequestUUID returns a context with request uuid.
func withRequestUUID(ctx context.Context, reqUUID string) context.Context {
	return context.WithValue(ctx, requestUUIDKey, reqUUID)
}

// RequestUUIDFromCtx returns the RequestUUID, if it exists on context
func RequestUUIDFromCtx(ctx context.Context) string {
	if val := ctx.Value(requestUUIDKey); val != nil {
		uuid, _ := val.(string)
		return uuid
	}
	return ""
}

// WithRoutingDelegate adds the tchannel routing delegate information in the
// request context.
func WithRoutingDelegate(ctx context.Context, rd string) context.Context {
	return context.WithValue(ctx, routingDelegateKey, rd)
}

// GetRoutingDelegateFromCtx returns the tchannel routing delegate info
// extracted from context.
func GetRoutingDelegateFromCtx(ctx context.Context) string {
	if val := ctx.Value(routingDelegateKey); val != nil {
		rd, _ := val.(string)
		return rd
	}
	return ""
}

// GetShardKeyFromCtx returns the tchannel shardkey info
// extracted from context.
func GetShardKeyFromCtx(ctx context.Context) string {
	if val := ctx.Value(shardKey); val != nil {
		sk, _ := val.(string)
		return sk
	}
	return ""
}

// WithLogFields returns a new context with the given log fields attached to context.Context
func WithLogFields(ctx context.Context, newFields ...zap.Field) context.Context {
	return context.WithValue(ctx, requestLogFields, accumulateLogFields(ctx, newFields))
}

// GetLogFieldsFromCtx returns the log fields attached to the context.Context
func GetLogFieldsFromCtx(ctx context.Context) []zap.Field {
	var fields []zap.Field
	v := ctx.Value(requestLogFields)
	if v != nil {
		fields = v.([]zap.Field)
	}
	return fields
}

// WithScopeTags returns a new context with the given scope tags attached to context.Context
func WithScopeTags(ctx context.Context, newFields map[string]string) context.Context {
	tags := GetScopeTagsFromCtx(ctx)
	for k, v := range newFields {
		tags[k] = v
	}

	return context.WithValue(ctx, scopeTags, tags)
}

// GetScopeTagsFromCtx returns the tag info extracted from context.
func GetScopeTagsFromCtx(ctx context.Context) map[string]string {
	tags := make(map[string]string)
	if val := ctx.Value(scopeTags); val != nil {
		headers, _ := val.(map[string]string)
		for k, v := range headers {
			tags[k] = v
		}
	}

	return tags
}

func accumulateLogFields(ctx context.Context, newFields []zap.Field) []zap.Field {
	previousFields := GetLogFieldsFromCtx(ctx)
	return append(previousFields, newFields...)
}

// ContextExtractor is a extractor that extracts some log fields from the context
type ContextExtractor interface {
	ExtractScopeTags(ctx context.Context) map[string]string
	ExtractLogFields(ctx context.Context) []zap.Field
}

// ContextExtractors warps extractors for context, implements ContextExtractor interface
type ContextExtractors struct {
	ScopeTagsExtractors []ContextScopeTagsExtractor
	LogFieldsExtractors []ContextLogFieldsExtractor
}

// ExtractScopeTags extracts scope fields from a context into a tag.
func (c *ContextExtractors) ExtractScopeTags(ctx context.Context) map[string]string {
	tags := make(map[string]string)
	for _, fn := range c.ScopeTagsExtractors {
		sc := fn(ctx)
		for k, v := range sc {
			tags[k] = v
		}
	}

	return tags
}

// ExtractLogFields extracts log fields from a context into a field.
func (c *ContextExtractors) ExtractLogFields(ctx context.Context) []zap.Field {
	var fields []zap.Field
	for _, fn := range c.LogFieldsExtractors {
		logFields := fn(ctx)
		fields = append(fields, logFields...)
	}

	return fields
}

// ContextLogger is a logger that extracts some log fields from the context before passing through to underlying zap logger.
type ContextLogger interface {
	Debug(ctx context.Context, msg string, fields ...zap.Field)
	Error(ctx context.Context, msg string, fields ...zap.Field)
	Info(ctx context.Context, msg string, fields ...zap.Field)
	Panic(ctx context.Context, msg string, fields ...zap.Field)
	Warn(ctx context.Context, msg string, fields ...zap.Field)

	// Other utility methods on the logger
	Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry
}

// NewContextLogger returns a logger that extracts log fields a context before passing through to underlying zap logger.
func NewContextLogger(log *zap.Logger) ContextLogger {
	return &contextLogger{
		log: log,
	}
}

type contextLogger struct {
	log *zap.Logger
}

func (c *contextLogger) Debug(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Debug(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Error(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Error(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Info(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Info(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Panic(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Panic(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Warn(ctx context.Context, msg string, userFields ...zap.Field) {
	c.log.Warn(msg, accumulateLogFields(ctx, userFields)...)
}

func (c *contextLogger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
	return c.log.Check(lvl, msg)
}

// Logger is a generic logger interface that zap.Logger implements.
type Logger interface {
	Debug(msg string, fields ...zap.Field)
	Error(msg string, fields ...zap.Field)
	Info(msg string, fields ...zap.Field)
	Panic(msg string, fields ...zap.Field)
	Warn(msg string, fields ...zap.Field)
	Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry
}

// ContextMetrics emit metrics with tags extracted from context.
type ContextMetrics interface {
	IncCounter(ctx context.Context, name string, value int64)
	RecordTimer(ctx context.Context, name string, d time.Duration)
}

type contextMetrics struct {
	scope tally.Scope
}

// NewContextMetrics create ContextMetrics to emit metrics with tags extracted from context.
func NewContextMetrics(scope tally.Scope) ContextMetrics {
	return &contextMetrics{
		scope: scope,
	}
}

// IncCounter increments the counter with current tags from context
func (c *contextMetrics) IncCounter(ctx context.Context, name string, value int64) {
	tags := GetScopeTagsFromCtx(ctx)
	c.scope.Tagged(tags).Counter(name).Inc(value)
}

// RecordTimer records the duration with current tags from context
func (c *contextMetrics) RecordTimer(ctx context.Context, name string, d time.Duration) {
	tags := GetScopeTagsFromCtx(ctx)
	c.scope.Tagged(tags).Timer(name).Record(d)
}
<|endoftext|>


<commit_before>package runtime

import (
	"context"
	"encoding/base64"
	"fmt"
	"net"
	"net/http"
	"net/textproto"
	"strconv"
	"strings"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

// MetadataHeaderPrefix is the http prefix that represents custom metadata
// parameters to or from a gRPC call.
const MetadataHeaderPrefix = "Grpc-Metadata-"

// MetadataPrefix is prepended to permanent HTTP header keys (as specified
// by the IANA) when added to the gRPC context.
const MetadataPrefix = "grpcgateway-"

// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to
// HTTP headers in a response handled by grpc-gateway
const MetadataTrailerPrefix = "Grpc-Trailer-"

const metadataGrpcTimeout = "Grpc-Timeout"
const metadataHeaderBinarySuffix = "-Bin"

const xForwardedFor = "X-Forwarded-For"
const xForwardedHost = "X-Forwarded-Host"

var (
	// DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound
	// header isn't present. If the value is 0 the sent `context` will not have a timeout.
	DefaultContextTimeout = 0 * time.Second
)

type rpcMethodKey struct{}

func decodeBinHeader(v string) ([]byte, error) {
	if len(v)%4 == 0 {
		// Input was padded, or padding was not necessary.
		return base64.StdEncoding.DecodeString(v)
	}
	return base64.RawStdEncoding.DecodeString(v)
}

/*
AnnotateContext adds context information such as metadata from the request.

At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For",
except that the forwarded destination is not another HTTP service but rather
a gRPC service.
*/
func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, error) {
	ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName)
	if err != nil {
		return nil, err
	}
	if md == nil {
		return ctx, nil
	}

	return metadata.NewOutgoingContext(ctx, md), nil
}

// AnnotateIncomingContext adds context information such as metadata from the request.
// Attach metadata as incoming context.
func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, error) {
	ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName)
	if err != nil {
		return nil, err
	}
	if md == nil {
		return ctx, nil
	}

	return metadata.NewIncomingContext(ctx, md), nil
}

func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, metadata.MD, error) {
	ctx = withRPCMethod(ctx, rpcMethodName)
	var pairs []string
	timeout := DefaultContextTimeout
	if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
		var err error
		timeout, err = timeoutDecode(tm)
		if err != nil {
			return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
		}
	}

	for key, vals := range req.Header {
		for _, val := range vals {
			key = textproto.CanonicalMIMEHeaderKey(key)
			// For backwards-compatibility, pass through 'authorization' header with no prefix.
			if key == "Authorization" {
				pairs = append(pairs, "authorization", val)
			}
			if h, ok := mux.incomingHeaderMatcher(key); ok {
				// Handles "-bin" metadata in grpc, since grpc will do another base64
				// encode before sending to server, we need to decode it first.
				if strings.HasSuffix(key, metadataHeaderBinarySuffix) {
					b, err := decodeBinHeader(val)
					if err != nil {
						return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err)
					}

					val = string(b)
				}
				pairs = append(pairs, h, val)
			}
		}
	}
	if host := req.Header.Get(xForwardedHost); host != "" {
		pairs = append(pairs, strings.ToLower(xForwardedHost), host)
	} else if req.Host != "" {
		pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
	}

	if addr := req.RemoteAddr; addr != "" {
		if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
			if fwd := req.Header.Get(xForwardedFor); fwd == "" {
				pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP)
			} else {
				pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP))
			}
		} else {
			grpclog.Infof("invalid remote addr: %s", addr)
		}
	}

	if timeout != 0 {
		ctx, _ = context.WithTimeout(ctx, timeout)
	}
	if len(pairs) == 0 {
		return ctx, nil, nil
	}
	md := metadata.Pairs(pairs...)
	for _, mda := range mux.metadataAnnotators {
		md = metadata.Join(md, mda(ctx, req))
	}
	return ctx, md, nil
}

// ServerMetadata consists of metadata sent from gRPC server.
type ServerMetadata struct {
	HeaderMD  metadata.MD
	TrailerMD metadata.MD
}

type serverMetadataKey struct{}

// NewServerMetadataContext creates a new context with ServerMetadata
func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context {
	return context.WithValue(ctx, serverMetadataKey{}, md)
}

// ServerMetadataFromContext returns the ServerMetadata in ctx
func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) {
	md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata)
	return
}

func timeoutDecode(s string) (time.Duration, error) {
	size := len(s)
	if size < 2 {
		return 0, fmt.Errorf("timeout string is too short: %q", s)
	}
	d, ok := timeoutUnitToDuration(s[size-1])
	if !ok {
		return 0, fmt.Errorf("timeout unit is not recognized: %q", s)
	}
	t, err := strconv.ParseInt(s[:size-1], 10, 64)
	if err != nil {
		return 0, err
	}
	return d * time.Duration(t), nil
}

func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) {
	switch u {
	case 'H':
		return time.Hour, true
	case 'M':
		return time.Minute, true
	case 'S':
		return time.Second, true
	case 'm':
		return time.Millisecond, true
	case 'u':
		return time.Microsecond, true
	case 'n':
		return time.Nanosecond, true
	default:
	}
	return
}

// isPermanentHTTPHeader checks whether hdr belongs to the list of
// permanent request headers maintained by IANA.
// http://www.iana.org/assignments/message-headers/message-headers.xml
func isPermanentHTTPHeader(hdr string) bool {
	switch hdr {
	case
		"Accept",
		"Accept-Charset",
		"Accept-Language",
		"Accept-Ranges",
		"Authorization",
		"Cache-Control",
		"Content-Type",
		"Cookie",
		"Date",
		"Expect",
		"From",
		"Host",
		"If-Match",
		"If-Modified-Since",
		"If-None-Match",
		"If-Schedule-Tag-Match",
		"If-Unmodified-Since",
		"Max-Forwards",
		"Origin",
		"Pragma",
		"Referer",
		"User-Agent",
		"Via",
		"Warning":
		return true
	}
	return false
}

// RPCMethod returns the method string for the server context. The returned
// string is in the format of "/package.service/method".
func RPCMethod(ctx context.Context) (string, bool) {
	m := ctx.Value(rpcMethodKey{})
	if m == nil {
		return "", false
	}
	ms, ok := m.(string)
	if !ok {
		return "", false
	}
	return ms, true
}

func withRPCMethod(ctx context.Context, rpcMethodName string) context.Context {
	return context.WithValue(ctx, rpcMethodKey{}, rpcMethodName)
}
<commit_msg>Removed the "invalid remote addr" log (#1546)<commit_after>package runtime

import (
	"context"
	"encoding/base64"
	"fmt"
	"net"
	"net/http"
	"net/textproto"
	"strconv"
	"strings"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

// MetadataHeaderPrefix is the http prefix that represents custom metadata
// parameters to or from a gRPC call.
const MetadataHeaderPrefix = "Grpc-Metadata-"

// MetadataPrefix is prepended to permanent HTTP header keys (as specified
// by the IANA) when added to the gRPC context.
const MetadataPrefix = "grpcgateway-"

// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to
// HTTP headers in a response handled by grpc-gateway
const MetadataTrailerPrefix = "Grpc-Trailer-"

const metadataGrpcTimeout = "Grpc-Timeout"
const metadataHeaderBinarySuffix = "-Bin"

const xForwardedFor = "X-Forwarded-For"
const xForwardedHost = "X-Forwarded-Host"

var (
	// DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound
	// header isn't present. If the value is 0 the sent `context` will not have a timeout.
	DefaultContextTimeout = 0 * time.Second
)

type rpcMethodKey struct{}

func decodeBinHeader(v string) ([]byte, error) {
	if len(v)%4 == 0 {
		// Input was padded, or padding was not necessary.
		return base64.StdEncoding.DecodeString(v)
	}
	return base64.RawStdEncoding.DecodeString(v)
}

/*
AnnotateContext adds context information such as metadata from the request.

At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For",
except that the forwarded destination is not another HTTP service but rather
a gRPC service.
*/
func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, error) {
	ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName)
	if err != nil {
		return nil, err
	}
	if md == nil {
		return ctx, nil
	}

	return metadata.NewOutgoingContext(ctx, md), nil
}

// AnnotateIncomingContext adds context information such as metadata from the request.
// Attach metadata as incoming context.
func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, error) {
	ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName)
	if err != nil {
		return nil, err
	}
	if md == nil {
		return ctx, nil
	}

	return metadata.NewIncomingContext(ctx, md), nil
}

func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string) (context.Context, metadata.MD, error) {
	ctx = withRPCMethod(ctx, rpcMethodName)
	var pairs []string
	timeout := DefaultContextTimeout
	if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
		var err error
		timeout, err = timeoutDecode(tm)
		if err != nil {
			return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
		}
	}

	for key, vals := range req.Header {
		for _, val := range vals {
			key = textproto.CanonicalMIMEHeaderKey(key)
			// For backwards-compatibility, pass through 'authorization' header with no prefix.
			if key == "Authorization" {
				pairs = append(pairs, "authorization", val)
			}
			if h, ok := mux.incomingHeaderMatcher(key); ok {
				// Handles "-bin" metadata in grpc, since grpc will do another base64
				// encode before sending to server, we need to decode it first.
				if strings.HasSuffix(key, metadataHeaderBinarySuffix) {
					b, err := decodeBinHeader(val)
					if err != nil {
						return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err)
					}

					val = string(b)
				}
				pairs = append(pairs, h, val)
			}
		}
	}
	if host := req.Header.Get(xForwardedHost); host != "" {
		pairs = append(pairs, strings.ToLower(xForwardedHost), host)
	} else if req.Host != "" {
		pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
	}

	if addr := req.RemoteAddr; addr != "" {
		if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
			if fwd := req.Header.Get(xForwardedFor); fwd == "" {
				pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP)
			} else {
				pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP))
			}
		}
	}

	if timeout != 0 {
		ctx, _ = context.WithTimeout(ctx, timeout)
	}
	if len(pairs) == 0 {
		return ctx, nil, nil
	}
	md := metadata.Pairs(pairs...)
	for _, mda := range mux.metadataAnnotators {
		md = metadata.Join(md, mda(ctx, req))
	}
	return ctx, md, nil
}

// ServerMetadata consists of metadata sent from gRPC server.
type ServerMetadata struct {
	HeaderMD  metadata.MD
	TrailerMD metadata.MD
}

type serverMetadataKey struct{}

// NewServerMetadataContext creates a new context with ServerMetadata
func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context {
	return context.WithValue(ctx, serverMetadataKey{}, md)
}

// ServerMetadataFromContext returns the ServerMetadata in ctx
func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) {
	md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata)
	return
}

func timeoutDecode(s string) (time.Duration, error) {
	size := len(s)
	if size < 2 {
		return 0, fmt.Errorf("timeout string is too short: %q", s)
	}
	d, ok := timeoutUnitToDuration(s[size-1])
	if !ok {
		return 0, fmt.Errorf("timeout unit is not recognized: %q", s)
	}
	t, err := strconv.ParseInt(s[:size-1], 10, 64)
	if err != nil {
		return 0, err
	}
	return d * time.Duration(t), nil
}

func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) {
	switch u {
	case 'H':
		return time.Hour, true
	case 'M':
		return time.Minute, true
	case 'S':
		return time.Second, true
	case 'm':
		return time.Millisecond, true
	case 'u':
		return time.Microsecond, true
	case 'n':
		return time.Nanosecond, true
	default:
	}
	return
}

// isPermanentHTTPHeader checks whether hdr belongs to the list of
// permanent request headers maintained by IANA.
// http://www.iana.org/assignments/message-headers/message-headers.xml
func isPermanentHTTPHeader(hdr string) bool {
	switch hdr {
	case
		"Accept",
		"Accept-Charset",
		"Accept-Language",
		"Accept-Ranges",
		"Authorization",
		"Cache-Control",
		"Content-Type",
		"Cookie",
		"Date",
		"Expect",
		"From",
		"Host",
		"If-Match",
		"If-Modified-Since",
		"If-None-Match",
		"If-Schedule-Tag-Match",
		"If-Unmodified-Since",
		"Max-Forwards",
		"Origin",
		"Pragma",
		"Referer",
		"User-Agent",
		"Via",
		"Warning":
		return true
	}
	return false
}

// RPCMethod returns the method string for the server context. The returned
// string is in the format of "/package.service/method".
func RPCMethod(ctx context.Context) (string, bool) {
	m := ctx.Value(rpcMethodKey{})
	if m == nil {
		return "", false
	}
	ms, ok := m.(string)
	if !ok {
		return "", false
	}
	return ms, true
}

func withRPCMethod(ctx context.Context, rpcMethodName string) context.Context {
	return context.WithValue(ctx, rpcMethodKey{}, rpcMethodName)
}
<|endoftext|>


<commit_before>package api_test

import (
	"encoding/json"
	"errors"
	"github.com/gorilla/mux"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/t3hmrman/casgo/cas"
	"io/ioutil"
	"net/http"
)

var API_TEST_DATA map[string]string = map[string]string{
	"exampleAdminOnlyURI":   "/api/services",
	"exampleRegularUserURI": "/api/sessions",
	"userApiKey":            "userapikey",
	"userApiSecret":         "badsecret",
	"adminApiKey":           "adminapikey",
	"adminApiSecret":        "badsecret",
}

// List of tuples that describe all endpoints hierarchically
var EXPECTED_API_ENDPOINTS map[string][]StringTuple = map[string][]StringTuple{
	"/api/services": []StringTuple{
		StringTuple{"GET", "/api/services"},
		StringTuple{"POST", "/api/services"},
		StringTuple{"GET", "/api/services"},
		StringTuple{"POST", "/api/services"},
		StringTuple{"PUT", "/api/services/{servicename}"},
		StringTuple{"DELETE", "/api/services/{servicename}"},
	},
	"/api/sessions": []StringTuple{
		StringTuple{"GET", "/api/sessions/{userEmail}/services"},
		StringTuple{"GET", "/api/sessions"},
	},
}

func failRedirect(req *http.Request, via []*http.Request) error {
	Expect(req).To(BeNil())
	return errors.New("No redirects allowed")
}

// Utility function for performing JSON API requests
func jsonAPIRequestWithCustomHeaders(method, uri string, headers map[string]string) (*http.Client, *http.Request, map[string]interface{}) {
	client := &http.Client{
		CheckRedirect: failRedirect,
	}

	// Craft a request with api key and secret, popu
	req, err := http.NewRequest(method, uri, nil)
	for k, v := range headers {
		req.Header.Add(k, v)
	}

	// Perform request
	resp, err := client.Do(req)
	Expect(err).To(BeNil())

	// Read response body
	rawBody, err := ioutil.ReadAll(resp.Body)
	Expect(err).To(BeNil())

	// Parse response body into a map
	var respJSON map[string]interface{}
	err = json.Unmarshal(rawBody, &respJSON)
	Expect(err).To(BeNil())

	return client, req, respJSON
}

var _ = Describe("CasGo API", func() {

	Describe("#authenticateAPIUser", func() {
		It("Should fail for unauthenticated users", func() {
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(
				"GET",
				testHTTPServer.URL+API_TEST_DATA["exampleRegularUserURI"],
				map[string]string{},
			)
			Expect(respJSON["status"]).To(Equal("error"))
			Expect(respJSON["message"]).To(Equal(FailedToAuthenticateUserError.Msg))
		})

		It("Should properly authenticate a valid regular user's API key and secret to a non-admin-only endpoint", func() {
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(
				"GET",
				testHTTPServer.URL+API_TEST_DATA["exampleRegularUserURI"],
				map[string]string{
					"X-Api-Key":    API_TEST_DATA["userApiKey"],
					"X-Api-Secret": API_TEST_DATA["userApiSecret"],
				})
			Expect(respJSON["status"]).To(Equal("success"))
		})

		It("Should properly authenticate a valid admin user's API key and secret to an admin-only endpoint", func() {
			// Perform JSON API request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(
				"GET",
				testHTTPServer.URL+API_TEST_DATA["exampleAdminOnlyURI"],
				map[string]string{
					"X-Api-Key":    API_TEST_DATA["adminApiKey"],
					"X-Api-Secret": API_TEST_DATA["adminApiSecret"],
				})
			Expect(respJSON["status"]).To(Equal("success"))
		})

		It("Should fail to authenticate a regular user to an admin-only endpoint", func() {
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(
				"GET",
				testHTTPServer.URL+API_TEST_DATA["exampleAdminOnlyURI"],
				map[string]string{
					"X-Api-Key":    API_TEST_DATA["userApiKey"],
					"X-Api-Secret": API_TEST_DATA["userApiSecret"],
				})
			Expect(respJSON["status"]).To(Equal("error"))
			Expect(respJSON["message"]).To(Equal(InsufficientPermissionsError.Msg))
		})

	})

	Describe("#HookupAPIEndpoints", func() {
		It("Should hookup all /api/services endpoints", func() {
			testMux := mux.NewRouter()
			api, err := NewCasgoFrontendAPI(nil)
			api.HookupAPIEndpoints(testMux)
			Expect(err).To(BeNil())

			// Check all expected endpoints below "/api/services"
			var routeMatch mux.RouteMatch
			for _, tuple := range EXPECTED_API_ENDPOINTS["/api/services"] {
				// Craft request for listing services (GET /api/services)
				req, err := http.NewRequest(tuple.First(), tuple.Second(), nil)
				Expect(err).To(BeNil())

				// Get pattern that was matched
				Expect(testMux.Match(req, &routeMatch)).To(BeTrue())
			}
		})
	})

	Describe("#GetServices (GET /services)", func() {
		It("Should list all services for an admin user", func() {
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(
				"GET",
				testHTTPServer.URL+"/api/services",
				map[string]string{
					"X-Api-Key":    API_TEST_DATA["adminApiKey"],
					"X-Api-Secret": API_TEST_DATA["adminApiSecret"],
				},
			)
			Expect(respJSON["status"]).To(Equal("success"))

			// Get the list of services that was returned (dependent on fixture)
			var rawServicesList []interface{}
			Expect(respJSON["data"]).To(BeAssignableToTypeOf(rawServicesList))
			rawServicesList = respJSON["data"].([]interface{})
			Expect(len(rawServicesList)).To(Equal(1))

			// Check the map that represents the service
			var serviceMap map[string]interface{}
			Expect(rawServicesList[0]).To(BeAssignableToTypeOf(serviceMap))
			serviceMap = rawServicesList[0].(map[string]interface{})
			Expect(serviceMap["name"]).To(Equal("test_service"))
			Expect(serviceMap["url"]).To(Equal("localhost:3000/validateCASLogin"))
			Expect(serviceMap["adminEmail"]).To(Equal("admin@test.com"))
		})
	})

	// Describe("#CreateService (POST /services)", func() {
	//	It("Should create a service for an admin user", func() {})
	//	It("Should display an error for non-admin users", func() {})
	// })

	// Describe("#RemoveService (DELETE /services)", func() {
	//	It("Should create a service for an admin user", func() {})
	//	It("Should display an error for non-admin users", func() {})
	// })

	// Describe("#UpdateService (PUT /services)", func() {
	//	It("Should create a service for an admin user", func() {})
	//	It("Should display an error for non-admin users", func() {})
	// })

})
<commit_msg>Add tests for creating services through the API<commit_after>package api_test

import (
	"encoding/json"
	"errors"
	"github.com/gorilla/mux"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/t3hmrman/casgo/cas"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

var API_TEST_DATA map[string]string = map[string]string{
	"exampleAdminOnlyURI":   "/api/services",
	"exampleRegularUserURI": "/api/sessions",
	"userApiKey":            "userapikey",
	"userApiSecret":         "badsecret",
	"adminApiKey":           "adminapikey",
	"adminApiSecret":        "badsecret",
	"fakeServiceName":       "test_service_2",
	"fakeServiceUrl":        "localhost:3001/validateCASLogin",
	"fakeServiceAdminEmail": "admin@test.com",
}

// List of tuples that describe all endpoints hierarchically
var EXPECTED_API_ENDPOINTS map[string][]StringTuple = map[string][]StringTuple{
	"/api/services": []StringTuple{
		StringTuple{"GET", "/api/services"},
		StringTuple{"POST", "/api/services"},
		StringTuple{"GET", "/api/services"},
		StringTuple{"POST", "/api/services"},
		StringTuple{"PUT", "/api/services/{servicename}"},
		StringTuple{"DELETE", "/api/services/{servicename}"},
	},
	"/api/sessions": []StringTuple{
		StringTuple{"GET", "/api/sessions/{userEmail}/services"},
		StringTuple{"GET", "/api/sessions"},
	},
}

func failRedirect(req *http.Request, via []*http.Request) error {
	Expect(req).To(BeNil())
	return errors.New("No redirects allowed")
}

// Utility function for performing JSON API requests
func jsonAPIRequestWithCustomHeaders(req *http.Request) (*http.Client, *http.Request, map[string]interface{}) {
	client := &http.Client{
		CheckRedirect: failRedirect,
	}

	// Perform request
	resp, err := client.Do(req)
	Expect(err).To(BeNil())

	// Read response body
	rawBody, err := ioutil.ReadAll(resp.Body)
	Expect(err).To(BeNil())

	// Parse response body into a map
	var respJSON map[string]interface{}
	err = json.Unmarshal(rawBody, &respJSON)
	Expect(err).To(BeNil())

	return client, req, respJSON
}

var _ = Describe("CasGo API", func() {

	Describe("#authenticateAPIUser", func() {
		It("Should fail for unauthenticated users", func() {
			// Craft a request request
			req, err := http.NewRequest("GET", testHTTPServer.URL+API_TEST_DATA["exampleRegularUserURI"], nil)
			Expect(err).To(BeNil())

			// Perform request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON["status"]).To(Equal("error"))
			Expect(respJSON["message"]).To(Equal(FailedToAuthenticateUserError.Msg))
		})

		It("Should properly authenticate a valid regular user's API key and secret to a non-admin-only endpoint", func() {
			// Craft request with regular user's API key
			req, err := http.NewRequest("GET", testHTTPServer.URL+API_TEST_DATA["exampleRegularUserURI"], nil)
			Expect(err).To(BeNil())
			req.Header.Add("X-Api-Key", API_TEST_DATA["userApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["userApiSecret"])

			// Perform request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON["status"]).To(Equal("success"))
		})

		It("Should properly authenticate a valid admin user's API key and secret to an admin-only endpoint", func() {
			// Craft request with admin user's API key
			req, err := http.NewRequest("GET", testHTTPServer.URL+API_TEST_DATA["exampleAdminOnlyURI"], nil)
			Expect(err).To(BeNil())
			req.Header.Add("X-Api-Key", API_TEST_DATA["adminApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["adminApiSecret"])

			// Perform JSON API request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON["status"]).To(Equal("success"))
		})

		It("Should fail to authenticate a regular user to an admin-only endpoint", func() {
			// Craft request with regular user's API key
			req, err := http.NewRequest("GET", testHTTPServer.URL+API_TEST_DATA["exampleRegularUserURI"], nil)
			Expect(err).To(BeNil())
			req.Header.Add("X-Api-Key", API_TEST_DATA["userApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["userApiSecret"])

			// Perform JSON API request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON["status"]).To(Equal("error"))
			Expect(respJSON["message"]).To(Equal(InsufficientPermissionsError.Msg))
		})

	})

	Describe("#HookupAPIEndpoints", func() {
		It("Should hookup all /api/services endpoints", func() {
			testMux := mux.NewRouter()
			api, err := NewCasgoFrontendAPI(nil)
			api.HookupAPIEndpoints(testMux)
			Expect(err).To(BeNil())

			// Check all expected endpoints below "/api/services"
			var routeMatch mux.RouteMatch
			for _, tuple := range EXPECTED_API_ENDPOINTS["/api/services"] {
				// Craft request for listing services (GET /api/services)
				req, err := http.NewRequest(tuple.First(), tuple.Second(), nil)
				Expect(err).To(BeNil())

				// Get pattern that was matched
				Expect(testMux.Match(req, &routeMatch)).To(BeTrue())
			}
		})
	})

	Describe("#GetServices (GET /services)", func() {
		It("Should list all services for an admin user", func() {
			// Craft request with admin user's API key
			req, err := http.NewRequest("GET", testHTTPServer.URL+"/api/services", nil)
			Expect(err).To(BeNil())
			req.Header.Add("X-Api-Key", API_TEST_DATA["adminApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["adminApiSecret"])

			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON["status"]).To(Equal("success"))

			// Get the list of services that was returned (dependent on fixture)
			var rawServicesList []interface{}
			Expect(respJSON["data"]).To(BeAssignableToTypeOf(rawServicesList))
			rawServicesList = respJSON["data"].([]interface{})
			Expect(len(rawServicesList)).To(Equal(1))

			// Check the map that represents the service
			var serviceMap map[string]interface{}
			Expect(rawServicesList[0]).To(BeAssignableToTypeOf(serviceMap))
			serviceMap = rawServicesList[0].(map[string]interface{})
			Expect(serviceMap["name"]).To(Equal("test_service"))
			Expect(serviceMap["url"]).To(Equal("localhost:3000/validateCASLogin"))
			Expect(serviceMap["adminEmail"]).To(Equal("admin@test.com"))
		})
	})

	Describe("#CreateService (POST /services)", func() {
		It("Should fail to create a service given invalid input from an admin user", func() {
			// Craft request with admin user's API key
			req, err := http.NewRequest(
				"POST",
				testHTTPServer.URL+"/api/services",
				strings.NewReader(url.Values{"nope": {"nope"}}.Encode()),
			)
			Expect(err).To(BeNil())

			// Set header
			req.Header.Add("X-Api-Key", API_TEST_DATA["adminApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["adminApiSecret"])

			// Perform request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON).NotTo(BeNil())
			Expect(respJSON["status"]).To(Equal("error"))
			Expect(respJSON["message"]).To(Equal(InvalidServiceError.Msg))
		})

		It("Should successfully create a service given valid input from an admin user", func() {
			// Craft request with admin user's API key
			req, err := http.NewRequest(
				"POST",
				testHTTPServer.URL+"/api/services",
				strings.NewReader(
					url.Values{
						"name":       {API_TEST_DATA["fakeServiceName"]},
						"url":        {API_TEST_DATA["fakeServiceUrl"]},
						"adminEmail": {API_TEST_DATA["fakeServiceAdminEmail"]},
					}.Encode()),
			)
			Expect(err).To(BeNil())

			// Set header for request
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
			req.Header.Add("X-Api-Key", API_TEST_DATA["adminApiKey"])
			req.Header.Add("X-Api-Secret", API_TEST_DATA["adminApiSecret"])

			// Perform request
			_, _, respJSON := jsonAPIRequestWithCustomHeaders(req)
			Expect(respJSON).NotTo(BeNil())
			Expect(respJSON["status"]).To(Equal("success"))

			// Get the list of services that was returned (dependent on fixture)
			var newService map[string]interface{}
			Expect(respJSON["data"]).To(BeAssignableToTypeOf(newService))
			newService = respJSON["data"].(map[string]interface{})
			Expect(newService["name"]).To(Equal(API_TEST_DATA["fakeServiceName"]))
			Expect(newService["url"]).To(Equal(API_TEST_DATA["fakeServiceUrl"]))
			Expect(newService["adminEmail"]).To(Equal(API_TEST_DATA["fakeServiceAdminEmail"]))
		})

		//It("Should display an error for non-admin users", func() {})
	})

	// Describe("#RemoveService (DELETE /services)", func() {
	//	It("Should create a service for an admin user", func() {})
	//	It("Should display an error for non-admin users", func() {})
	// })

	// Describe("#UpdateService (PUT /services)", func() {
	//	It("Should create a service for an admin user", func() {})
	//	It("Should display an error for non-admin users", func() {})
	// })

})
<|endoftext|>


<commit_before>package eventmaster

import (
	"time"

	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	httpReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "http_server",
		Name:      "request_latency_ms",
		Help:      "Latency in ms of http requests grouped by req path",
		Buckets:   prometheus.ExponentialBuckets(1, 10, 10),
	}, []string{"path"})

	reqLatency = prometheus.NewSummaryVec(prometheus.SummaryOpts{
		Name: "http_request_latency_ms",
		Help: "http request duration (ms).",
	}, []string{"path"})

	httpReqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "http_server",
		Name:      "request_total",
		Help:      "The count of http requests received grouped by req path",
	}, []string{"path"})

	httpRespCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "http_server",
		Name:      "response_total",
		Help:      "The count of http responses issued classified by code and api endpoint",
	}, []string{"path", "code"})

	grpcReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "request_latency",
		Help:      "Latency of grpc requests grouped by method name",
	}, []string{"method"})

	grpcReqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "request_total",
		Help:      "The count of grpc requests received grouped by method name",
	}, []string{"method"})

	grpcRespCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "response_total",
		Help:      "The count of grpc responses issued classified by method name and success",
	}, []string{"method", "success"})

	rsyslogReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "rsyslog_server",
		Name:      "request_latency",
		Help:      "Latency of rsyslog requests",
	}, []string{})

	rsyslogReqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "rsyslog_server",
		Name:      "request_total",
		Help:      "The count of rsyslog requests received",
	}, []string{})

	eventStoreTimer = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "event_store",
		Name:      "method_time",
		Help:      "Time of event store methods by method name",
	}, []string{"method"})

	eventStoreDbErrCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "event_store",
		Name:      "db_error",
		Help:      "The count of db errors by db name and type of operation",
	}, []string{"db_name", "operation"})
)

// RegisterPromMetrics registers all the metrics that eventmanger uses.
func RegisterPromMetrics() error {
	regErr := prometheus.Register(httpReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			httpReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	if err := prometheus.Register(reqLatency); err != nil {
		return errors.Wrap(err, "registering request latency")
	}

	regErr = prometheus.Register(httpReqCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			httpReqCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(httpRespCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			httpRespCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcReqCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcReqCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcRespCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcRespCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(rsyslogReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			rsyslogReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(rsyslogReqCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			rsyslogReqCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(eventStoreTimer)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			eventStoreTimer = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(eventStoreDbErrCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			eventStoreDbErrCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}
	return nil
}

// msSince returns milliseconds since start.
func msSince(start time.Time) float64 {
	return float64(time.Since(start) / time.Millisecond)
}
<commit_msg>Remove http request counter<commit_after>package eventmaster

import (
	"time"

	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	httpReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "http_server",
		Name:      "request_latency_ms",
		Help:      "Latency in ms of http requests grouped by req path",
		Buckets:   prometheus.ExponentialBuckets(1, 10, 10),
	}, []string{"path"})

	reqLatency = prometheus.NewSummaryVec(prometheus.SummaryOpts{
		Name: "http_request_latency_ms",
		Help: "http request duration (ms).",
	}, []string{"path"})

	httpRespCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "http_server",
		Name:      "response_total",
		Help:      "The count of http responses issued classified by code and api endpoint",
	}, []string{"path", "code"})

	grpcReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "request_latency",
		Help:      "Latency of grpc requests grouped by method name",
	}, []string{"method"})

	grpcReqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "request_total",
		Help:      "The count of grpc requests received grouped by method name",
	}, []string{"method"})

	grpcRespCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "grpc_server",
		Name:      "response_total",
		Help:      "The count of grpc responses issued classified by method name and success",
	}, []string{"method", "success"})

	rsyslogReqLatencies = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "rsyslog_server",
		Name:      "request_latency",
		Help:      "Latency of rsyslog requests",
	}, []string{})

	rsyslogReqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "rsyslog_server",
		Name:      "request_total",
		Help:      "The count of rsyslog requests received",
	}, []string{})

	eventStoreTimer = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "eventmaster",
		Subsystem: "event_store",
		Name:      "method_time",
		Help:      "Time of event store methods by method name",
	}, []string{"method"})

	eventStoreDbErrCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "eventmaster",
		Subsystem: "event_store",
		Name:      "db_error",
		Help:      "The count of db errors by db name and type of operation",
	}, []string{"db_name", "operation"})
)

// RegisterPromMetrics registers all the metrics that eventmanger uses.
func RegisterPromMetrics() error {
	regErr := prometheus.Register(httpReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			httpReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	if err := prometheus.Register(reqLatency); err != nil {
		return errors.Wrap(err, "registering request latency")
	}

	regErr = prometheus.Register(httpRespCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			httpRespCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcReqCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcReqCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(grpcRespCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			grpcRespCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(rsyslogReqLatencies)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			rsyslogReqLatencies = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(rsyslogReqCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			rsyslogReqCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(eventStoreTimer)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			eventStoreTimer = c.ExistingCollector.(*prometheus.HistogramVec)
		} else {
			return regErr
		}
	}

	regErr = prometheus.Register(eventStoreDbErrCounter)
	if regErr != nil {
		if c, ok := regErr.(prometheus.AlreadyRegisteredError); ok {
			eventStoreDbErrCounter = c.ExistingCollector.(*prometheus.CounterVec)
		} else {
			return regErr
		}
	}
	return nil
}

// msSince returns milliseconds since start.
func msSince(start time.Time) float64 {
	return float64(time.Since(start) / time.Millisecond)
}
<|endoftext|>


<commit_before>package proxy

import (
	"fmt"
	"sync"

	cfg "github.com/tendermint/go-config"
	tmspcli "github.com/tendermint/tmsp/client"
	"github.com/tendermint/tmsp/example/dummy"
	nilapp "github.com/tendermint/tmsp/example/nil"
	"github.com/tendermint/tmsp/types"
)

// NewTMSPClient returns newly connected client
type ClientCreator interface {
	NewTMSPClient() (tmspcli.Client, error)
}

//----------------------------------------------------
// local proxy uses a mutex on an in-proc app

type localClientCreator struct {
	mtx *sync.Mutex
	app types.Application
}

func NewLocalClientCreator(app types.Application) ClientCreator {
	return &localClientCreator{
		mtx: new(sync.Mutex),
		app: app,
	}
}

func (l *localClientCreator) NewTMSPClient() (tmspcli.Client, error) {
	return tmspcli.NewLocalClient(l.mtx, l.app), nil
}

//---------------------------------------------------------------
// remote proxy opens new connections to an external app process

type remoteClientCreator struct {
	addr        string
	transport   string
	mustConnect bool
}

func NewRemoteClientCreator(addr, transport string, mustConnect bool) ClientCreator {
	return &remoteClientCreator{
		addr:        addr,
		transport:   transport,
		mustConnect: mustConnect,
	}
}

func (r *remoteClientCreator) NewTMSPClient() (tmspcli.Client, error) {
	// Run forever in a loop
	remoteApp, err := tmspcli.NewClient(r.addr, r.transport, r.mustConnect)
	if err != nil {
		return nil, fmt.Errorf("Failed to connect to proxy: %v", err)
	}
	return remoteApp, nil
}

//-----------------------------------------------------------------
// default

func DefaultClientCreator(config cfg.Config) ClientCreator {
	addr := config.GetString("proxy_app")
	transport := config.GetString("tmsp")

	switch addr {
	case "dummy":
		return NewLocalClientCreator(dummy.NewDummyApplication())
	case "nil":
		return NewLocalClientCreator(nilapp.NewNilApplication())
	default:
		mustConnect := true
		return NewRemoteClientCreator(addr, transport, mustConnect)
	}
}
<commit_msg>proxy: nil -> nilapp<commit_after>package proxy

import (
	"fmt"
	"sync"

	cfg "github.com/tendermint/go-config"
	tmspcli "github.com/tendermint/tmsp/client"
	"github.com/tendermint/tmsp/example/dummy"
	nilapp "github.com/tendermint/tmsp/example/nil"
	"github.com/tendermint/tmsp/types"
)

// NewTMSPClient returns newly connected client
type ClientCreator interface {
	NewTMSPClient() (tmspcli.Client, error)
}

//----------------------------------------------------
// local proxy uses a mutex on an in-proc app

type localClientCreator struct {
	mtx *sync.Mutex
	app types.Application
}

func NewLocalClientCreator(app types.Application) ClientCreator {
	return &localClientCreator{
		mtx: new(sync.Mutex),
		app: app,
	}
}

func (l *localClientCreator) NewTMSPClient() (tmspcli.Client, error) {
	return tmspcli.NewLocalClient(l.mtx, l.app), nil
}

//---------------------------------------------------------------
// remote proxy opens new connections to an external app process

type remoteClientCreator struct {
	addr        string
	transport   string
	mustConnect bool
}

func NewRemoteClientCreator(addr, transport string, mustConnect bool) ClientCreator {
	return &remoteClientCreator{
		addr:        addr,
		transport:   transport,
		mustConnect: mustConnect,
	}
}

func (r *remoteClientCreator) NewTMSPClient() (tmspcli.Client, error) {
	// Run forever in a loop
	fmt.Println("ADDR", r.addr, r.transport)
	remoteApp, err := tmspcli.NewClient(r.addr, r.transport, r.mustConnect)
	if err != nil {
		return nil, fmt.Errorf("Failed to connect to proxy: %v", err)
	}
	return remoteApp, nil
}

//-----------------------------------------------------------------
// default

func DefaultClientCreator(config cfg.Config) ClientCreator {
	addr := config.GetString("proxy_app")
	transport := config.GetString("tmsp")

	switch addr {
	case "dummy":
		return NewLocalClientCreator(dummy.NewDummyApplication())
	case "nilapp":
		return NewLocalClientCreator(nilapp.NewNilApplication())
	default:
		mustConnect := true
		return NewRemoteClientCreator(addr, transport, mustConnect)
	}
}
<|endoftext|>