<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"log"
	"net/http"
	"net/smtp"
	"net/url"
	"runtime"
	"strconv"
	"text/template"
	"time"
)

type flags struct {
	url        url.URL
	caption    string
	from_Gmail string
	to_mail    string
	password   string
}

func main() {

	runtime.GOMAXPROCS(runtime.NumCPU()*2 + 1)

	log.Printf("Hawk is flying...")

	f, err := getFlags()
	if err != nil {
		log.Fatalf("flags parsing fail: %v", err)
	}

	for {

		go func(url url.URL) {

			c := make(chan error, 1)
			go looking(url, c)

			t := time.Now()

			err := error(nil)

			select {

			case <-time.After(1 * time.Second):
				err = errors.New("timeout")

			case err = <-c:
				log.Printf("looking: " + time.Since(t).String())
			}

			if err != nil {
				log.Printf("result: %v", err)

				go sendGMail(f, err)
			}

		}(f.url)

		time.Sleep(time.Second * time.Duration(10))
	}
}

func getFlags() (flags, error) {

	// parse
	u := flag.String("u", "http://localhost:8080", "hawk url")
	c := flag.String("c", "cobra", "caption")
	f := flag.String("f", "sender@gmail.com", "gmail sender")
	t := flag.String("t", "receiver@example.com", "email receiver")
	p := flag.String("p", "123456", "gmail password")

	flag.Parse()

	// url
	ur, err := url.Parse(*u)
	if err != nil {
		return flags{}, err
	}

	// caption
	ca := *c

	// from_Gmail
	fr := *f

	// to_mail
	to := *t

	//password
	pw := *p

	return flags{*ur, ca, fr, to, pw}, nil
}

func looking(url url.URL, c chan error) {

	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		c <- err
		return
	}

	req.Header.Set("Connection", "close")
	req.Header.Set("User-Agent", "HawkEye")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		c <- err
		return
	}

	if err := resp.Body.Close(); err != nil {
		c <- err
		return
	}

	if resp.StatusCode != 200 {
		c <- errors.New("http resp: " + strconv.Itoa(resp.StatusCode) + " " + resp.Status)
		return
	}

	c <- nil
}

func sendGMail(f flags, e error) {

	auth := smtp.PlainAuth(
		"",
		f.from_Gmail,
		f.password,
		"smtp.gmail.com",
	)

	type SmtpTemplateData struct {
		From    string
		To      string
		Subject string
		Body    string
	}

	const emailTemplate = `From: {{.From}}
To: {{.To}}
Subject: {{.Subject}}

{{.Body}}
`

	var err error
	var doc bytes.Buffer

	context := &SmtpTemplateData{
		f.from_Gmail,
		f.to_mail,
		f.caption + " " + time.Now().Format("01/02 15:04:05"),
		e.Error(),
	}

	t := template.New("emailTemplate")
	t, err = t.Parse(emailTemplate)
	if err != nil {
		log.Printf("error trying to parse mail template")
		return
	}
	err = t.Execute(&doc, context)
	if err != nil {
		log.Printf("error trying to execute mail template")
		return
	}

	err = smtp.SendMail(
		"smtp.gmail.com:587",
		auth,
		f.from_Gmail,
		[]string{f.to_mail},
		doc.Bytes(),
	)
	if err != nil {
		log.Printf("smtp.SendMail err: " + err.Error())
		return
	}
}
<commit_msg>Send email after timout too.<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"log"
	"net/http"
	"net/smtp"
	"net/url"
	"runtime"
	"strconv"
	"text/template"
	"time"
)

type flags struct {
	url        url.URL
	caption    string
	from_Gmail string
	to_mail    string
	password   string
}

func main() {

	runtime.GOMAXPROCS(runtime.NumCPU()*2 + 1)

	log.Printf("Hawk is flying...")

	f, err := getFlags()
	if err != nil {
		log.Fatalf("flags parsing fail: %v", err)
	}

	for {

		go func(url url.URL) {

			c := make(chan error, 1)
			go looking(url, c)

			t := time.Now()

			err := error(nil)

			select {

			case <-time.After(1 * time.Second):
				err = errors.New("timeout")

			case err = <-c:
				log.Printf("looking: " + time.Since(t).String())
				close(c)
			}

			if err != nil {

				go sendGMail(f, err)
				log.Printf("result: %v", err)

				err, ok := <-c
				if ok {
					go sendGMail(f, err)
					log.Printf("result: %v", err)
				}
			}

		}(f.url)

		time.Sleep(time.Second * time.Duration(10))
	}
}

func getFlags() (flags, error) {

	// parse
	u := flag.String("u", "http://localhost:8080", "hawk url")
	c := flag.String("c", "cobra", "caption")
	f := flag.String("f", "sender@gmail.com", "gmail sender")
	t := flag.String("t", "receiver@example.com", "email receiver")
	p := flag.String("p", "123456", "gmail password")

	flag.Parse()

	// url
	ur, err := url.Parse(*u)
	if err != nil {
		return flags{}, err
	}

	// caption
	ca := *c

	// from_Gmail
	fr := *f

	// to_mail
	to := *t

	//password
	pw := *p

	return flags{*ur, ca, fr, to, pw}, nil
}

func looking(url url.URL, c chan error) {

	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		c <- err
		return
	}

	req.Header.Set("Connection", "close")
	req.Header.Set("User-Agent", "HawkEye")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		c <- err
		return
	}

	if err := resp.Body.Close(); err != nil {
		c <- err
		return
	}

	if resp.StatusCode != 200 {
		c <- errors.New("http resp: " + strconv.Itoa(resp.StatusCode) + " " + resp.Status)
		return
	}

	c <- nil
}

func sendGMail(f flags, e error) {

	auth := smtp.PlainAuth(
		"",
		f.from_Gmail,
		f.password,
		"smtp.gmail.com",
	)

	type SmtpTemplateData struct {
		From    string
		To      string
		Subject string
		Body    string
	}

	const emailTemplate = `From: {{.From}}
To: {{.To}}
Subject: {{.Subject}}

{{.Body}}
`

	var err error
	var doc bytes.Buffer

	context := &SmtpTemplateData{
		f.from_Gmail,
		f.to_mail,
		f.caption + " " + time.Now().Format("01/02 15:04:05"),
		e.Error(),
	}

	t := template.New("emailTemplate")
	t, err = t.Parse(emailTemplate)
	if err != nil {
		log.Printf("error trying to parse mail template")
		return
	}
	err = t.Execute(&doc, context)
	if err != nil {
		log.Printf("error trying to execute mail template")
		return
	}

	err = smtp.SendMail(
		"smtp.gmail.com:587",
		auth,
		f.from_Gmail,
		[]string{f.to_mail},
		doc.Bytes(),
	)
	if err != nil {
		log.Printf("smtp.SendMail err: " + err.Error())
		return
	}
}
<|endoftext|>


<commit_before>package ignition

const CloudProviderConf = `cloud: {{ .EnvironmentName }}
tenantId: {{ .TenantID }}
subscriptionId: {{ .SubscriptionID }}
resourceGroup: {{ .ResourceGroup }}
location: {{ .Location }}
{{- if not .UseManagedIdentityExtension }}
aadClientId: {{ .AADClientID }}
aadClientSecret: {{ .AADClientSecret }}
{{- end}}
primaryScaleSetName: {{ .PrimaryScaleSetName }}
subnetName: {{ .SubnetName }}
securityGroupName: {{ .SecurityGroupName }}
vnetName: {{ .VnetName }}
vmType: vmss
routeTableName: {{ .RouteTableName }}
useManagedIdentityExtension: {{ .UseManagedIdentityExtension }}
loadBalancerSku: standard
`
<commit_msg>Add rate limiting to cloud provider config (#581)<commit_after>package ignition

const CloudProviderConf = `cloud: {{ .EnvironmentName }}
tenantId: {{ .TenantID }}
subscriptionId: {{ .SubscriptionID }}
resourceGroup: {{ .ResourceGroup }}
location: {{ .Location }}
{{- if not .UseManagedIdentityExtension }}
aadClientId: {{ .AADClientID }}
aadClientSecret: {{ .AADClientSecret }}
{{- end}}
cloudProviderBackoff: true
cloudProviderBackoffRetries: 6
cloudProviderBackoffJitter: 1
cloudProviderBackoffDuration: 6
cloudProviderBackoffExponent: 1.5
cloudProviderRateLimit: true
cloudProviderRateLimitQPS: 3
cloudProviderRateLimitBucket: 10
cloudProviderRateLimitQPSWrite: 3
cloudProviderRateLimitBucketWrite: 10
primaryScaleSetName: {{ .PrimaryScaleSetName }}
subnetName: {{ .SubnetName }}
securityGroupName: {{ .SecurityGroupName }}
vnetName: {{ .VnetName }}
vmType: vmss
routeTableName: {{ .RouteTableName }}
useManagedIdentityExtension: {{ .UseManagedIdentityExtension }}
loadBalancerSku: standard
`
<|endoftext|>


<commit_before>package whetstone_test

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"

	"github.com/cloudfoundry-incubator/runtime-schema/models/factories"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var (
	diegoEdgeCli string
	tmpDir       string
)

var _ = BeforeSuite(func() {
	tmpDir = os.TempDir()

	var err error
	diegoEdgeCli, err = gexec.Build("github.com/pivotal-cf-experimental/diego-edge-cli")
	Expect(err).ToNot(HaveOccurred())
})

var _ = AfterSuite(func() {
	gexec.CleanupBuildArtifacts()
})

var _ = Describe("Diego Edge", func() {
	Context("when desiring a docker-based LRP", func() {

		var (
			appName string
			route   string
		)

		BeforeEach(func() {
			appName = fmt.Sprintf("whetstone-%s", factories.GenerateGuid())
			route = fmt.Sprintf("%s.%s", appName, domain)

			targetDiego(domain)
		})

		AfterEach(func() {
			stopApp(appName)

			Eventually(errorCheckForRoute(route), timeout, 1).Should(HaveOccurred())
		})

		It("eventually runs a docker app", func() {
			startDockerApp(appName)
			Eventually(errorCheckForRoute(route), timeout, 1).ShouldNot(HaveOccurred())

			logsStream := streamLogs(appName)
			Eventually(logsStream.Out, timeout).Should(gbytes.Say("WHETSTONE TEST APP. Says Hello Whetstone"))

			scaleApp(appName)

			instanceCountChan := make(chan int, numCpu)
			go countInstances(route, instanceCountChan)
			Eventually(instanceCountChan, timeout).Should(Receive(Equal(3)))

			logsStream.Terminate().Wait()
		})
	})

})

func startDockerApp(appName string) {
	command := command(diegoEdgeCli, "start", appName, "-i", "docker:///diegoedge/diego-edge-docker-app", "--env", "APP_NAME", "--", "/dockerapp", "--message", "Hello Whetstone")
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	Eventually(session, timeout).Should(gexec.Exit(0))

	Expect(session.Out).To(gbytes.Say(appName + " is now running."))
}

func streamLogs(appName string) *gexec.Session {
	command := command(diegoEdgeCli, "logs", appName)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).ToNot(HaveOccurred())

	return session
}

func scaleApp(appName string) {
	command := command(diegoEdgeCli, "scale", appName, "--instances", "3")
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	Eventually(session).Should(gexec.Exit(0))
}

func stopApp(appName string) {
	command := command(diegoEdgeCli, "stop", appName)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	Eventually(session).Should(gexec.Exit(0))
}

func targetDiego(domain string) {
	command := command(diegoEdgeCli, "target", domain)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	Eventually(session).Should(gexec.Exit(0))
}

func command(name string, arg ...string) *exec.Cmd {
	command := exec.Command(name, arg...)
	command.Env = []string{fmt.Sprintf("DIEGO_CLI_HOME=%s", tmpDir), "APP_NAME=WHETSTONE TEST APP"}
	return command
}

func errorCheckForRoute(route string) func() error {
	return func() error {
		response, err := makeGetRequestToRoute(route)
		if err != nil {
			return err
		}

		io.Copy(ioutil.Discard, response.Body)
		defer response.Body.Close()

		if response.StatusCode != 200 {
			return fmt.Errorf("Status code %d should be 200", response.StatusCode)
		}

		return nil
	}
}

func countInstances(route string, instanceCountChan chan<- int) {
	defer GinkgoRecover()
	instanceIndexRoute := fmt.Sprintf("%s/instance-index", route)
	instancesSeen := make(map[int]bool)

	instanceIndexChan := make(chan int, numCpu)

	for i := 0; i < numCpu; i++ {
		go pollForInstanceIndices(instanceIndexRoute, instanceIndexChan)
	}

	for {
		instanceIndex := <-instanceIndexChan
		instancesSeen[instanceIndex] = true
		instanceCountChan <- len(instancesSeen)
	}
}

func pollForInstanceIndices(route string, instanceIndexChan chan<- int) {
	defer GinkgoRecover()
	for {
		response, err := makeGetRequestToRoute(route)
		Expect(err).To(BeNil())

		responseBody, err := ioutil.ReadAll(response.Body)
		defer response.Body.Close()
		Expect(err).To(BeNil())

		instanceIndex, err := strconv.Atoi(string(responseBody))
		if err != nil {
			continue
		}
		instanceIndexChan <- instanceIndex
	}
}

func makeGetRequestToRoute(route string) (*http.Response, error) {
	routeWithScheme := fmt.Sprintf("http://%s", route)
	resp, err := http.DefaultClient.Get(routeWithScheme)
	if err != nil {
		return nil, err
	}

	return resp, nil
}
<commit_msg>Test cli commands end with a new line<commit_after>package whetstone_test

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"

	"github.com/cloudfoundry-incubator/runtime-schema/models/factories"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var (
	diegoEdgeCli string
	tmpDir       string
)

var _ = BeforeSuite(func() {
	tmpDir = os.TempDir()

	var err error
	diegoEdgeCli, err = gexec.Build("github.com/pivotal-cf-experimental/diego-edge-cli")
	Expect(err).ToNot(HaveOccurred())
})

var _ = AfterSuite(func() {
	gexec.CleanupBuildArtifacts()
})

var _ = Describe("Diego Edge", func() {
	Context("when desiring a docker-based LRP", func() {

		var (
			appName string
			route   string
		)

		BeforeEach(func() {
			appName = fmt.Sprintf("whetstone-%s", factories.GenerateGuid())
			route = fmt.Sprintf("%s.%s", appName, domain)

			targetDiego(domain)
		})

		AfterEach(func() {
			stopApp(appName)

			Eventually(errorCheckForRoute(route), timeout, 1).Should(HaveOccurred())
		})

		It("eventually runs a docker app", func() {
			startDockerApp(appName)
			Eventually(errorCheckForRoute(route), timeout, 1).ShouldNot(HaveOccurred())

			logsStream := streamLogs(appName)
			Eventually(logsStream.Out, timeout).Should(gbytes.Say("WHETSTONE TEST APP. Says Hello Whetstone"))

			scaleApp(appName)

			instanceCountChan := make(chan int, numCpu)
			go countInstances(route, instanceCountChan)
			Eventually(instanceCountChan, timeout).Should(Receive(Equal(3)))

			logsStream.Terminate().Wait()
		})
	})

})

func startDockerApp(appName string) {
	command := command(diegoEdgeCli, "start", appName, "-i", "docker:///diegoedge/diego-edge-docker-app", "--env", "APP_NAME", "--", "/dockerapp", "--message", "Hello Whetstone")
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	expectExit(session)

	Expect(session.Out).To(gbytes.Say(appName + " is now running."))
}

func streamLogs(appName string) *gexec.Session {
	command := command(diegoEdgeCli, "logs", appName)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).ToNot(HaveOccurred())

	return session
}

func scaleApp(appName string) {
	command := command(diegoEdgeCli, "scale", appName, "--instances", "3")
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	expectExit(session)
}

func stopApp(appName string) {
	command := command(diegoEdgeCli, "stop", appName)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	expectExit(session)
}

func targetDiego(domain string) {
	command := command(diegoEdgeCli, "target", domain)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)

	Expect(err).ToNot(HaveOccurred())
	expectExit(session)
}

func command(name string, arg ...string) *exec.Cmd {
	command := exec.Command(name, arg...)
	command.Env = []string{fmt.Sprintf("DIEGO_CLI_HOME=%s", tmpDir), "APP_NAME=WHETSTONE TEST APP"}
	return command
}

func errorCheckForRoute(route string) func() error {
	return func() error {
		response, err := makeGetRequestToRoute(route)
		if err != nil {
			return err
		}

		io.Copy(ioutil.Discard, response.Body)
		defer response.Body.Close()

		if response.StatusCode != 200 {
			return fmt.Errorf("Status code %d should be 200", response.StatusCode)
		}

		return nil
	}
}

func countInstances(route string, instanceCountChan chan<- int) {
	defer GinkgoRecover()
	instanceIndexRoute := fmt.Sprintf("%s/instance-index", route)
	instancesSeen := make(map[int]bool)

	instanceIndexChan := make(chan int, numCpu)

	for i := 0; i < numCpu; i++ {
		go pollForInstanceIndices(instanceIndexRoute, instanceIndexChan)
	}

	for {
		instanceIndex := <-instanceIndexChan
		instancesSeen[instanceIndex] = true
		instanceCountChan <- len(instancesSeen)
	}
}

func pollForInstanceIndices(route string, instanceIndexChan chan<- int) {
	defer GinkgoRecover()
	for {
		response, err := makeGetRequestToRoute(route)
		Expect(err).To(BeNil())

		responseBody, err := ioutil.ReadAll(response.Body)
		defer response.Body.Close()
		Expect(err).To(BeNil())

		instanceIndex, err := strconv.Atoi(string(responseBody))
		if err != nil {
			continue
		}
		instanceIndexChan <- instanceIndex
	}
}

func makeGetRequestToRoute(route string) (*http.Response, error) {
	routeWithScheme := fmt.Sprintf("http://%s", route)
	resp, err := http.DefaultClient.Get(routeWithScheme)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func expectExit(session *gexec.Session) {
	Eventually(session, timeout).Should(gexec.Exit(0))
	Expect(string(session.Out.Contents())).To(HaveSuffix("\n"))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	xc "github.com/dsvensson/go-xmmsclient/xmmsclient"
	"strings"
	"time"
)

func signal(client *xc.Client) {
	fmt.Println("Requesting playtime:")
	for {
		value, err := client.SignalPlaybackPlaytime()
		if err != nil {
			fmt.Println("Error(SignalPlaybackPlaytime):", err)
			return
		}
		fmt.Printf("Playtime: %d\n", value)
	}
}

func playlistChanges(client *xc.Client) {
	bcast := client.BroadcastPlaylistChanged()
	for {
		value, err := bcast.Next()
		if err != nil {
			fmt.Println("Error(PlaylistChanged):", err)
			return
		}
		fmt.Println(value)
	}
}

func repeat(client *xc.Client) {
	for {
		value, err := client.PlaylistListEntries(xc.ActivePlaylist)
		if err != nil {
			fmt.Println("Error(PlaylistListEntries):", err)
			return
		}
		for position, mid := range value {
			propDict, err := client.MedialibGetInfo(mid)
			if err != nil {
				fmt.Println("Error(GetInfo):", err)
				return
			}

			dict, err := xc.PropDictToDictDefault(propDict)
			if err != nil {
				fmt.Println("Error(PropDict->Dict):", err)
				return
			}

			fmt.Printf("repeat(): [%2d] %s // %s // %s\n",
				position, dict["artist"], dict["album"], dict["title"])
		}
		time.Sleep(time.Millisecond * 1500)
	}
}

func prettyPlayback(status xc.XmmsInt) {
	switch status {
	case xc.PlaybackStatusPlay:
		fmt.Println("Status: PLAYING")
	case xc.PlaybackStatusStop:
		fmt.Println("Status: STOPPED")
	case xc.PlaybackStatusPause:
		fmt.Println("Status: PAUSED")
	}
}

func main() {
	client := xc.NewClient("hello-from-go")

	clientId, err := client.Dial("localhost:xmms2")
	if err != nil {
		fmt.Println("Error(Dial):", err)
		return
	}

	go repeat(client)
	go playlistChanges(client)
	go signal(client)

	go func() {
		value, err := client.PlaybackStatus()
		if err != nil {
			fmt.Println("Error(PlaybackStatus):", err)
			return
		}
		prettyPlayback(value)

		bcast := client.BroadcastPlaybackStatus()
		for {
			value, err := bcast.Next()
			if err != nil {
				fmt.Println("Error(BroadcastPlaybackStatus):", err)
				return
			}
			prettyPlayback(value)
		}
	}()

	time.Sleep(time.Millisecond * 5)

	value, err := client.CollectionList(xc.NamespacePlaylists)
	if err != nil {
		fmt.Println("Error(CollectionList):", err)
		return
	}

	for index, name := range value {
		if !strings.HasPrefix(name, "_") {
			fmt.Printf("  main(): [%2v] %v::%v\n", index, xc.NamespacePlaylists, name)
		}
	}

	clients, err := client.CourierGetConnectedClients()
	if err != nil {
		fmt.Println("Error(CourierGetConnectedClients):", err)
		return
	}
	fmt.Println("Connected clients:", clients, "self:", clientId)

	coll := xc.XmmsColl{Type: xc.CollectionTypeUniverse}
	matches, err := client.CollectionQueryInfos(coll, 0, 0, []string{"artist", "album"}, []string{"album"})
	if err != nil {
		fmt.Println("Error(CollectionQueryInfos):", err)
		return
	}
	fmt.Println("All albums:", matches)

	time.Sleep(time.Second * 3)
	fmt.Println(" close():")
	client.Close()
	fmt.Println(" sleep():")
	time.Sleep(time.Second * 2)
}
<commit_msg>macOS doesn't recognize the xmms2 service port.<commit_after>package main

import (
	"fmt"
	xc "github.com/dsvensson/go-xmmsclient/xmmsclient"
	"strings"
	"time"
)

func signal(client *xc.Client) {
	fmt.Println("Requesting playtime:")
	for {
		value, err := client.SignalPlaybackPlaytime()
		if err != nil {
			fmt.Println("Error(SignalPlaybackPlaytime):", err)
			return
		}
		fmt.Printf("Playtime: %d\n", value)
	}
}

func playlistChanges(client *xc.Client) {
	bcast := client.BroadcastPlaylistChanged()
	for {
		value, err := bcast.Next()
		if err != nil {
			fmt.Println("Error(PlaylistChanged):", err)
			return
		}
		fmt.Println(value)
	}
}

func repeat(client *xc.Client) {
	for {
		value, err := client.PlaylistListEntries(xc.ActivePlaylist)
		if err != nil {
			fmt.Println("Error(PlaylistListEntries):", err)
			return
		}
		for position, mid := range value {
			propDict, err := client.MedialibGetInfo(mid)
			if err != nil {
				fmt.Println("Error(GetInfo):", err)
				return
			}

			dict, err := xc.PropDictToDictDefault(propDict)
			if err != nil {
				fmt.Println("Error(PropDict->Dict):", err)
				return
			}

			fmt.Printf("repeat(): [%2d] %s // %s // %s\n",
				position, dict["artist"], dict["album"], dict["title"])
		}
		time.Sleep(time.Millisecond * 1500)
	}
}

func prettyPlayback(status xc.XmmsInt) {
	switch status {
	case xc.PlaybackStatusPlay:
		fmt.Println("Status: PLAYING")
	case xc.PlaybackStatusStop:
		fmt.Println("Status: STOPPED")
	case xc.PlaybackStatusPause:
		fmt.Println("Status: PAUSED")
	}
}

func main() {
	client := xc.NewClient("hello-from-go")

	clientId, err := client.Dial("localhost:9667")
	if err != nil {
		fmt.Println("Error(Dial):", err)
		return
	}

	go repeat(client)
	go playlistChanges(client)
	go signal(client)

	go func() {
		value, err := client.PlaybackStatus()
		if err != nil {
			fmt.Println("Error(PlaybackStatus):", err)
			return
		}
		prettyPlayback(value)

		bcast := client.BroadcastPlaybackStatus()
		for {
			value, err := bcast.Next()
			if err != nil {
				fmt.Println("Error(BroadcastPlaybackStatus):", err)
				return
			}
			prettyPlayback(value)
		}
	}()

	time.Sleep(time.Millisecond * 5)

	value, err := client.CollectionList(xc.NamespacePlaylists)
	if err != nil {
		fmt.Println("Error(CollectionList):", err)
		return
	}

	for index, name := range value {
		if !strings.HasPrefix(name, "_") {
			fmt.Printf("  main(): [%2v] %v::%v\n", index, xc.NamespacePlaylists, name)
		}
	}

	clients, err := client.CourierGetConnectedClients()
	if err != nil {
		fmt.Println("Error(CourierGetConnectedClients):", err)
		return
	}
	fmt.Println("Connected clients:", clients, "self:", clientId)

	coll := xc.XmmsColl{Type: xc.CollectionTypeUniverse}
	matches, err := client.CollectionQueryInfos(coll, 0, 0, []string{"artist", "album"}, []string{"album"})
	if err != nil {
		fmt.Println("Error(CollectionQueryInfos):", err)
		return
	}
	fmt.Println("All albums:", matches)

	time.Sleep(time.Second * 3)
	fmt.Println(" close():")
	client.Close()
	fmt.Println(" sleep():")
	time.Sleep(time.Second * 2)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/basho-labs/riak-mesos/cepmd/cepm"
	"github.com/basho-labs/riak-mesos/common"
	metamgr "github.com/basho-labs/riak-mesos/metadata_manager"
	"github.com/basho-labs/riak-mesos/process_manager"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"text/template"
	"time"
)

type RiakNode struct {
	executor        *ExecutorCore
	taskInfo        *mesos.TaskInfo
	generation      uint64
	finishChan      chan interface{}
	running         bool
	metadataManager *metamgr.MetadataManager
	taskData        common.TaskData
	pm              *process_manager.ProcessManager
}

type templateData struct {
	HTTPPort               int64
	PBPort                 int64
	HandoffPort            int64
	FullyQualifiedNodeName string
	DisterlPort            int64
}

type advancedTemplateData struct {
	CEPMDPort int
}

func NewRiakNode(taskInfo *mesos.TaskInfo, executor *ExecutorCore) *RiakNode {
	taskData, err := common.DeserializeTaskData(taskInfo.Data)
	if err != nil {
		log.Panic("Got error", err)
	}

	log.Infof("Deserialized task data: %+v", taskData)
	mgr := metamgr.NewMetadataManager(executor.fwInfo.GetId().GetValue(), taskData.Zookeepers)

	return &RiakNode{

		executor:        executor,
		taskInfo:        taskInfo,
		running:         false,
		metadataManager: mgr,
		taskData:        taskData,
	}
}

func portIter(resources []*mesos.Resource) chan int64 {
	ports := make(chan int64)
	go func() {
		defer close(ports)
		for _, resource := range util.FilterResources(resources, func(res *mesos.Resource) bool { return res.GetName() == "ports" }) {
			for _, port := range common.RangesToArray(resource.GetRanges().GetRange()) {
				ports <- port
			}
		}
	}()
	return ports
}
func (riakNode *RiakNode) runLoop(child *metamgr.ZkNode) {

	runStatus := &mesos.TaskStatus{
		TaskId: riakNode.taskInfo.GetTaskId(),
		State:  mesos.TaskState_TASK_RUNNING.Enum(),
	}
	_, err := riakNode.executor.Driver.SendStatusUpdate(runStatus)
	if err != nil {
		log.Panic("Got error", err)
	}

	waitChan := riakNode.pm.Listen()
	select {
	case <-waitChan:
		{
			log.Info("Riak Died, failing")
			// Just in case, cleanup
			// This means the node died :(
			runStatus = &mesos.TaskStatus{
				TaskId: riakNode.taskInfo.GetTaskId(),
				State:  mesos.TaskState_TASK_FAILED.Enum(),
			}
			_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
			if err != nil {
				log.Panic("Got error", err)
			}
		}
	case <-riakNode.finishChan:
		{
			log.Info("Finish channel says to shut down Riak")
			riakNode.pm.TearDown()
			runStatus = &mesos.TaskStatus{
				TaskId: riakNode.taskInfo.GetTaskId(),
				State:  mesos.TaskState_TASK_FINISHED.Enum(),
			}
			_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
			if err != nil {
				log.Panic("Got error", err)
			}
		}
	}
	child.Delete()
	time.Sleep(15 * time.Second)
	log.Info("Shutting down")
	riakNode.executor.Driver.Stop()

}
func (riakNode *RiakNode) configureRiak(ports chan int64) templateData {

	data, err := Asset("data/riak.conf")
	if err != nil {
		log.Panic("Got error", err)
	}
	tmpl, err := template.New("test").Parse(string(data))

	if err != nil {
		log.Panic(err)
	}

	// Populate template data from the MesosTask
	vars := templateData{}
	vars.FullyQualifiedNodeName = riakNode.taskData.FullyQualifiedNodeName

	vars.HTTPPort = <-ports
	vars.PBPort = <-ports
	vars.HandoffPort = <-ports
	vars.DisterlPort = <-ports

	file, err := os.OpenFile("riak/etc/riak.conf", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0664)

	defer file.Close()
	if err != nil {
		log.Panic("Unable to open file: ", err)
	}

	err = tmpl.Execute(file, vars)

	if err != nil {
		log.Panic("Got error", err)
	}
	return vars
}
func (riakNode *RiakNode) configureAdvanced(cepmdPort int) {

	data, err := Asset("data/advanced.config")
	if err != nil {
		log.Panic("Got error", err)
	}
	tmpl, err := template.New("advanced").Parse(string(data))

	if err != nil {
		log.Panic(err)
	}

	// Populate template data from the MesosTask
	vars := advancedTemplateData{}
	vars.CEPMDPort = cepmdPort
	file, err := os.OpenFile("riak/etc/advanced.config", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0664)

	defer file.Close()
	if err != nil {
		log.Panic("Unable to open file: ", err)
	}

	err = tmpl.Execute(file, vars)

	if err != nil {
		log.Panic("Got error", err)
	}
}
func (riakNode *RiakNode) Run() {

	var err error
	log.Info("Other hilarious facts: ", riakNode.taskInfo)

	ports := portIter(riakNode.taskInfo.Resources)
	config := riakNode.configureRiak(ports)

	c := cepm.NewCPMd(0, riakNode.metadataManager)
	c.Background()
	riakNode.configureAdvanced(c.GetPort())

	args := []string{"console", "-noinput"}

	err = cepm.InstallInto("riak/lib/kernel-2.16.4/ebin")
	if err != nil {
		log.Panic(err)
	}
	args = append(args, "-no_epmd")
	os.MkdirAll("riak/lib/kernel-2.16.4/priv", 0777)
	ioutil.WriteFile("riak/lib/kernel-2.16.4/priv/cepmd_port", []byte(fmt.Sprintf("%d.", c.GetPort())), 0777)

	HealthCheckFun := func() error {
		process := exec.Command("/usr/bin/timeout", "--kill-after=5s", "--signal=TERM", "5s", "riak/bin/riak-admin", "wait-for-service", "riak_kv")
		process.Stdout = os.Stdout
		process.Stderr = os.Stderr

		wd, err := os.Getwd()
		if err != nil {
			log.Fatal("Could not get current working directory")
		}
		home := filepath.Join(wd, "riak/data")
		homevar := fmt.Sprintf("HOME=%s", home)
		process.Env = append(os.Environ(), homevar)
		process.Env = append(process.Env, "NO_EPMD=1")
		process.Env = append(process.Env, fmt.Sprintf("CEPMD_PORT=%d", c.GetPort()))
		return process.Run()
	}
	riakNode.pm, err = process_manager.NewProcessManager(func() { return }, "riak/bin/riak", args, HealthCheckFun)

	if err != nil {
		log.Error("Could not start Riak: ", err)

		runStatus := &mesos.TaskStatus{
			TaskId: riakNode.taskInfo.GetTaskId(),
			State:  mesos.TaskState_TASK_FAILED.Enum(),
		}
		_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
		if err != nil {
			log.Panic("Got error", err)
		}
		// Shutdown:
		time.Sleep(15 * time.Minute)
		log.Info("Shutting down due to GC, after failing to bring up Riak node")
		riakNode.executor.Driver.Stop()
	} else {
		rootNode := riakNode.metadataManager.GetRootNode()

		clustersNode, err := rootNode.GetChild("clusters")
		if err != nil {
			log.Panic(err)
		}
		clusterNode, err := clustersNode.GetChild(riakNode.taskData.ClusterName)
		if err != nil {
			log.Panic(err)
		}

		clusterNode.CreateChildIfNotExists("coordinator")
		coordinator, err := clusterNode.GetChild("coordinator")
		if err != nil {
			log.Panic(err)
		}
		coordinator.CreateChildIfNotExists("coordinatedNodes")
		coordinatedNodes, err := coordinator.GetChild("coordinatedNodes")
		if err != nil {
			log.Panic(err)
		}

		// The following is commented out as part of experimenting with moving REX
		// to the scheduler as opposed to running in the executors
		// It used to coordinate the cluster join action.

		// lock := coordinator.GetLock()
		// lock.Lock()
		// Do cluster joiny stuff

		child, err := coordinatedNodes.MakeChild(riakNode.taskInfo.GetTaskId().GetValue(), true)
		if err != nil {
			log.Panic(err)
		}
		coordinatedData := common.CoordinatedData{
			NodeName:    riakNode.taskData.FullyQualifiedNodeName,
			DisterlPort: int(config.DisterlPort),
			PBPort:      int(config.PBPort),
			HTTPPort:    int(config.HTTPPort),
			Hostname:    riakNode.executor.slaveInfo.GetHostname(),
		}
		cdBytes, err := coordinatedData.Serialize()
		if err != nil {
			log.Panic("Could not serialize coordinated data	", err)
		}
		child.SetData(cdBytes)
		// lock.Unlock()

		runStatus := &mesos.TaskStatus{
			TaskId: riakNode.taskInfo.GetTaskId(),
			State:  mesos.TaskState_TASK_RUNNING.Enum(),
		}
		_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
		if err != nil {
			log.Panic("Got error", err)
		}
		riakNode.running = true
		go riakNode.runLoop(child)
	}
}

func (riakNode *RiakNode) next() {
	riakNode.executor.lock.Lock()
	defer riakNode.executor.lock.Unlock()
	bin := make([]byte, 4)
	binary.PutUvarint(bin, riakNode.generation)
	runStatus := &mesos.TaskStatus{
		TaskId: riakNode.taskInfo.GetTaskId(),
		State:  mesos.TaskState_TASK_RUNNING.Enum(),
		Data:   bin,
	}
	_, err := riakNode.executor.Driver.SendStatusUpdate(runStatus)
	if err != nil {
		log.Panic("Got error", err)
	}
	riakNode.generation = riakNode.generation + 1
}

func (riakNode *RiakNode) finish() {
	riakNode.finishChan <- nil
}
<commit_msg>making kernerl directory generic for different builds in the future<commit_after>package main

import (
	"encoding/binary"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"text/template"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/basho-labs/riak-mesos/cepmd/cepm"
	"github.com/basho-labs/riak-mesos/common"
	metamgr "github.com/basho-labs/riak-mesos/metadata_manager"
	"github.com/basho-labs/riak-mesos/process_manager"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
)

type RiakNode struct {
	executor        *ExecutorCore
	taskInfo        *mesos.TaskInfo
	generation      uint64
	finishChan      chan interface{}
	running         bool
	metadataManager *metamgr.MetadataManager
	taskData        common.TaskData
	pm              *process_manager.ProcessManager
}

type templateData struct {
	HTTPPort               int64
	PBPort                 int64
	HandoffPort            int64
	FullyQualifiedNodeName string
	DisterlPort            int64
}

type advancedTemplateData struct {
	CEPMDPort int
}

func NewRiakNode(taskInfo *mesos.TaskInfo, executor *ExecutorCore) *RiakNode {
	taskData, err := common.DeserializeTaskData(taskInfo.Data)
	if err != nil {
		log.Panic("Got error", err)
	}

	log.Infof("Deserialized task data: %+v", taskData)
	mgr := metamgr.NewMetadataManager(executor.fwInfo.GetId().GetValue(), taskData.Zookeepers)

	return &RiakNode{

		executor:        executor,
		taskInfo:        taskInfo,
		running:         false,
		metadataManager: mgr,
		taskData:        taskData,
	}
}

func portIter(resources []*mesos.Resource) chan int64 {
	ports := make(chan int64)
	go func() {
		defer close(ports)
		for _, resource := range util.FilterResources(resources, func(res *mesos.Resource) bool { return res.GetName() == "ports" }) {
			for _, port := range common.RangesToArray(resource.GetRanges().GetRange()) {
				ports <- port
			}
		}
	}()
	return ports
}
func (riakNode *RiakNode) runLoop(child *metamgr.ZkNode) {

	runStatus := &mesos.TaskStatus{
		TaskId: riakNode.taskInfo.GetTaskId(),
		State:  mesos.TaskState_TASK_RUNNING.Enum(),
	}
	_, err := riakNode.executor.Driver.SendStatusUpdate(runStatus)
	if err != nil {
		log.Panic("Got error", err)
	}

	waitChan := riakNode.pm.Listen()
	select {
	case <-waitChan:
		{
			log.Info("Riak Died, failing")
			// Just in case, cleanup
			// This means the node died :(
			runStatus = &mesos.TaskStatus{
				TaskId: riakNode.taskInfo.GetTaskId(),
				State:  mesos.TaskState_TASK_FAILED.Enum(),
			}
			_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
			if err != nil {
				log.Panic("Got error", err)
			}
		}
	case <-riakNode.finishChan:
		{
			log.Info("Finish channel says to shut down Riak")
			riakNode.pm.TearDown()
			runStatus = &mesos.TaskStatus{
				TaskId: riakNode.taskInfo.GetTaskId(),
				State:  mesos.TaskState_TASK_FINISHED.Enum(),
			}
			_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
			if err != nil {
				log.Panic("Got error", err)
			}
		}
	}
	child.Delete()
	time.Sleep(15 * time.Second)
	log.Info("Shutting down")
	riakNode.executor.Driver.Stop()

}
func (riakNode *RiakNode) configureRiak(ports chan int64) templateData {

	data, err := Asset("data/riak.conf")
	if err != nil {
		log.Panic("Got error", err)
	}
	tmpl, err := template.New("test").Parse(string(data))

	if err != nil {
		log.Panic(err)
	}

	// Populate template data from the MesosTask
	vars := templateData{}
	vars.FullyQualifiedNodeName = riakNode.taskData.FullyQualifiedNodeName

	vars.HTTPPort = <-ports
	vars.PBPort = <-ports
	vars.HandoffPort = <-ports
	vars.DisterlPort = <-ports

	file, err := os.OpenFile("riak/etc/riak.conf", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0664)

	defer file.Close()
	if err != nil {
		log.Panic("Unable to open file: ", err)
	}

	err = tmpl.Execute(file, vars)

	if err != nil {
		log.Panic("Got error", err)
	}
	return vars
}
func (riakNode *RiakNode) configureAdvanced(cepmdPort int) {

	data, err := Asset("data/advanced.config")
	if err != nil {
		log.Panic("Got error", err)
	}
	tmpl, err := template.New("advanced").Parse(string(data))

	if err != nil {
		log.Panic(err)
	}

	// Populate template data from the MesosTask
	vars := advancedTemplateData{}
	vars.CEPMDPort = cepmdPort
	file, err := os.OpenFile("riak/etc/advanced.config", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0664)

	defer file.Close()
	if err != nil {
		log.Panic("Unable to open file: ", err)
	}

	err = tmpl.Execute(file, vars)

	if err != nil {
		log.Panic("Got error", err)
	}
}
func (riakNode *RiakNode) Run() {

	var err error
	log.Info("Other hilarious facts: ", riakNode.taskInfo)

	ports := portIter(riakNode.taskInfo.Resources)
	config := riakNode.configureRiak(ports)

	c := cepm.NewCPMd(0, riakNode.metadataManager)
	c.Background()
	riakNode.configureAdvanced(c.GetPort())

	args := []string{"console", "-noinput"}

	kernelDirs, err := filepath.Glob("riak/lib/kernel*")
	if err != nil {
		log.Fatal("Could not find kernel directory")
	}

	log.Infof("Found kernel dirs: %v", kernelDirs)

	err = cepm.InstallInto(fmt.Sprint(kernelDirs[0], "/ebin"))
	if err != nil {
		log.Panic(err)
	}
	args = append(args, "-no_epmd")
	os.MkdirAll(fmt.Sprint(kernelDirs[0], "/priv"), 0777)
	ioutil.WriteFile(fmt.Sprint(kernelDirs[0], "/priv/cepmd_port"), []byte(fmt.Sprintf("%d.", c.GetPort())), 0777)

	HealthCheckFun := func() error {
		process := exec.Command("/usr/bin/timeout", "--kill-after=5s", "--signal=TERM", "5s", "riak/bin/riak-admin", "wait-for-service", "riak_kv")
		process.Stdout = os.Stdout
		process.Stderr = os.Stderr

		wd, err := os.Getwd()
		if err != nil {
			log.Fatal("Could not get current working directory")
		}
		home := filepath.Join(wd, "riak/data")
		homevar := fmt.Sprintf("HOME=%s", home)
		process.Env = append(os.Environ(), homevar)
		process.Env = append(process.Env, "NO_EPMD=1")
		process.Env = append(process.Env, fmt.Sprintf("CEPMD_PORT=%d", c.GetPort()))
		return process.Run()
	}
	riakNode.pm, err = process_manager.NewProcessManager(func() { return }, "riak/bin/riak", args, HealthCheckFun)

	if err != nil {
		log.Error("Could not start Riak: ", err)

		runStatus := &mesos.TaskStatus{
			TaskId: riakNode.taskInfo.GetTaskId(),
			State:  mesos.TaskState_TASK_FAILED.Enum(),
		}
		_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
		if err != nil {
			log.Panic("Got error", err)
		}
		// Shutdown:
		time.Sleep(15 * time.Minute)
		log.Info("Shutting down due to GC, after failing to bring up Riak node")
		riakNode.executor.Driver.Stop()
	} else {
		rootNode := riakNode.metadataManager.GetRootNode()

		clustersNode, err := rootNode.GetChild("clusters")
		if err != nil {
			log.Panic(err)
		}
		clusterNode, err := clustersNode.GetChild(riakNode.taskData.ClusterName)
		if err != nil {
			log.Panic(err)
		}

		clusterNode.CreateChildIfNotExists("coordinator")
		coordinator, err := clusterNode.GetChild("coordinator")
		if err != nil {
			log.Panic(err)
		}
		coordinator.CreateChildIfNotExists("coordinatedNodes")
		coordinatedNodes, err := coordinator.GetChild("coordinatedNodes")
		if err != nil {
			log.Panic(err)
		}

		// The following is commented out as part of experimenting with moving REX
		// to the scheduler as opposed to running in the executors
		// It used to coordinate the cluster join action.

		// lock := coordinator.GetLock()
		// lock.Lock()
		// Do cluster joiny stuff

		child, err := coordinatedNodes.MakeChild(riakNode.taskInfo.GetTaskId().GetValue(), true)
		if err != nil {
			log.Panic(err)
		}
		coordinatedData := common.CoordinatedData{
			NodeName:    riakNode.taskData.FullyQualifiedNodeName,
			DisterlPort: int(config.DisterlPort),
			PBPort:      int(config.PBPort),
			HTTPPort:    int(config.HTTPPort),
			Hostname:    riakNode.executor.slaveInfo.GetHostname(),
		}
		cdBytes, err := coordinatedData.Serialize()
		if err != nil {
			log.Panic("Could not serialize coordinated data	", err)
		}
		child.SetData(cdBytes)
		// lock.Unlock()

		runStatus := &mesos.TaskStatus{
			TaskId: riakNode.taskInfo.GetTaskId(),
			State:  mesos.TaskState_TASK_RUNNING.Enum(),
		}
		_, err = riakNode.executor.Driver.SendStatusUpdate(runStatus)
		if err != nil {
			log.Panic("Got error", err)
		}
		riakNode.running = true
		go riakNode.runLoop(child)
	}
}

func (riakNode *RiakNode) next() {
	riakNode.executor.lock.Lock()
	defer riakNode.executor.lock.Unlock()
	bin := make([]byte, 4)
	binary.PutUvarint(bin, riakNode.generation)
	runStatus := &mesos.TaskStatus{
		TaskId: riakNode.taskInfo.GetTaskId(),
		State:  mesos.TaskState_TASK_RUNNING.Enum(),
		Data:   bin,
	}
	_, err := riakNode.executor.Driver.SendStatusUpdate(runStatus)
	if err != nil {
		log.Panic("Got error", err)
	}
	riakNode.generation = riakNode.generation + 1
}

func (riakNode *RiakNode) finish() {
	riakNode.finishChan <- nil
}
<|endoftext|>


<commit_before>package metrics_test

import (
	"errors"
	"time"

	"code.cloudfoundry.org/clock/fakeclock"
	mfakes "code.cloudfoundry.org/diego-logging-client/testhelpers"
	loggregator "code.cloudfoundry.org/go-loggregator"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"
	"code.cloudfoundry.org/locket/db/dbfakes"
	"code.cloudfoundry.org/locket/metrics"
	"code.cloudfoundry.org/locket/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("LockMetrics", func() {
	type FakeGauge struct {
		Name  string
		Value int
	}

	var (
		runner           ifrit.Runner
		process          ifrit.Process
		fakeMetronClient *mfakes.FakeIngressClient
		logger           *lagertest.TestLogger
		fakeClock        *fakeclock.FakeClock
		metricsInterval  time.Duration
		lockDB           *dbfakes.FakeLockDB
		metricsChan      chan FakeGauge
	)

	metricsChan = make(chan FakeGauge, 100)

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("metrics")
		fakeMetronClient = new(mfakes.FakeIngressClient)
		fakeClock = fakeclock.NewFakeClock(time.Now())
		metricsInterval = 10 * time.Second

		lockDB = &dbfakes.FakeLockDB{}

		lockDB.CountStub = func(l lager.Logger, lockType string) (int, error) {
			switch {
			case lockType == models.LockType:
				return 3, nil
			case lockType == models.PresenceType:
				return 2, nil
			default:
				return 0, errors.New("unknown type")
			}
		}

		fakeMetronClient.SendMetricStub = func(name string, value int, opts ...loggregator.EmitGaugeOption) error {
			defer GinkgoRecover()

			Eventually(metricsChan).Should(BeSent(FakeGauge{name, value}))
			return nil
		}
	})

	JustBeforeEach(func() {
		runner = metrics.NewLockMetricsNotifier(
			logger,
			fakeClock,
			fakeMetronClient,
			metricsInterval,
			lockDB,
		)
		process = ifrit.Background(runner)
		Eventually(process.Ready()).Should(BeClosed())
	})

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

	Context("when there are no errors retrieving counts from database", func() {

		JustBeforeEach(func() {
			fakeClock.Increment(metricsInterval)
		})

		It("emits a metric for the number of active locks", func() {
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActiveLocks", 3})))
			fakeClock.Increment(metricsInterval)
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActiveLocks", 3})))
		})

		It("emits a metric for the number of active presences", func() {
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActivePresences", 2})))
			fakeClock.Increment(metricsInterval)
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActivePresences", 2})))
		})
	})

	Context("when there are errors retrieving counts from database", func() {
		BeforeEach(func() {
			lockDB.CountReturns(1, errors.New("DB error"))
		})

		JustBeforeEach(func() {
			fakeClock.Increment(metricsInterval)
		})

		It("does not emit any metrics", func() {
			Consistently(metricsChan).ShouldNot(Receive())
			fakeClock.Increment(metricsInterval)
			Consistently(metricsChan).ShouldNot(Receive())
		})
	})
})
<commit_msg>prevent test pollution<commit_after>package metrics_test

import (
	"errors"
	"time"

	"code.cloudfoundry.org/clock/fakeclock"
	mfakes "code.cloudfoundry.org/diego-logging-client/testhelpers"
	loggregator "code.cloudfoundry.org/go-loggregator"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"
	"code.cloudfoundry.org/locket/db/dbfakes"
	"code.cloudfoundry.org/locket/metrics"
	"code.cloudfoundry.org/locket/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("LockMetrics", func() {
	type FakeGauge struct {
		Name  string
		Value int
	}

	var (
		runner           ifrit.Runner
		process          ifrit.Process
		fakeMetronClient *mfakes.FakeIngressClient
		logger           *lagertest.TestLogger
		fakeClock        *fakeclock.FakeClock
		metricsInterval  time.Duration
		lockDB           *dbfakes.FakeLockDB
		metricsChan      chan FakeGauge
	)

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("metrics")
		fakeMetronClient = new(mfakes.FakeIngressClient)
		fakeClock = fakeclock.NewFakeClock(time.Now())
		metricsInterval = 10 * time.Second

		lockDB = &dbfakes.FakeLockDB{}

		lockDB.CountStub = func(l lager.Logger, lockType string) (int, error) {
			switch {
			case lockType == models.LockType:
				return 3, nil
			case lockType == models.PresenceType:
				return 2, nil
			default:
				return 0, errors.New("unknown type")
			}
		}

		metricsChan = make(chan FakeGauge, 100)

		ch := metricsChan
		fakeMetronClient.SendMetricStub = func(name string, value int, opts ...loggregator.EmitGaugeOption) error {
			defer GinkgoRecover()

			Eventually(ch).Should(BeSent(FakeGauge{name, value}))
			return nil
		}
	})

	JustBeforeEach(func() {
		runner = metrics.NewLockMetricsNotifier(
			logger,
			fakeClock,
			fakeMetronClient,
			metricsInterval,
			lockDB,
		)
		process = ifrit.Background(runner)
		Eventually(process.Ready()).Should(BeClosed())
	})

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

	Context("when there are no errors retrieving counts from database", func() {

		JustBeforeEach(func() {
			fakeClock.Increment(metricsInterval)
		})

		It("emits a metric for the number of active locks", func() {
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActiveLocks", 3})))
			fakeClock.Increment(metricsInterval)
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActiveLocks", 3})))
		})

		It("emits a metric for the number of active presences", func() {
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActivePresences", 2})))
			fakeClock.Increment(metricsInterval)
			Eventually(metricsChan).Should(Receive(Equal(FakeGauge{"ActivePresences", 2})))
		})
	})

	Context("when there are errors retrieving counts from database", func() {
		BeforeEach(func() {
			lockDB.CountReturns(1, errors.New("DB error"))
		})

		JustBeforeEach(func() {
			fakeClock.Increment(metricsInterval)
		})

		It("does not emit any metrics", func() {
			Consistently(metricsChan).ShouldNot(Receive())
			fakeClock.Increment(metricsInterval)
			Consistently(metricsChan).ShouldNot(Receive())
		})
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2020 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 testutil

import (
	"fmt"
	"io"
	"strings"

	"github.com/prometheus/client_golang/prometheus/testutil/promlint"
)

// exceptionMetrics is an exception list of metrics which violates promlint rules.
//
// The original entries come from the existing metrics when we introduce promlint.
// We setup this list for allow and not fail on the current violations.
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
var exceptionMetrics = []string{
	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/egressselector
	"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix

	// k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset
	"apiserver_flowcontrol_current_inqueue_requests",   // label names should be written in 'snake_case' not 'camelCase',
	"apiserver_flowcontrol_current_executing_requests", // label names should be written in 'snake_case' not 'camelCase'
	"apiserver_flowcontrol_rejected_requests_total",    // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/healthz
	"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters
	"authenticated_user_requests", // counter metrics should have "_total" suffix
	"authentication_attempts",     // counter metrics should have "_total" suffix

	// kube-apiserver
	"aggregator_openapi_v2_regeneration_count",
	"apiserver_admission_step_admission_duration_seconds_summary",
	"apiserver_current_inflight_requests",
	"apiserver_longrunning_gauge",
	"get_token_count",
	"get_token_fail_count",
	"ssh_tunnel_open_count",
	"ssh_tunnel_open_fail_count",

	// kube-controller-manager
	"attachdetach_controller_forced_detaches",
	"authenticated_user_requests",
	"authentication_attempts",
	"get_token_count",
	"get_token_fail_count",
	"node_collector_evictions_number",

	// k8s.io/kubernetes/pkg/kubelet/server/stats
	"container_cpu_usage_seconds_total", // non-counter metrics should not have "_total" suffix
	"node_cpu_usage_seconds_total",      // non-counter metrics should not have "_total" suffix

	// k8s.io/kubernetes/pkg/kubelet/pleg
	"kubelet_running_container_count", // non-histogram and non-summary metrics should not have "_count" suffix
	"kubelet_running_pod_count",       // non-histogram and non-summary metrics should not have "_count" suffix
}

// A Problem is an issue detected by a Linter.
type Problem promlint.Problem

func (p *Problem) String() string {
	return fmt.Sprintf("%s:%s", p.Metric, p.Text)
}

// A Linter is a Prometheus metrics linter.  It identifies issues with metric
// names, types, and metadata, and reports them to the caller.
type Linter struct {
	promLinter *promlint.Linter
}

// Lint performs a linting pass, returning a slice of Problems indicating any
// issues found in the metrics stream.  The slice is sorted by metric name
// and issue description.
func (l *Linter) Lint() ([]Problem, error) {
	promProblems, err := l.promLinter.Lint()
	if err != nil {
		return nil, err
	}

	// Ignore problems those in exception list
	problems := make([]Problem, 0, len(promProblems))
	for i := range promProblems {
		if !l.shouldIgnore(promProblems[i].Metric) {
			problems = append(problems, Problem(promProblems[i]))
		}
	}

	return problems, nil
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func (l *Linter) shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
// Only the text exposition format is supported.
func NewPromLinter(r io.Reader) *Linter {
	return &Linter{
		promLinter: promlint.New(r),
	}
}

func mergeProblems(problems []Problem) string {
	var problemsMsg []string

	for index := range problems {
		problemsMsg = append(problemsMsg, problems[index].String())
	}

	return strings.Join(problemsMsg, ",")
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// getLintError will ignore the metrics in exception list and converts lint problem to error.
func getLintError(problems []promlint.Problem) error {
	var filteredProblems []Problem
	for _, problem := range problems {
		if shouldIgnore(problem.Metric) {
			continue
		}

		filteredProblems = append(filteredProblems, Problem(problem))
	}

	if len(filteredProblems) == 0 {
		return nil
	}

	return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
}
<commit_msg>Update two metrics name to make promlint happy.<commit_after>/*
Copyright 2020 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 testutil

import (
	"fmt"
	"io"
	"strings"

	"github.com/prometheus/client_golang/prometheus/testutil/promlint"
)

// exceptionMetrics is an exception list of metrics which violates promlint rules.
//
// The original entries come from the existing metrics when we introduce promlint.
// We setup this list for allow and not fail on the current violations.
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
var exceptionMetrics = []string{
	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/egressselector
	"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix

	// k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset
	"apiserver_flowcontrol_current_inqueue_requests",   // label names should be written in 'snake_case' not 'camelCase',
	"apiserver_flowcontrol_current_executing_requests", // label names should be written in 'snake_case' not 'camelCase'
	"apiserver_flowcontrol_rejected_requests_total",    // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/healthz
	"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters
	"authenticated_user_requests", // counter metrics should have "_total" suffix
	"authentication_attempts",     // counter metrics should have "_total" suffix

	// kube-apiserver
	"aggregator_openapi_v2_regeneration_count",
	"apiserver_admission_step_admission_duration_seconds_summary",
	"apiserver_current_inflight_requests",
	"apiserver_longrunning_gauge",
	"get_token_count",
	"get_token_fail_count",
	"ssh_tunnel_open_count",
	"ssh_tunnel_open_fail_count",

	// kube-controller-manager
	"attachdetach_controller_forced_detaches",
	"authenticated_user_requests",
	"authentication_attempts",
	"get_token_count",
	"get_token_fail_count",
	"node_collector_evictions_number",

	// k8s.io/kubernetes/pkg/kubelet/server/stats
	// The two metrics have been deprecated and will be removed in release v1.20+.
	"container_cpu_usage_seconds_total", // non-counter metrics should not have "_total" suffix
	"node_cpu_usage_seconds_total",      // non-counter metrics should not have "_total" suffix
}

// A Problem is an issue detected by a Linter.
type Problem promlint.Problem

func (p *Problem) String() string {
	return fmt.Sprintf("%s:%s", p.Metric, p.Text)
}

// A Linter is a Prometheus metrics linter.  It identifies issues with metric
// names, types, and metadata, and reports them to the caller.
type Linter struct {
	promLinter *promlint.Linter
}

// Lint performs a linting pass, returning a slice of Problems indicating any
// issues found in the metrics stream.  The slice is sorted by metric name
// and issue description.
func (l *Linter) Lint() ([]Problem, error) {
	promProblems, err := l.promLinter.Lint()
	if err != nil {
		return nil, err
	}

	// Ignore problems those in exception list
	problems := make([]Problem, 0, len(promProblems))
	for i := range promProblems {
		if !l.shouldIgnore(promProblems[i].Metric) {
			problems = append(problems, Problem(promProblems[i]))
		}
	}

	return problems, nil
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func (l *Linter) shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
// Only the text exposition format is supported.
func NewPromLinter(r io.Reader) *Linter {
	return &Linter{
		promLinter: promlint.New(r),
	}
}

func mergeProblems(problems []Problem) string {
	var problemsMsg []string

	for index := range problems {
		problemsMsg = append(problemsMsg, problems[index].String())
	}

	return strings.Join(problemsMsg, ",")
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// getLintError will ignore the metrics in exception list and converts lint problem to error.
func getLintError(problems []promlint.Problem) error {
	var filteredProblems []Problem
	for _, problem := range problems {
		if shouldIgnore(problem.Metric) {
			continue
		}

		filteredProblems = append(filteredProblems, Problem(problem))
	}

	if len(filteredProblems) == 0 {
		return nil
	}

	return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
}
<|endoftext|>


<commit_before>/*
Copyright 2018 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 cmd

import (
	"fmt"
	"io"
	"sort"
	"strings"

	"github.com/spf13/cobra"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/printers"
)

var (
	apiresources_example = templates.Examples(`
		# Print the supported API Resources
		kubectl api-resources

		# Print the supported API Resources with more information
		kubectl api-resources -o wide

		# Print the supported namespaced resources
		kubectl api-resources --namespaced=true

		# Print the supported non-namespaced resources
		kubectl api-resources --namespaced=false

		# Print the supported API Resources with specific APIGroup
		kubectl api-resources --api-group=extensions`)
)

// ApiResourcesOptions is the start of the data required to perform the operation.  As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ApiResourcesOptions struct {
	out io.Writer

	Output     string
	APIGroup   string
	Namespaced bool
	Verbs      []string
	NoHeaders  bool
	Cached     bool
}

// groupResource contains the APIGroup and APIResource
type groupResource struct {
	APIGroup    string
	APIResource metav1.APIResource
}

func NewCmdApiResources(f cmdutil.Factory, out io.Writer) *cobra.Command {
	options := &ApiResourcesOptions{
		out: out,
	}

	cmd := &cobra.Command{
		Use:     "api-resources",
		Short:   "Print the supported API resources on the server",
		Long:    "Print the supported API resources on the server",
		Example: apiresources_example,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(options.Complete(cmd))
			cmdutil.CheckErr(options.Validate(cmd))
			cmdutil.CheckErr(options.RunApiResources(cmd, f))
		},
	}
	cmdutil.AddOutputFlags(cmd)
	cmdutil.AddNoHeadersFlags(cmd)
	cmd.Flags().StringVar(&options.APIGroup, "api-group", "", "Limit to resources in the specified API group.")
	cmd.Flags().BoolVar(&options.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.")
	cmd.Flags().StringSliceVar(&options.Verbs, "verbs", options.Verbs, "Limit to resources that support the specified verbs.")
	cmd.Flags().BoolVar(&options.Cached, "cached", options.Cached, "Use the cached list of resources if available.")
	return cmd
}

func (o *ApiResourcesOptions) Complete(cmd *cobra.Command) error {
	o.Output = cmdutil.GetFlagString(cmd, "output")
	o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers")
	return nil
}

func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error {
	validOutputTypes := sets.NewString("", "json", "yaml", "wide", "name", "custom-columns", "custom-columns-file", "go-template", "go-template-file", "jsonpath", "jsonpath-file")
	supportedOutputTypes := sets.NewString("", "wide", "name")
	outputFormat := cmdutil.GetFlagString(cmd, "output")
	if !validOutputTypes.Has(outputFormat) {
		return fmt.Errorf("output must be one of '' or 'wide': %v", outputFormat)
	}
	if !supportedOutputTypes.Has(outputFormat) {
		return fmt.Errorf("--output %v is not available in kubectl api-resources", outputFormat)
	}
	return nil
}

func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error {
	w := printers.GetNewTabWriter(o.out)
	defer w.Flush()

	discoveryclient, err := f.DiscoveryClient()
	if err != nil {
		return err
	}

	if !o.Cached {
		// Always request fresh data from the server
		discoveryclient.Invalidate()
	}

	lists, err := discoveryclient.ServerPreferredResources()
	if err != nil {
		return err
	}

	resources := []groupResource{}

	groupChanged := cmd.Flags().Changed("api-group")
	nsChanged := cmd.Flags().Changed("namespaced")

	for _, list := range lists {
		if len(list.APIResources) == 0 {
			continue
		}
		gv, err := schema.ParseGroupVersion(list.GroupVersion)
		if err != nil {
			continue
		}
		for _, resource := range list.APIResources {
			if len(resource.Verbs) == 0 {
				continue
			}
			// filter apiGroup
			if groupChanged && o.APIGroup != gv.Group {
				continue
			}
			// filter namespaced
			if nsChanged && o.Namespaced != resource.Namespaced {
				continue
			}
			// filter to resources that support the specified verbs
			if len(o.Verbs) > 0 && !sets.NewString(resource.Verbs...).HasAll(o.Verbs...) {
				continue
			}
			resources = append(resources, groupResource{
				APIGroup:    gv.Group,
				APIResource: resource,
			})
		}
	}

	if o.NoHeaders == false && o.Output != "name" {
		if err = printContextHeaders(w, o.Output); err != nil {
			return err
		}
	}

	sort.Stable(sortableGroupResource(resources))
	for _, r := range resources {
		switch o.Output {
		case "name":
			name := r.APIResource.Name
			if len(r.APIGroup) > 0 {
				name += "." + r.APIGroup
			}
			if _, err := fmt.Fprintf(w, "%s\n", name); err != nil {
				return err
			}
		case "wide":
			if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\t%v\n",
				r.APIResource.Name,
				strings.Join(r.APIResource.ShortNames, ","),
				r.APIGroup,
				r.APIResource.Namespaced,
				r.APIResource.Kind,
				r.APIResource.Verbs); err != nil {
				return err
			}
		case "":
			if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\n",
				r.APIResource.Name,
				strings.Join(r.APIResource.ShortNames, ","),
				r.APIGroup,
				r.APIResource.Namespaced,
				r.APIResource.Kind); err != nil {
				return err
			}
		}
	}
	return nil
}

func printContextHeaders(out io.Writer, output string) error {
	columnNames := []string{"NAME", "SHORTNAMES", "APIGROUP", "NAMESPACED", "KIND"}
	if output == "wide" {
		columnNames = append(columnNames, "VERBS")
	}
	_, err := fmt.Fprintf(out, "%s\n", strings.Join(columnNames, "\t"))
	return err
}

type sortableGroupResource []groupResource

func (s sortableGroupResource) Len() int      { return len(s) }
func (s sortableGroupResource) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sortableGroupResource) Less(i, j int) bool {
	ret := strings.Compare(s[i].APIGroup, s[j].APIGroup)
	if ret > 0 {
		return false
	} else if ret == 0 {
		return strings.Compare(s[i].APIResource.Name, s[j].APIResource.Name) < 0
	}
	return true
}
<commit_msg>UPSTREAM: 64516: Fix error message to be consistent with others<commit_after>/*
Copyright 2018 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 cmd

import (
	"fmt"
	"io"
	"sort"
	"strings"

	"github.com/spf13/cobra"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/printers"
)

var (
	apiresourcesExample = templates.Examples(`
		# Print the supported API Resources
		kubectl api-resources

		# Print the supported API Resources with more information
		kubectl api-resources -o wide

		# Print the supported namespaced resources
		kubectl api-resources --namespaced=true

		# Print the supported non-namespaced resources
		kubectl api-resources --namespaced=false

		# Print the supported API Resources with specific APIGroup
		kubectl api-resources --api-group=extensions`)
)

// ApiResourcesOptions is the start of the data required to perform the operation.  As new fields are added, add them here instead of
// referencing the cmd.Flags()
type ApiResourcesOptions struct {
	out io.Writer

	Output     string
	APIGroup   string
	Namespaced bool
	Verbs      []string
	NoHeaders  bool
	Cached     bool
}

// groupResource contains the APIGroup and APIResource
type groupResource struct {
	APIGroup    string
	APIResource metav1.APIResource
}

func NewCmdApiResources(f cmdutil.Factory, out io.Writer) *cobra.Command {
	options := &ApiResourcesOptions{
		out: out,
	}

	cmd := &cobra.Command{
		Use:     "api-resources",
		Short:   "Print the supported API resources on the server",
		Long:    "Print the supported API resources on the server",
		Example: apiresourcesExample,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(options.Complete(cmd))
			cmdutil.CheckErr(options.Validate(cmd))
			cmdutil.CheckErr(options.RunApiResources(cmd, f))
		},
	}
	cmdutil.AddOutputFlags(cmd)
	cmdutil.AddNoHeadersFlags(cmd)
	cmd.Flags().StringVar(&options.APIGroup, "api-group", "", "Limit to resources in the specified API group.")
	cmd.Flags().BoolVar(&options.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.")
	cmd.Flags().StringSliceVar(&options.Verbs, "verbs", options.Verbs, "Limit to resources that support the specified verbs.")
	cmd.Flags().BoolVar(&options.Cached, "cached", options.Cached, "Use the cached list of resources if available.")
	return cmd
}

func (o *ApiResourcesOptions) Complete(cmd *cobra.Command) error {
	o.Output = cmdutil.GetFlagString(cmd, "output")
	o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers")
	return nil
}

func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error {
	validOutputTypes := sets.NewString("", "json", "yaml", "wide", "name", "custom-columns", "custom-columns-file", "go-template", "go-template-file", "jsonpath", "jsonpath-file")
	supportedOutputTypes := sets.NewString("", "wide", "name")
	outputFormat := cmdutil.GetFlagString(cmd, "output")
	if !validOutputTypes.Has(outputFormat) {
		return fmt.Errorf("output must be one of '' or 'wide': %v", outputFormat)
	}
	if !supportedOutputTypes.Has(outputFormat) {
		return fmt.Errorf("--output %v is not available", outputFormat)
	}
	return nil
}

func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error {
	w := printers.GetNewTabWriter(o.out)
	defer w.Flush()

	discoveryclient, err := f.DiscoveryClient()
	if err != nil {
		return err
	}

	if !o.Cached {
		// Always request fresh data from the server
		discoveryclient.Invalidate()
	}

	lists, err := discoveryclient.ServerPreferredResources()
	if err != nil {
		return err
	}

	resources := []groupResource{}

	groupChanged := cmd.Flags().Changed("api-group")
	nsChanged := cmd.Flags().Changed("namespaced")

	for _, list := range lists {
		if len(list.APIResources) == 0 {
			continue
		}
		gv, err := schema.ParseGroupVersion(list.GroupVersion)
		if err != nil {
			continue
		}
		for _, resource := range list.APIResources {
			if len(resource.Verbs) == 0 {
				continue
			}
			// filter apiGroup
			if groupChanged && o.APIGroup != gv.Group {
				continue
			}
			// filter namespaced
			if nsChanged && o.Namespaced != resource.Namespaced {
				continue
			}
			// filter to resources that support the specified verbs
			if len(o.Verbs) > 0 && !sets.NewString(resource.Verbs...).HasAll(o.Verbs...) {
				continue
			}
			resources = append(resources, groupResource{
				APIGroup:    gv.Group,
				APIResource: resource,
			})
		}
	}

	if o.NoHeaders == false && o.Output != "name" {
		if err = printContextHeaders(w, o.Output); err != nil {
			return err
		}
	}

	sort.Stable(sortableGroupResource(resources))
	for _, r := range resources {
		switch o.Output {
		case "name":
			name := r.APIResource.Name
			if len(r.APIGroup) > 0 {
				name += "." + r.APIGroup
			}
			if _, err := fmt.Fprintf(w, "%s\n", name); err != nil {
				return err
			}
		case "wide":
			if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\t%v\n",
				r.APIResource.Name,
				strings.Join(r.APIResource.ShortNames, ","),
				r.APIGroup,
				r.APIResource.Namespaced,
				r.APIResource.Kind,
				r.APIResource.Verbs); err != nil {
				return err
			}
		case "":
			if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\n",
				r.APIResource.Name,
				strings.Join(r.APIResource.ShortNames, ","),
				r.APIGroup,
				r.APIResource.Namespaced,
				r.APIResource.Kind); err != nil {
				return err
			}
		}
	}
	return nil
}

func printContextHeaders(out io.Writer, output string) error {
	columnNames := []string{"NAME", "SHORTNAMES", "APIGROUP", "NAMESPACED", "KIND"}
	if output == "wide" {
		columnNames = append(columnNames, "VERBS")
	}
	_, err := fmt.Fprintf(out, "%s\n", strings.Join(columnNames, "\t"))
	return err
}

type sortableGroupResource []groupResource

func (s sortableGroupResource) Len() int      { return len(s) }
func (s sortableGroupResource) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sortableGroupResource) Less(i, j int) bool {
	ret := strings.Compare(s[i].APIGroup, s[j].APIGroup)
	if ret > 0 {
		return false
	} else if ret == 0 {
		return strings.Compare(s[i].APIResource.Name, s[j].APIResource.Name) < 0
	}
	return true
}
<|endoftext|>


<commit_before>package portal

import (
	"github.com/Cepave/fe/http/base"
	event "github.com/Cepave/fe/model/falcon_portal"
)

type PortalController struct {
	base.BaseController
}

func (this *PortalController) EventCasesGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	startTime, _ := this.GetInt64("startTime", 0)
	endTime, _ := this.GetInt64("endTime", 0)
	prioprity, _ := this.GetInt("prioprity", -1)
	status := this.GetString("status", "DEFAULT")

	username := this.GetString("cName", "")
	limitNum, _ := this.GetInt("limit", 0)
	elimit, _ := this.GetInt("elimit", 0)
	events, err := event.GetEventCases(startTime, endTime, prioprity, status, limitNum, elimit, username)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	baseResp.Data["eventCases"] = events
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) ColseCase() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	username := this.GetString("cName", "")
	closedNote := this.GetString("closedNote", "")
	id := this.GetString("id", "xxx")
	switch {
	case id == "xxx":
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	case closedNote == "":
		this.ResposeError(baseResp, "You can not skip closed note")
		return
	}
	err = event.CloseEvent(username, closedNote, id)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) AddNote() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	username := this.GetString("cName", "")
	note := this.GetString("Note", "")
	id := this.GetString("id", "xxx")
	status := this.GetString("status", "")
	caseId := this.GetString("caseId", "")
	switch {
	case id == "xxx":
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	case note == "":
		this.ResposeError(baseResp, "You can not skip closed note")
		return
	}
	err = event.AddNote(username, note, id, status, caseId)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) NotesGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	id := this.GetString("id", "xxx")
	limitNum, _ := this.GetInt("limit", 0)
	if id == "xxx" {
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	}
	notes := event.GetNotes(id)
	baseResp.Data["notes"] = events
	return
}

func (this *PortalController) EventGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	startTime, _ := this.GetInt64("startTime", 0)
	endTime, _ := this.GetInt64("endTime", 0)

	limitNum, _ := this.GetInt("limit", 0)
	events, err := event.GetEvents(startTime, endTime, limitNum)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	baseResp.Data["events"] = events
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) CountNumOfTlp() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()

	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	} else {
		numberOfteam, err := event.CountNumOfTlp()
		if err != nil {
			this.ResposeError(baseResp, err.Error())
			return
		}
		baseResp.Data["count"] = numberOfteam
	}
	this.ServeApiJson(baseResp)
	return
}
<commit_msg>fixed erros<commit_after>package portal

import (
	"github.com/Cepave/fe/http/base"
	event "github.com/Cepave/fe/model/falcon_portal"
)

type PortalController struct {
	base.BaseController
}

func (this *PortalController) EventCasesGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	startTime, _ := this.GetInt64("startTime", 0)
	endTime, _ := this.GetInt64("endTime", 0)
	prioprity, _ := this.GetInt("prioprity", -1)
	status := this.GetString("status", "DEFAULT")

	username := this.GetString("cName", "")
	limitNum, _ := this.GetInt("limit", 0)
	elimit, _ := this.GetInt("elimit", 0)
	events, err := event.GetEventCases(startTime, endTime, prioprity, status, limitNum, elimit, username)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	baseResp.Data["eventCases"] = events
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) ColseCase() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	username := this.GetString("cName", "")
	closedNote := this.GetString("closedNote", "")
	id := this.GetString("id", "xxx")
	switch {
	case id == "xxx":
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	case closedNote == "":
		this.ResposeError(baseResp, "You can not skip closed note")
		return
	}
	err = event.CloseEvent(username, closedNote, id)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) AddNote() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	username := this.GetString("cName", "")
	note := this.GetString("Note", "")
	id := this.GetString("id", "xxx")
	status := this.GetString("status", "")
	caseId := this.GetString("caseId", "")
	switch {
	case id == "xxx":
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	case note == "":
		this.ResposeError(baseResp, "You can not skip closed note")
		return
	}
	err = event.AddNote(username, note, id, status, caseId)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) NotesGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	id := this.GetString("id", "xxx")
	limitNum, _ := this.GetInt("limit", 0)
	if id == "xxx" {
		this.ResposeError(baseResp, "You dosen't pick any event id")
		return
	}
	notes := event.GetNotes(id, limitNum)
	baseResp.Data["notes"] = notes
	return
}

func (this *PortalController) EventGet() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	startTime, _ := this.GetInt64("startTime", 0)
	endTime, _ := this.GetInt64("endTime", 0)

	limitNum, _ := this.GetInt("limit", 0)
	events, err := event.GetEvents(startTime, endTime, limitNum)
	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	}
	baseResp.Data["events"] = events
	this.ServeApiJson(baseResp)
	return
}

func (this *PortalController) CountNumOfTlp() {
	baseResp := this.BasicRespGen()
	_, err := this.SessionCheck()

	if err != nil {
		this.ResposeError(baseResp, err.Error())
		return
	} else {
		numberOfteam, err := event.CountNumOfTlp()
		if err != nil {
			this.ResposeError(baseResp, err.Error())
			return
		}
		baseResp.Data["count"] = numberOfteam
	}
	this.ServeApiJson(baseResp)
	return
}
<|endoftext|>


<commit_before>package main

import (
  "log"
  "github.com/gorilla/mux"
  "net/http"
  "net/http/httputil"
  "net/url"
  "github.com/fhs/gompd/mpd"
  "github.com/ascherkus/go-id3/src/id3"
  "os"
  "fmt"
  "encoding/json"
)

// TODO: consider if global is really the best idea, or if we should
//       make some classes, or something...
var mpd_conn *mpd.Client

func main() {

  // TODO: functionize?
  // connect to MPD
  conn, err := mpd.Dial("tcp", "localhost:6600")

  // if we can't connect to MPD everything's fucked, nothing's going to work
  // kill all humans, and die, respectfully, after explaining what the issue
  // is.
  if err != nil {
    log.Fatal(err)
    log.Println("\n\nServer quiting because it can't connect to MPD");
    return
  }
  defer conn.Close()

  // set global mpd_conn to our new connection.
  mpd_conn = conn

  // create a new mux router for our server.
  r := mux.NewRouter()

  // requests to `/stream` are proxied to the MPD httpd.
  r.HandleFunc("/stream",
    httputil.NewSingleHostReverseProxy(&url.URL{Scheme:"http", Host: "localhost:8000", Path: "/"}).ServeHTTP)

  // list all songs
  r.HandleFunc("/songs", listSongs)

  r.HandleFunc("/current", getCurrentSong)

  // This MUST go last! It takes precidence over any after it, meaning
  // the server will try to serve a file, which most likely doesn't exist,
  // and will 404.
  //
  // serve up the frontend files.
  r.PathPrefix("/").Handler(http.FileServer(http.Dir("../frontend/turbo_wookie/web")))

  // create a new http.Server
  server := &http.Server{
    Addr: ":9000",
    Handler: r,
  }

  log.Println("Starting server on port 9000")

  // sit, waiting, like a hunter, spying on its prey.
  server.ListenAndServe()
}

func jsoniffy(v interface {}) string {
  obj, err := json.MarshalIndent(v, "", "  ")
  if err != nil {
    log.Print("Couldn't turn something into JSON: ", v)
    log.Fatal(err)
  }

  return string(obj)
}

func listSongs(w http.ResponseWriter, r *http.Request) {
  // get all files from MPD
  mpdfiles, err := mpd_conn.GetFiles()
  if err != nil {
    log.Println("Couldn't get a list of files...")
    log.Fatal(err)
  }

  // create a slice of id3.File s
  files := make([]*id3.File, 0)

  for _, song := range mpdfiles {
    // grab the file on the filesystem
    file, err := os.Open("mpd/music/" + song)
    if err != nil {
      log.Println("Couldn't open file: " + song)
      log.Fatal(err)
    }

    // add the current file to our slice
    id3_file := id3.Read(file)
    files = append(files, id3_file)
  }

  // turn the files slice into some json
  files_json, err := json.MarshalIndent(files, "", "  ")
  if err != nil {
    log.Println("Couldn't turn files into json")
    log.Fatal(err)
  }

  // send the json to the client.
  fmt.Fprintf(w, string(files_json))
}

func getCurrentSong(w http.ResponseWriter, r *http.Request) {
  currentSong, err := mpd_conn.CurrentSong()
  if err != nil {
    log.Println("Couldn't get current song info")
    log.Fatal(err)
  }

  fmt.Fprintf(w, jsoniffy(currentSong))
}

<commit_msg>more comments<commit_after>package main

import (
  "log"
  "github.com/gorilla/mux"
  "net/http"
  "net/http/httputil"
  "net/url"
  "github.com/fhs/gompd/mpd"
  "github.com/ascherkus/go-id3/src/id3"
  "os"
  "fmt"
  "encoding/json"
)

// TODO: consider if global is really the best idea, or if we should
//       make some classes, or something...
var mpd_conn *mpd.Client

func main() {
  mpdConnect("localhost:6600")

  // create a new mux router for our server.
  r := mux.NewRouter()

  // requests to `/stream` are proxied to the MPD httpd.
  r.HandleFunc("/stream",
    httputil.NewSingleHostReverseProxy(
      &url.URL{
        Scheme:"http",
        Host: "localhost:8000",
        Path: "/",
      }).ServeHTTP)

  r.HandleFunc("/songs", listSongs)
  r.HandleFunc("/current", getCurrentSong)

  // This MUST go last! It takes precidence over any after it, meaning
  // the server will try to serve a file, which most likely doesn't exist,
  // and will 404.
  //
  // serve up the frontend files.
  r.PathPrefix("/").Handler(http.FileServer(http.Dir("../frontend/turbo_wookie/web")))

  // sit, waiting, like a hunter, spying on its prey.
  log.Println("Starting server on port 9000")
  http.ListenAndServe(":9000", r)
}

/********************
  Handler Functions
 ********************/

// return all songs known to MPD to the client.
func listSongs(w http.ResponseWriter, r *http.Request) {
  // get all files from MPD
  mpdfiles, err := mpd_conn.GetFiles()
  if err != nil {
    log.Println("Couldn't get a list of files...")
    log.Fatal(err)
  }

  // create a slice of id3.File s
  files := make([]*id3.File, 0)

  for _, song := range mpdfiles {
    // grab the file on the filesystem
    file, err := os.Open("mpd/music/" + song)
    if err != nil {
      log.Println("Couldn't open file: " + song)
      log.Fatal(err)
    }

    // add the current file to our slice
    id3_file := id3.Read(file)
    files = append(files, id3_file)
  }

  // turn the files slice into some json
  files_json, err := json.MarshalIndent(files, "", "  ")
  if err != nil {
    log.Println("Couldn't turn files into json")
    log.Fatal(err)
  }

  // send the json to the client.
  fmt.Fprintf(w, string(files_json))
}

// Return a JSON representation of the currently playing song.
func getCurrentSong(w http.ResponseWriter, r *http.Request) {
  currentSong, err := mpd_conn.CurrentSong()
  if err != nil {
    log.Println("Couldn't get current song info")
    log.Fatal(err)
  }

  fmt.Fprintf(w, jsoniffy(currentSong))
}

/*******************
  Helper Functions
 *******************/

// Connect to MPD's control channel, and set the global mpd_conn to it.
func mpdConnect(url string) {
  conn, err := mpd.Dial("tcp", url)

  // if we can't connect to MPD everything's fucked, nothing's going to work
  // kill all humans, and die, respectfully, after explaining what the issue
  // is.
  if err != nil {
    log.Println("\n\nServer quiting because it can't connect to MPD");
    log.Fatal(err)
    return
  }
  defer conn.Close()

  // set global mpd_conn to our new connection.
  mpd_conn = conn
}

// turn anything into JSON.
func jsoniffy(v interface {}) string {
  obj, err := json.MarshalIndent(v, "", "  ")
  if err != nil {
    log.Print("Couldn't turn something into JSON: ", v)
    log.Fatal(err)
  }

  return string(obj)
}<|endoftext|>


<commit_before>package cassandra

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/gocql/gocql"
	"github.com/intelsdi-x/swan/pkg/cassandra"
	. "github.com/smartystreets/goconvey/convey"
	"math/rand"
	"testing"
	"time"
)

func insertDataIntoCassandra(session *gocql.Session, metrics *cassandra.Metrics) error {
	// TODO(CD): Consider getting schema from the cassandra publisher plugin
	session.Query(`CREATE TABLE IF NOT EXISTS snap.metrics (
		ns  text,
		ver int,
		host text,
		time timestamp,
		valtype text,
		doubleVal double,
		boolVal boolean,
		strVal text,
		tags map<text,text>,
		PRIMARY KEY ((ns, ver, host), time)
	) WITH CLUSTERING ORDER BY (time DESC);`,
	).Exec()

	err := session.Query(`insert into snap.metrics(
		ns, ver, host, time, boolval,
		doubleval, strval, tags, valtype) values
		(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		metrics.Namespace(), metrics.Version(), metrics.Host(), metrics.Time(), metrics.Boolval(),
		metrics.Doubleval(), metrics.Strval(), metrics.Tags(), metrics.Valtype(),
	).Exec()

	if err != nil {
		return err
	}
	return nil
}

func TestValuesGatherer(t *testing.T) {
	// Create fake experiment ID.
	rand.Seed(int64(time.Now().Nanosecond()))
	value := rand.Int()
	experimentID := fmt.Sprintf("%d", value)
	expectedTagsMap := map[string]string{"swan_experiment": experimentID, "swan_phase": "p2", "swan_repetition": "2"}

	//Create Metrics struct that will be inserted into cassandra.
	metrics := cassandra.NewMetrics(experimentID, 1, "abc", time.Now(), false, 10, "c", expectedTagsMap, "boolval")

	logrus.SetLevel(logrus.ErrorLevel)
	Convey("While connecting to Cassandra with proper parameters", t, func() {
		cassandraConfig, err := cassandra.CreateConfigWithSession("127.0.0.1", "snap")
		session := cassandraConfig.CassandraSession()
		Convey("I should receive not empty session", func() {
			So(session, ShouldNotBeNil)
			So(err, ShouldBeNil)
			Convey("I should be able to insert data into cassandra", func() {
				err := insertDataIntoCassandra(session, metrics)
				So(err, ShouldBeNil)
				Convey("and I should be able to receive expected values and close session", func() {
					metricsList, err := cassandraConfig.GetValuesForGivenExperiment(experimentID)
					So(len(metricsList), ShouldBeGreaterThan, 0)
					So(err, ShouldBeNil)
					resultedMetrics := metricsList[0]

					// Check values of metrics.
					So(resultedMetrics.Namespace(), ShouldEqual, metrics.Namespace())
					So(resultedMetrics.Version(), ShouldEqual, metrics.Version())
					So(resultedMetrics.Host(), ShouldEqual, metrics.Host())

					// Cassandra stores time values in UTC by default. So, we
					// convert the expected time value to UTC to avoid discrepancies
					// in the interpreted calendar date and the test flakiness
					// that could cause. For completeness, we also pre-emptively
					// convert the result time to UTC in case the database is
					// configured to use a non-default TZ.
					_, _, resultedDay := resultedMetrics.Time().UTC().Date()
					_, _, expectedDay := metrics.Time().UTC().Date()

					So(resultedDay, ShouldEqual, expectedDay)
					So(resultedMetrics.Boolval(), ShouldEqual, metrics.Boolval())
					So(resultedMetrics.Doubleval(), ShouldEqual, metrics.Doubleval())
					So(resultedMetrics.Strval(), ShouldEqual, metrics.Strval())
					So(resultedMetrics.Tags()["swan_experiment"], ShouldEqual,
						metrics.Tags()["swan_experiment"])
					So(resultedMetrics.Tags()["swan_phase"], ShouldEqual,
						metrics.Tags()["swan_phase"])
					So(resultedMetrics.Tags()["swan_repetition"], ShouldEqual,
						metrics.Tags()["swan_repetition"])
					So(resultedMetrics.Valtype(), ShouldEqual, metrics.Valtype())

					err = cassandraConfig.CloseSession()
					So(err, ShouldBeNil)
				})
			})
		})

	})
}
<commit_msg>Added checking if err is not nil during creating Cassandra session.<commit_after>package cassandra

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/gocql/gocql"
	"github.com/intelsdi-x/swan/pkg/cassandra"
	. "github.com/smartystreets/goconvey/convey"
	"math/rand"
	"testing"
	"time"
)

func insertDataIntoCassandra(session *gocql.Session, metrics *cassandra.Metrics) error {
	// TODO(CD): Consider getting schema from the cassandra publisher plugin
	session.Query(`CREATE TABLE IF NOT EXISTS snap.metrics (
		ns  text,
		ver int,
		host text,
		time timestamp,
		valtype text,
		doubleVal double,
		boolVal boolean,
		strVal text,
		tags map<text,text>,
		PRIMARY KEY ((ns, ver, host), time)
	) WITH CLUSTERING ORDER BY (time DESC);`,
	).Exec()

	err := session.Query(`insert into snap.metrics(
		ns, ver, host, time, boolval,
		doubleval, strval, tags, valtype) values
		(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		metrics.Namespace(), metrics.Version(), metrics.Host(), metrics.Time(), metrics.Boolval(),
		metrics.Doubleval(), metrics.Strval(), metrics.Tags(), metrics.Valtype(),
	).Exec()

	if err != nil {
		return err
	}
	return nil
}

func TestValuesGatherer(t *testing.T) {
	// Create fake experiment ID.
	rand.Seed(int64(time.Now().Nanosecond()))
	value := rand.Int()
	experimentID := fmt.Sprintf("%d", value)
	expectedTagsMap := map[string]string{"swan_experiment": experimentID, "swan_phase": "p2", "swan_repetition": "2"}

	//Create Metrics struct that will be inserted into cassandra.
	metrics := cassandra.NewMetrics(experimentID, 1, "abc", time.Now(), false, 10, "c", expectedTagsMap, "boolval")

	logrus.SetLevel(logrus.ErrorLevel)
	Convey("While connecting to Cassandra with proper parameters", t, func() {
		cassandraConfig, err := cassandra.CreateConfigWithSession("127.0.0.1", "snap")
		So(err, ShouldBeNil)
		session := cassandraConfig.CassandraSession()
		Convey("I should receive not empty session", func() {
			So(session, ShouldNotBeNil)
			So(err, ShouldBeNil)
			Convey("I should be able to insert data into cassandra", func() {
				err := insertDataIntoCassandra(session, metrics)
				So(err, ShouldBeNil)
				Convey("and I should be able to receive expected values and close session", func() {
					metricsList, err := cassandraConfig.GetValuesForGivenExperiment(experimentID)
					So(len(metricsList), ShouldBeGreaterThan, 0)
					So(err, ShouldBeNil)
					resultedMetrics := metricsList[0]

					// Check values of metrics.
					So(resultedMetrics.Namespace(), ShouldEqual, metrics.Namespace())
					So(resultedMetrics.Version(), ShouldEqual, metrics.Version())
					So(resultedMetrics.Host(), ShouldEqual, metrics.Host())

					// Cassandra stores time values in UTC by default. So, we
					// convert the expected time value to UTC to avoid discrepancies
					// in the interpreted calendar date and the test flakiness
					// that could cause. For completeness, we also pre-emptively
					// convert the result time to UTC in case the database is
					// configured to use a non-default TZ.
					_, _, resultedDay := resultedMetrics.Time().UTC().Date()
					_, _, expectedDay := metrics.Time().UTC().Date()

					So(resultedDay, ShouldEqual, expectedDay)
					So(resultedMetrics.Boolval(), ShouldEqual, metrics.Boolval())
					So(resultedMetrics.Doubleval(), ShouldEqual, metrics.Doubleval())
					So(resultedMetrics.Strval(), ShouldEqual, metrics.Strval())
					So(resultedMetrics.Tags()["swan_experiment"], ShouldEqual,
						metrics.Tags()["swan_experiment"])
					So(resultedMetrics.Tags()["swan_phase"], ShouldEqual,
						metrics.Tags()["swan_phase"])
					So(resultedMetrics.Tags()["swan_repetition"], ShouldEqual,
						metrics.Tags()["swan_repetition"])
					So(resultedMetrics.Valtype(), ShouldEqual, metrics.Valtype())

					err = cassandraConfig.CloseSession()
					So(err, ShouldBeNil)
				})
			})
		})

	})
}
<|endoftext|>