<commit_before>// Copyright 2018 ETH Zurich
// Copyright 2020 ETH Zurich, Anapaya Systems
//
// 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 xtest

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/scionproto/scion/go/lib/addr"
)

// Update registers the '-update' flag for the test.
//
// This flag should be checked by golden file tests to see whether the golden
// files should be updated or not. The golden files should be deterministic.
// Use UpdateNonDeterminsticGoldenFiles instead, if they are not deterministic.
//
// To update all golden files, run the following command:
//
//   go test ./... -update
//
// To update a specific package, run the following command:
//
//   go test ./path/to/package -update
//
// The flag should be registered as a package global variable:
//
//   var update = xtest.UpdateGoldenFiles()
func UpdateGoldenFiles() *bool {
	return flag.Bool("update", false, "set to regenerate the golden files")
}

// UpdateNonDeterminsticGoldenFiles registers the '-update-non-deterministic'
// flag for the test.
//
// This flag should be checked by golden file tests to see whether the
// non-deterministic golden files should be updated or not.
//
// To update all golden files, run the following command:
//
//   go test ./... -update-non-deterministic
//
// To update a specific package, run the following command:
//
//   go test ./path/to/package -update-non-deterministic
//
// The flag should be registered as a package global variable:
//
//   var updateNonDeterministic = xtest.UpdateNonDeterminsticGoldenFiles()
func UpdateNonDeterminsticGoldenFiles() *bool {
	return flag.Bool("update-non-deterministic", false,
		"set to regenerate the non-deterministic golden files",
	)
}

// TempFileName creates a temporary file in dir with the specified prefix, and
// then closes and deletes the file and returns its name. It is useful for
// testing packages that care about a unique path without being able to
// overwrite it (e.g., UNIX domain socket addresses or databases).
func TempFileName(dir, prefix string) (string, error) {
	file, err := ioutil.TempFile(dir, prefix)
	if err != nil {
		return "", err
	}

	name := file.Name()
	if err := file.Close(); err != nil {
		return "", err
	}

	if err := os.Remove(name); err != nil {
		return "", err
	}
	return name, nil
}

// MustTempFileName is a wrapper around TempFileName. The function panics if an
// error occurs. It is intended for tests where error handling is not
// necessary, and for chaining functions.
func MustTempFileName(dir, prefix string) string {
	name, err := TempFileName(dir, prefix)
	if err != nil {
		panic(err)
	}
	return name
}

// MustTempDir creates a new temporary directory under dir with the specified
// prefix. If the function encounters an error it panics. The second return
// value is a clean-up function that can be called to recursively delete the
// entire directory.
func MustTempDir(dir, prefix string) (string, func()) {
	name, err := ioutil.TempDir(dir, prefix)
	if err != nil {
		panic(err)
	}
	return name, func() {
		os.RemoveAll(name)
	}
}

func TempDir(t testing.TB) (string, func()) {
	testName := strings.NewReplacer("/", "_", "\\", "_", ":", "_").Replace(t.Name())
	name, err := ioutil.TempDir("", fmt.Sprintf("%s_*", testName))
	require.NoError(t, err)
	return name, func() {
		os.RemoveAll(name)
	}
}

// CopyDir copies "from" to "to", using the unix cp command.
func CopyDir(t testing.TB, from, to string) {
	t.Helper()
	cmd := exec.Command("cp", "-rL", from, to)
	out, err := cmd.CombinedOutput()
	require.NoError(t, err, string(out))
}

// FailOnErr causes t to exit with a fatal error if err is non-nil.
func FailOnErr(t testing.TB, err error, desc ...string) {
	t.Helper()

	if err != nil {
		t.Fatal(strings.Join(desc, " "), err)
	}
}

// MustMarshalJSONToFile marshals v and writes the result to file
// testdata/baseName. If the file exists, it is truncated; if it doesn't exist,
// it is created. On errors, t.Fatal() is called.
func MustMarshalJSONToFile(t testing.TB, v interface{}, baseName string) {
	t.Helper()

	enc, err := json.MarshalIndent(v, "", "    ")
	if err != nil {
		t.Fatal(err)
	}

	buffer := bytes.NewBuffer(enc)
	if err := buffer.WriteByte('\n'); err != nil {
		t.Fatal(err)
	}

	MustWriteToFile(t, buffer.Bytes(), baseName)
}

// MustWriteToFile writes b to file testdata/baseName. If the file exists, it
// is truncated; if it doesn't exist, it is created. On errors, t.Fatal() is
// called.
func MustWriteToFile(t testing.TB, b []byte, baseName string) {
	t.Helper()

	if err := ioutil.WriteFile(ExpandPath(baseName), b, 0644); err != nil {
		t.Fatal(err)
	}
}

// MustReadFromFile reads testdata/baseName and returns the raw content. On
// errors, t.Fatal() is called.
func MustReadFromFile(t testing.TB, baseName string) []byte {
	t.Helper()

	name := filepath.Join("testdata", baseName)
	b, err := ioutil.ReadFile(name)
	if err != nil {
		t.Fatal(err)
	}
	return b
}

// ExpandPath returns testdata/file.
func ExpandPath(file string) string {
	return filepath.Join("testdata", file)
}

// MustParseIA parses s and returns the corresponding addr.IA object. It
// panics if s is not a valid ISD-AS representation.
func MustParseIA(s string) addr.IA {
	ia, err := addr.IAFromString(s)
	if err != nil {
		panic(err)
	}
	return ia
}

// MustParseAS parses s and returns the corresponding addr.AS object. It panics
// if s is not valid AS representation.
func MustParseAS(s string) addr.AS {
	ia, err := addr.ASFromString(s)
	if err != nil {
		panic(err)
	}
	return ia
}

// MustParseASes parses a list of comma separated AS strings. It panics in case
// parsing fails.
func MustParseASes(list string) []addr.AS {
	l := strings.Split(list, ",")
	var ases []addr.AS
	for _, raw := range l {
		ases = append(ases, MustParseAS(raw))
	}
	return ases
}

// MustParseHexString parses s and returns the corresponding byte slice.
// It panics if the decoding fails.
func MustParseHexString(s string) []byte {
	// remove whitespace
	reg, err := regexp.Compile(`\s+`)
	if err != nil {
		panic(err)
	}
	s = reg.ReplaceAllString(s, "")

	decoded, err := hex.DecodeString(s)
	if err != nil {
		panic(err)
	}
	return decoded
}

// MustParseCIDR parses s and returns the corresponding net.IPNet object. It
// fails the test if s is not a valid CIDR string.
func MustParseCIDR(t *testing.T, s string) *net.IPNet {
	t.Helper()

	_, network, err := net.ParseCIDR(s)
	require.NoError(t, err)
	return network
}

// MustParseCIDRs parses the CIDR entries and returns a list containing the
// parsed net.IPNet objects.
func MustParseCIDRs(t *testing.T, entries ...string) []*net.IPNet {
	t.Helper()

	result := make([]*net.IPNet, 0, len(entries))
	for _, e := range entries {
		result = append(result, MustParseCIDR(t, e))
	}
	return result
}

// MustParseUDPAddr parses s and returns the corresponding net.UDPAddr object.
// It fails the test if s is not a valid UDP address string.
func MustParseUDPAddr(t *testing.T, s string) *net.UDPAddr {
	t.Helper()

	a, err := net.ResolveUDPAddr("udp", s)
	require.NoError(t, err)
	if ipv4 := a.IP.To4(); ipv4 != nil {
		a.IP = ipv4
	}
	return a
}

// AssertReadReturnsBetween will call t.Fatalf if the first read from the
// channel doesn't happen between x and y.
func AssertReadReturnsBetween(t testing.TB, ch <-chan struct{}, x, y time.Duration) {
	AssertReadDoesNotReturnBefore(t, ch, x)
	// Above aborts the test if it returns before x time passed, so if we get
	// here x time has passed.
	AssertReadReturnsBefore(t, ch, y-x)
}

// AssertReadReturnsBefore will call t.Fatalf if the first read from the
// channel doesn't happen before timeout.
func AssertReadReturnsBefore(t testing.TB, ch <-chan struct{}, timeout time.Duration) {
	t.Helper()
	select {
	case <-ch:
	case <-time.After(timeout):
		t.Fatalf("goroutine took too long to finish")
	}
}

// AssertReadDoesNotReturnBefore will call t.Fatalf if the first read from the
// channel happens before timeout.
func AssertReadDoesNotReturnBefore(t testing.TB, ch <-chan struct{}, timeout time.Duration) {
	select {
	case <-ch:
		t.Fatalf("goroutine finished too quickly")
	case <-time.After(timeout):
	}
}

// AssertError checks that err is not nil if expectError is true and that is it nil otherwise
func AssertError(t *testing.T, err error, expectError bool) {
	if expectError {
		assert.Error(t, err)
	} else {
		assert.NoError(t, err)
	}
}
<commit_msg>xtest: add test name sanitizer<commit_after>// Copyright 2018 ETH Zurich
// Copyright 2020 ETH Zurich, Anapaya Systems
//
// 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 xtest

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/scionproto/scion/go/lib/addr"
)

// Update registers the '-update' flag for the test.
//
// This flag should be checked by golden file tests to see whether the golden
// files should be updated or not. The golden files should be deterministic.
// Use UpdateNonDeterminsticGoldenFiles instead, if they are not deterministic.
//
// To update all golden files, run the following command:
//
//   go test ./... -update
//
// To update a specific package, run the following command:
//
//   go test ./path/to/package -update
//
// The flag should be registered as a package global variable:
//
//   var update = xtest.UpdateGoldenFiles()
func UpdateGoldenFiles() *bool {
	return flag.Bool("update", false, "set to regenerate the golden files")
}

// UpdateNonDeterminsticGoldenFiles registers the '-update-non-deterministic'
// flag for the test.
//
// This flag should be checked by golden file tests to see whether the
// non-deterministic golden files should be updated or not.
//
// To update all golden files, run the following command:
//
//   go test ./... -update-non-deterministic
//
// To update a specific package, run the following command:
//
//   go test ./path/to/package -update-non-deterministic
//
// The flag should be registered as a package global variable:
//
//   var updateNonDeterministic = xtest.UpdateNonDeterminsticGoldenFiles()
func UpdateNonDeterminsticGoldenFiles() *bool {
	return flag.Bool("update-non-deterministic", false,
		"set to regenerate the non-deterministic golden files",
	)
}

// TempFileName creates a temporary file in dir with the specified prefix, and
// then closes and deletes the file and returns its name. It is useful for
// testing packages that care about a unique path without being able to
// overwrite it (e.g., UNIX domain socket addresses or databases).
func TempFileName(dir, prefix string) (string, error) {
	file, err := ioutil.TempFile(dir, prefix)
	if err != nil {
		return "", err
	}

	name := file.Name()
	if err := file.Close(); err != nil {
		return "", err
	}

	if err := os.Remove(name); err != nil {
		return "", err
	}
	return name, nil
}

// MustTempFileName is a wrapper around TempFileName. The function panics if an
// error occurs. It is intended for tests where error handling is not
// necessary, and for chaining functions.
func MustTempFileName(dir, prefix string) string {
	name, err := TempFileName(dir, prefix)
	if err != nil {
		panic(err)
	}
	return name
}

// MustTempDir creates a new temporary directory under dir with the specified
// prefix. If the function encounters an error it panics. The second return
// value is a clean-up function that can be called to recursively delete the
// entire directory.
func MustTempDir(dir, prefix string) (string, func()) {
	name, err := ioutil.TempDir(dir, prefix)
	if err != nil {
		panic(err)
	}
	return name, func() {
		os.RemoveAll(name)
	}
}

// SanitizedName sanitizes the test name such that it can be used as a file name.
func SanitizedName(t testing.TB) string {
	return strings.NewReplacer(" ", "_", "/", "_", "\\", "_", ":", "_").Replace(t.Name())
}

func TempDir(t testing.TB) (string, func()) {
	name, err := ioutil.TempDir("", fmt.Sprintf("%s_*", SanitizedName(t)))
	require.NoError(t, err)
	return name, func() {
		os.RemoveAll(name)
	}
}

// CopyDir copies "from" to "to", using the unix cp command.
func CopyDir(t testing.TB, from, to string) {
	t.Helper()
	cmd := exec.Command("cp", "-rL", from, to)
	out, err := cmd.CombinedOutput()
	require.NoError(t, err, string(out))
}

// FailOnErr causes t to exit with a fatal error if err is non-nil.
func FailOnErr(t testing.TB, err error, desc ...string) {
	t.Helper()

	if err != nil {
		t.Fatal(strings.Join(desc, " "), err)
	}
}

// MustMarshalJSONToFile marshals v and writes the result to file
// testdata/baseName. If the file exists, it is truncated; if it doesn't exist,
// it is created. On errors, t.Fatal() is called.
func MustMarshalJSONToFile(t testing.TB, v interface{}, baseName string) {
	t.Helper()

	enc, err := json.MarshalIndent(v, "", "    ")
	if err != nil {
		t.Fatal(err)
	}

	buffer := bytes.NewBuffer(enc)
	if err := buffer.WriteByte('\n'); err != nil {
		t.Fatal(err)
	}

	MustWriteToFile(t, buffer.Bytes(), baseName)
}

// MustWriteToFile writes b to file testdata/baseName. If the file exists, it
// is truncated; if it doesn't exist, it is created. On errors, t.Fatal() is
// called.
func MustWriteToFile(t testing.TB, b []byte, baseName string) {
	t.Helper()

	if err := ioutil.WriteFile(ExpandPath(baseName), b, 0644); err != nil {
		t.Fatal(err)
	}
}

// MustReadFromFile reads testdata/baseName and returns the raw content. On
// errors, t.Fatal() is called.
func MustReadFromFile(t testing.TB, baseName string) []byte {
	t.Helper()

	name := filepath.Join("testdata", baseName)
	b, err := ioutil.ReadFile(name)
	if err != nil {
		t.Fatal(err)
	}
	return b
}

// ExpandPath returns testdata/file.
func ExpandPath(file string) string {
	return filepath.Join("testdata", file)
}

// MustParseIA parses s and returns the corresponding addr.IA object. It
// panics if s is not a valid ISD-AS representation.
func MustParseIA(s string) addr.IA {
	ia, err := addr.IAFromString(s)
	if err != nil {
		panic(err)
	}
	return ia
}

// MustParseAS parses s and returns the corresponding addr.AS object. It panics
// if s is not valid AS representation.
func MustParseAS(s string) addr.AS {
	ia, err := addr.ASFromString(s)
	if err != nil {
		panic(err)
	}
	return ia
}

// MustParseASes parses a list of comma separated AS strings. It panics in case
// parsing fails.
func MustParseASes(list string) []addr.AS {
	l := strings.Split(list, ",")
	var ases []addr.AS
	for _, raw := range l {
		ases = append(ases, MustParseAS(raw))
	}
	return ases
}

// MustParseHexString parses s and returns the corresponding byte slice.
// It panics if the decoding fails.
func MustParseHexString(s string) []byte {
	// remove whitespace
	reg, err := regexp.Compile(`\s+`)
	if err != nil {
		panic(err)
	}
	s = reg.ReplaceAllString(s, "")

	decoded, err := hex.DecodeString(s)
	if err != nil {
		panic(err)
	}
	return decoded
}

// MustParseCIDR parses s and returns the corresponding net.IPNet object. It
// fails the test if s is not a valid CIDR string.
func MustParseCIDR(t *testing.T, s string) *net.IPNet {
	t.Helper()

	_, network, err := net.ParseCIDR(s)
	require.NoError(t, err)
	return network
}

// MustParseCIDRs parses the CIDR entries and returns a list containing the
// parsed net.IPNet objects.
func MustParseCIDRs(t *testing.T, entries ...string) []*net.IPNet {
	t.Helper()

	result := make([]*net.IPNet, 0, len(entries))
	for _, e := range entries {
		result = append(result, MustParseCIDR(t, e))
	}
	return result
}

// MustParseUDPAddr parses s and returns the corresponding net.UDPAddr object.
// It fails the test if s is not a valid UDP address string.
func MustParseUDPAddr(t *testing.T, s string) *net.UDPAddr {
	t.Helper()

	a, err := net.ResolveUDPAddr("udp", s)
	require.NoError(t, err)
	if ipv4 := a.IP.To4(); ipv4 != nil {
		a.IP = ipv4
	}
	return a
}

// AssertReadReturnsBetween will call t.Fatalf if the first read from the
// channel doesn't happen between x and y.
func AssertReadReturnsBetween(t testing.TB, ch <-chan struct{}, x, y time.Duration) {
	AssertReadDoesNotReturnBefore(t, ch, x)
	// Above aborts the test if it returns before x time passed, so if we get
	// here x time has passed.
	AssertReadReturnsBefore(t, ch, y-x)
}

// AssertReadReturnsBefore will call t.Fatalf if the first read from the
// channel doesn't happen before timeout.
func AssertReadReturnsBefore(t testing.TB, ch <-chan struct{}, timeout time.Duration) {
	t.Helper()
	select {
	case <-ch:
	case <-time.After(timeout):
		t.Fatalf("goroutine took too long to finish")
	}
}

// AssertReadDoesNotReturnBefore will call t.Fatalf if the first read from the
// channel happens before timeout.
func AssertReadDoesNotReturnBefore(t testing.TB, ch <-chan struct{}, timeout time.Duration) {
	select {
	case <-ch:
		t.Fatalf("goroutine finished too quickly")
	case <-time.After(timeout):
	}
}

// AssertError checks that err is not nil if expectError is true and that is it nil otherwise
func AssertError(t *testing.T, err error, expectError bool) {
	if expectError {
		assert.Error(t, err)
	} else {
		assert.NoError(t, err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"container/ring"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"log"
	_ "net"
	"net/http"
	"regexp"
	"runtime"
	"time"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func get_news(key string, topic string) {
	rssurl := "https://news.google.co.kr/news?pz=1&cf=all&ned=kr&hl=en&output=rss&topic=" + topic
	log.Printf("Getting news to cachemap[%s] from %s\n", key, rssurl)
	r, _ := http.Get(rssurl)
	defer r.Body.Close()
	b, _ := ioutil.ReadAll(r.Body)
	//ioutil.WriteFile("news.xml", b, 0666) // write rss to disk
	c := regexp.MustCompile("(.+) - [^-]+$")
	//d, _ := xml.NewDecoder(r.Body)
	v := RSSResult{}
	_ = xml.Unmarshal(b, &v)
	for i, _ := range v.Titles { // reverse
		t := v.Titles[len(v.Titles)-1-i]
		s := c.FindAllStringSubmatch(t, -1)[0][1]
		//fmt.Println(s)
		dup := false
		for _, v := range cachemap {
			v.ring.Do(func(o interface{}) { // check if already exists
				if dup || o == nil {
					return
				}
				if o == s {
					dup = true
				}
			})
		}
		if dup {
			fmt.Printf("%s is removed because of duplication\n", s)
			continue
		}
		cachemap[key].addRing(s)
		fmt.Println(s)
	}
}

type RSSResult struct {
	XMLName xml.Name `xml:"rss"`
	Titles  []string `xml:"channel>item>title"`
}
type CacheItem struct {
	topic string
	ring  *ring.Ring
}

func (cacheItem *CacheItem) addRing(value interface{}) {
	cacheItem.ring = cacheItem.ring.Prev()
	cacheItem.ring.Value = value
}

var cachemap = map[string]*CacheItem{
	"prim": &CacheItem{"", ring.New(10)},
	"soc":  &CacheItem{"y", ring.New(10)},
	"pol":  &CacheItem{"p", ring.New(10)},
	"eco":  &CacheItem{"b", ring.New(10)},
	"int":  &CacheItem{"w", ring.New(10)},
	"cul":  &CacheItem{"l", ring.New(10)},
	"cel":  &CacheItem{"e", ring.New(10)},
	"sci":  &CacheItem{"t", ring.New(10)},
}

var cacheready bool = false

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // use all physical cores

	http.HandleFunc("/", handler)
	http.HandleFunc("/news", newshandler)
	http.HandleFunc("/weather", newshandler)
	go http.ListenAndServe(":81", nil)

	for {
		log.Println("Refreshing cachemap")
		for k, v := range cachemap {
			get_news(k, v.topic)
		}

		for k, v := range cachemap {
			v.ring.Do(func(o interface{}) {
				fmt.Println("cache", k, ":", o)
			})
		}
		time.Sleep(3 * time.Minute)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	fmt.Fprintf(w, "Got tired of life? Want some fun? Contact me instead of hacking hospitals : sbw228@gmail.com")
}

type JSONnews struct {
	Section string
	News    string
}

func newshandler(w http.ResponseWriter, r *http.Request) {
	ori := r.Header.Get("Origin")
	w.Header().Set("Access-Control-Allow-Origin", ori)
	w.Header().Set("Access-Control-Allow-Methods", "GET")
	m := make(map[string][]string)
	for k, v := range cachemap {
		v.ring.Do(func(o interface{}) {
			if o != nil {
				m[k] = append(m[k], o.(string))
			}
		})
	}
	json.NewEncoder(w).Encode(m)
	log.Printf("%s is retrieving cache\n", r.Host)
	/*for _, v := range cachemap {
		v.ring.Do(func(o interface{}) {

		})
	}*/
}
<commit_msg>english as default, remove debug msg, 15minute as refresh freq<commit_after>package main

import (
	"container/ring"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"log"
	_ "net"
	"net/http"
	"regexp"
	"runtime"
	"time"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func get_news(key string, topic string) {
	rssurl := "https://news.google.co.kr/news?pz=1&cf=all&ned=us&hl=en&output=rss&topic=" + topic
	log.Printf("Getting news to cachemap[%s] from %s\n", key, rssurl)
	r, _ := http.Get(rssurl)
	defer r.Body.Close()
	b, _ := ioutil.ReadAll(r.Body)
	//ioutil.WriteFile("news.xml", b, 0666) // write rss to disk
	c := regexp.MustCompile("(.+) - [^-]+$")
	//d, _ := xml.NewDecoder(r.Body)
	v := RSSResult{}
	_ = xml.Unmarshal(b, &v)
	for i, _ := range v.Titles { // reverse
		t := v.Titles[len(v.Titles)-1-i]
		s := c.FindAllStringSubmatch(t, -1)[0][1]
		//fmt.Println(s)
		dup := false
		for _, v := range cachemap {
			v.ring.Do(func(o interface{}) { // check if already exists
				if dup || o == nil {
					return
				}
				if o == s {
					dup = true
				}
			})
		}
		if dup {
			fmt.Printf("%s is removed because of duplication\n", s)
			continue
		}
		cachemap[key].addRing(s)
		fmt.Println(s)
	}
}

type RSSResult struct {
	XMLName xml.Name `xml:"rss"`
	Titles  []string `xml:"channel>item>title"`
}
type CacheItem struct {
	topic string
	ring  *ring.Ring
}

func (cacheItem *CacheItem) addRing(value interface{}) {
	cacheItem.ring = cacheItem.ring.Prev()
	cacheItem.ring.Value = value
}

var cachemap = map[string]*CacheItem{
	"prim": &CacheItem{"", ring.New(10)},
	"soc":  &CacheItem{"y", ring.New(10)},
	"pol":  &CacheItem{"p", ring.New(10)},
	"eco":  &CacheItem{"b", ring.New(10)},
	"int":  &CacheItem{"w", ring.New(10)},
	"cul":  &CacheItem{"l", ring.New(10)},
	"cel":  &CacheItem{"e", ring.New(10)},
	"sci":  &CacheItem{"t", ring.New(10)},
}

var cacheready bool = false

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // use all physical cores

	http.HandleFunc("/", handler)
	http.HandleFunc("/news", newshandler)
	http.HandleFunc("/weather", newshandler)
	go http.ListenAndServe(":81", nil)

	for {
		log.Println("Refreshing cachemap")
		for k, v := range cachemap {
			get_news(k, v.topic)
		}

		/* //debug purpose code
		for k, v := range cachemap {
			v.ring.Do(func(o interface{}) {
				fmt.Println("cache", k, ":", o)
			})
		} */
		time.Sleep(15 * time.Minute)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	fmt.Fprintf(w, "Got tired of life? Want some fun? Contact me instead of hacking hospitals : sbw228@gmail.com")
}

type JSONnews struct {
	Section string
	News    string
}

func newshandler(w http.ResponseWriter, r *http.Request) {
	ori := r.Header.Get("Origin")
	w.Header().Set("Access-Control-Allow-Origin", ori)
	w.Header().Set("Access-Control-Allow-Methods", "GET")
	m := make(map[string][]string)
	for k, v := range cachemap {
		v.ring.Do(func(o interface{}) {
			if o != nil {
				m[k] = append(m[k], o.(string))
			}
		})
	}
	json.NewEncoder(w).Encode(m)
	log.Printf("%s is retrieving cache\n", r.Host)
	/*for _, v := range cachemap {
		v.ring.Do(func(o interface{}) {

		})
	}*/
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pbdi "github.com/brotherlogic/discovery/proto"
	pb "github.com/brotherlogic/gobuildslave/proto"
	"github.com/brotherlogic/goserver/utils"

	//Needed to pull in gzip encoding init
	_ "google.golang.org/grpc/encoding/gzip"
)

func findServer(ctx context.Context, name, server string) (string, int) {
	conn, _ := grpc.Dial(utils.Discover, grpc.WithInsecure())
	defer conn.Close()

	registry := pbdi.NewDiscoveryServiceClient(conn)
	rs, _ := registry.ListAllServices(ctx, &pbdi.ListRequest{})

	for _, r := range rs.GetServices().Services {
		if r.Identifier == server && r.Name == name {
			return r.Ip, int(r.Port)
		}
	}

	return "", -1
}

func findServers(ctx context.Context) []*pbdi.RegistryEntry {
	conn, _ := grpc.Dial(utils.Discover, grpc.WithInsecure())
	defer conn.Close()

	registry := pbdi.NewDiscoveryServiceClient(conn)
	rs, _ := registry.ListAllServices(ctx, &pbdi.ListRequest{})

	list := make([]*pbdi.RegistryEntry, 0)
	for _, r := range rs.GetServices().Services {
		if r.Name == "gobuildslave" {
			list = append(list, r)
		}
	}

	return list
}

func main() {
	buildFlags := flag.NewFlagSet("BuildServer", flag.ExitOnError)
	var name = buildFlags.String("name", "", "Name of the binary to build")
	var server = buildFlags.String("server", "", "Name of the server to build on")
	var hosta = buildFlags.String("hosta", "", "Name of the server to build on")

	ctx, cancel := utils.BuildContext("gobuildslavecli-"+os.Args[1], "gobuildslave")
	defer cancel()

	if len(os.Args) <= 1 {
		fmt.Printf("Commands: build run\n")
	} else {
		switch os.Args[1] {
		case "build":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.BuildJob(ctx, &pb.JobSpec{Name: *name})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "run":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.Run(ctx, &pb.JobSpec{Name: *name, Server: *server})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "kill":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.Kill(ctx, &pb.JobSpec{Name: *name, Server: *server})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "list":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				res, err := registry.List(ctx, &pb.Empty{})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
				for _, r := range res.Details {
					fmt.Printf("%v (%v) - %v\n", r.Spec.Name, time.Unix(r.StartTime, 0).Format("02/01 15:04"), r)
				}
			}
		case "nlist":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				conn, err := grpc.Dial(*hosta+":53604", grpc.WithInsecure())
				if err != nil {
					log.Fatalf("Error dialling: %v", err)
				}
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.ListJobs(ctx, &pb.ListRequest{})
				if err != nil {
					log.Fatalf("Error listing job with: %v", err)
				}
				for _, r := range res.Jobs {
					fmt.Printf("%v {%v / %v}-> %v [%v] (%v)\n", r.Job.Name, r.GetPort(), r.GetRunningVersion(), r.State, r.GetSubState(), time.Unix(r.GetLastUpdateTime(), 0))
				}
			}
		case "nbuild":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				_, err := registry.RunJob(ctx, &pb.RunRequest{Job: &pb.Job{Name: "recordalerting", GoPath: "github.com/brotherlogic/recordalerting"}})
				if err != nil {
					log.Fatalf("Error listing job: %v", err)
				}
			}
		case "nconfig":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				conn, err := grpc.Dial(*hosta+":53604", grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.SlaveConfig(ctx, &pb.ConfigRequest{})
				if err != nil {
					log.Fatalf("Error listing job: %v", err)
				}
				fmt.Printf("%v\n", res)
			}
		case "nlistall":
			servers := findServers(ctx)

			if len(servers) == 0 {
				log.Fatalf("No Servers found!")
			}

			for _, s := range servers {
				conn, _ := grpc.Dial(s.GetIp()+":"+strconv.Itoa(int(s.GetPort())), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.ListJobs(ctx, &pb.ListRequest{})
				if err != nil {
					fmt.Printf("Error discovering job with: %v\n", err)
				} else {
					for _, r := range res.Jobs {
						fmt.Printf("%v:%v -> %v [%v] (%v)\n", r.Job.Name, s.GetIdentifier(), r.State, r.GetSubState(), time.Unix(r.GetLastUpdateTime(), 0))
					}
				}
			}
		}

	}
}
<commit_msg>Adds in CLI<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pbdi "github.com/brotherlogic/discovery/proto"
	pb "github.com/brotherlogic/gobuildslave/proto"
	"github.com/brotherlogic/goserver/utils"

	//Needed to pull in gzip encoding init
	_ "google.golang.org/grpc/encoding/gzip"
)

func findServer(ctx context.Context, name, server string) (string, int) {
	conn, _ := grpc.Dial(utils.Discover, grpc.WithInsecure())
	defer conn.Close()

	registry := pbdi.NewDiscoveryServiceClient(conn)
	rs, _ := registry.ListAllServices(ctx, &pbdi.ListRequest{})

	for _, r := range rs.GetServices().Services {
		if r.Identifier == server && r.Name == name {
			return r.Ip, int(r.Port)
		}
	}

	return "", -1
}

func findServers(ctx context.Context) []*pbdi.RegistryEntry {
	conn, _ := grpc.Dial(utils.Discover, grpc.WithInsecure())
	defer conn.Close()

	registry := pbdi.NewDiscoveryServiceClient(conn)
	rs, _ := registry.ListAllServices(ctx, &pbdi.ListRequest{})

	list := make([]*pbdi.RegistryEntry, 0)
	for _, r := range rs.GetServices().Services {
		if r.Name == "gobuildslave" {
			list = append(list, r)
		}
	}

	return list
}

func main() {
	buildFlags := flag.NewFlagSet("BuildServer", flag.ExitOnError)
	var name = buildFlags.String("name", "", "Name of the binary to build")
	var server = buildFlags.String("server", "", "Name of the server to build on")
	var hosta = buildFlags.String("hosta", "", "Name of the server to build on")

	ctx, cancel := utils.BuildContext("gobuildslavecli-"+os.Args[1], "gobuildslave")
	defer cancel()

	if len(os.Args) <= 1 {
		fmt.Printf("Commands: build run\n")
	} else {
		switch os.Args[1] {
		case "sd":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				_, err := registry.FullShutdown(ctx, &pb.ShutdownRequest{})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "build":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.BuildJob(ctx, &pb.JobSpec{Name: *name})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "run":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.Run(ctx, &pb.JobSpec{Name: *name, Server: *server})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "kill":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				_, err := registry.Kill(ctx, &pb.JobSpec{Name: *name, Server: *server})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
			}
		case "list":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewGoBuildSlaveClient(conn)
				res, err := registry.List(ctx, &pb.Empty{})
				if err != nil {
					log.Fatalf("Error building job: %v", err)
				}
				for _, r := range res.Details {
					fmt.Printf("%v (%v) - %v\n", r.Spec.Name, time.Unix(r.StartTime, 0).Format("02/01 15:04"), r)
				}
			}
		case "nlist":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				conn, err := grpc.Dial(*hosta+":53604", grpc.WithInsecure())
				if err != nil {
					log.Fatalf("Error dialling: %v", err)
				}
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.ListJobs(ctx, &pb.ListRequest{})
				if err != nil {
					log.Fatalf("Error listing job with: %v", err)
				}
				for _, r := range res.Jobs {
					fmt.Printf("%v {%v / %v}-> %v [%v] (%v)\n", r.Job.Name, r.GetPort(), r.GetRunningVersion(), r.State, r.GetSubState(), time.Unix(r.GetLastUpdateTime(), 0))
				}
			}
		case "nbuild":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				host, port := findServer(ctx, "gobuildslave", *server)

				conn, _ := grpc.Dial(host+":"+strconv.Itoa(port), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				_, err := registry.RunJob(ctx, &pb.RunRequest{Job: &pb.Job{Name: "recordalerting", GoPath: "github.com/brotherlogic/recordalerting"}})
				if err != nil {
					log.Fatalf("Error listing job: %v", err)
				}
			}
		case "nconfig":
			if err := buildFlags.Parse(os.Args[2:]); err == nil {
				conn, err := grpc.Dial(*hosta+":53604", grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.SlaveConfig(ctx, &pb.ConfigRequest{})
				if err != nil {
					log.Fatalf("Error listing job: %v", err)
				}
				fmt.Printf("%v\n", res)
			}
		case "nlistall":
			servers := findServers(ctx)

			if len(servers) == 0 {
				log.Fatalf("No Servers found!")
			}

			for _, s := range servers {
				conn, _ := grpc.Dial(s.GetIp()+":"+strconv.Itoa(int(s.GetPort())), grpc.WithInsecure())
				defer conn.Close()

				registry := pb.NewBuildSlaveClient(conn)
				res, err := registry.ListJobs(ctx, &pb.ListRequest{})
				if err != nil {
					fmt.Printf("Error discovering job with: %v\n", err)
				} else {
					for _, r := range res.Jobs {
						fmt.Printf("%v:%v -> %v [%v] (%v)\n", r.Job.Name, s.GetIdentifier(), r.State, r.GetSubState(), time.Unix(r.GetLastUpdateTime(), 0))
					}
				}
			}
		}

	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"

	"github.com/go-yaml/yaml"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "(en|de|nl|...)")
		os.Exit(1)
	}

	final := make(map[string]map[string][]string)

	for _, lang := range os.Args[1:] {
		fmt.Fprintln(os.Stderr, lang)
		f, err := os.Open("/home/manveru/.gem/ruby/1.9.1/gems/faker-1.0.1/lib/locales/" + lang + ".yml")
		if err != nil {
			panic(err)
		}

		in, err := ioutil.ReadAll(f)
		if err != nil {
			panic(err)
		}

		final[lang] = make(map[string][]string)

		out := make(map[string]map[string]map[string]map[string]interface{})
		err = yaml.Unmarshal(in, out)
		if err != nil {
			panic(err)
		}

		for _, v1 := range out { // language
			for _, v2 := range v1 { // faker
				for k3, v3 := range v2 {
					for k4, v4 := range v3 {
						key := k3 + "." + k4
						switch v4.(type) {
						case []interface{}:
							for k5, v5 := range v4.([]interface{}) {
								switch v5.(type) {
								case string:
									final[lang][key] = append(final[lang][key], v5.(string))
								case []interface{}:
									arr := make([]string, 0)
									for _, v6 := range v5.([]interface{}) {
										arr = append(arr, v6.(string))
									}
									key5 := fmt.Sprintf("%s.%d", key, k5)
									sort.Strings(arr)
									final[lang][key5] = arr
								default:
									panic(fmt.Sprintf("%#v", v5))
								}
							}
						case map[interface{}]interface{}:
							for k5, v5 := range v4.(map[interface{}]interface{}) {
								switch v5.(type) {
								case []interface{}:
									arr := make([]string, 0)
									for _, v6 := range v5.([]interface{}) {
										arr = append(arr, v6.(string))
									}
									var key5 string
									switch k5.(type) {
									case string:
										key5 = fmt.Sprintf("%s.%s", key, k5)
									default:
										panic(fmt.Sprintf("%#v", k5))
									}
									sort.Strings(arr)
									final[lang][key5] = arr
								default:
									panic("")
								}
							}
						default:
							panic("")
						}
					}
				}
			}
		}
	}

	fmt.Println("package faker\n")
	fmt.Println("var Dict = map[string]map[string][]string{")
	for language, maps := range final {
		fmt.Printf("\t%q: map[string][]string{\n", language)
		for key, values := range maps {
			fmt.Printf("\t\t%q: []string{\n", key)
			for _, value := range values {
				fmt.Printf("\t\t\t%q,\n", value)
			}
			fmt.Println("\t\t},")
		}
		fmt.Println("\t},")
	}
	fmt.Println("}")
}
<commit_msg>using correct import path for yaml the go yaml project has switched its repository to github, but the import path is using gopkg.in, updating for faker. Thanks to @AlekSi for the ht on this!<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"

	yaml "gopkg.in/yaml.v2"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "(en|de|nl|...)")
		os.Exit(1)
	}

	final := make(map[string]map[string][]string)

	for _, lang := range os.Args[1:] {
		fmt.Fprintln(os.Stderr, lang)
		f, err := os.Open("/home/manveru/.gem/ruby/1.9.1/gems/faker-1.0.1/lib/locales/" + lang + ".yml")
		if err != nil {
			panic(err)
		}

		in, err := ioutil.ReadAll(f)
		if err != nil {
			panic(err)
		}

		final[lang] = make(map[string][]string)

		out := make(map[string]map[string]map[string]map[string]interface{})
		err = yaml.Unmarshal(in, out)
		if err != nil {
			panic(err)
		}

		for _, v1 := range out { // language
			for _, v2 := range v1 { // faker
				for k3, v3 := range v2 {
					for k4, v4 := range v3 {
						key := k3 + "." + k4
						switch v4.(type) {
						case []interface{}:
							for k5, v5 := range v4.([]interface{}) {
								switch v5.(type) {
								case string:
									final[lang][key] = append(final[lang][key], v5.(string))
								case []interface{}:
									arr := make([]string, 0)
									for _, v6 := range v5.([]interface{}) {
										arr = append(arr, v6.(string))
									}
									key5 := fmt.Sprintf("%s.%d", key, k5)
									sort.Strings(arr)
									final[lang][key5] = arr
								default:
									panic(fmt.Sprintf("%#v", v5))
								}
							}
						case map[interface{}]interface{}:
							for k5, v5 := range v4.(map[interface{}]interface{}) {
								switch v5.(type) {
								case []interface{}:
									arr := make([]string, 0)
									for _, v6 := range v5.([]interface{}) {
										arr = append(arr, v6.(string))
									}
									var key5 string
									switch k5.(type) {
									case string:
										key5 = fmt.Sprintf("%s.%s", key, k5)
									default:
										panic(fmt.Sprintf("%#v", k5))
									}
									sort.Strings(arr)
									final[lang][key5] = arr
								default:
									panic("")
								}
							}
						default:
							panic("")
						}
					}
				}
			}
		}
	}

	fmt.Println("package faker\n")
	fmt.Println("var Dict = map[string]map[string][]string{")
	for language, maps := range final {
		fmt.Printf("\t%q: map[string][]string{\n", language)
		for key, values := range maps {
			fmt.Printf("\t\t%q: []string{\n", key)
			for _, value := range values {
				fmt.Printf("\t\t\t%q,\n", value)
			}
			fmt.Println("\t\t},")
		}
		fmt.Println("\t},")
	}
	fmt.Println("}")
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd.

// +build ignore

// Command print fetches and prints package.
//
// Usage: go run print.go importPath
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/golang/gddo//gosrc"
)

var (
	etag    = flag.String("etag", "", "Etag")
	local   = flag.String("local", "", "Get package from local workspace.")
	present = flag.Bool("present", false, "Get presentation.")
)

func main() {
	flag.Parse()
	gosrc.SetUserAgent("print")
	if len(flag.Args()) != 1 {
		log.Fatal("Usage: go run print.go importPath")
	}
	if *present {
		printPresentation(flag.Args()[0])
	} else {
		printDir(flag.Args()[0])
	}
}

func printDir(path string) {
	if *local != "" {
		gosrc.SetLocalDevMode(*local)
	}
	dir, err := gosrc.Get(http.DefaultClient, path, *etag)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("ImportPath    ", dir.ImportPath)
	fmt.Println("ResovledPath  ", dir.ResolvedPath)
	fmt.Println("ProjectRoot   ", dir.ProjectRoot)
	fmt.Println("ProjectName   ", dir.ProjectName)
	fmt.Println("ProjectURL    ", dir.ProjectURL)
	fmt.Println("VCS           ", dir.VCS)
	fmt.Println("Etag          ", dir.Etag)
	fmt.Println("BrowseURL     ", dir.BrowseURL)
	fmt.Println("Subdirectories", strings.Join(dir.Subdirectories, ", "))
	fmt.Println("LineFmt       ", dir.LineFmt)
	fmt.Println("Files:")
	for _, file := range dir.Files {
		fmt.Printf("%30s %5d %s\n", file.Name, len(file.Data), file.BrowseURL)
	}
}

func printPresentation(path string) {
	pres, err := gosrc.GetPresentation(http.DefaultClient, path)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", pres.Files[pres.Filename])
	for name, data := range pres.Files {
		if name != pres.Filename {
			fmt.Printf("---------- %s ----------\n%s\n", name, data)
		}
	}
}
<commit_msg>gosrc: repair print.go program.<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd.

// +build ignore

// Command print fetches and prints package.
//
// Usage: go run print.go importPath
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/golang/gddo/gosrc"
)

var (
	etag    = flag.String("etag", "", "Etag")
	local   = flag.String("local", "", "Get package from local workspace.")
	present = flag.Bool("present", false, "Get presentation.")
)

func main() {
	flag.Parse()
	if len(flag.Args()) != 1 {
		log.Fatal("Usage: go run print.go importPath")
	}
	if *present {
		printPresentation(flag.Args()[0])
	} else {
		printDir(flag.Args()[0])
	}
}

func printDir(path string) {
	if *local != "" {
		gosrc.SetLocalDevMode(*local)
	}
	dir, err := gosrc.Get(http.DefaultClient, path, *etag)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("ImportPath    ", dir.ImportPath)
	fmt.Println("ResovledPath  ", dir.ResolvedPath)
	fmt.Println("ProjectRoot   ", dir.ProjectRoot)
	fmt.Println("ProjectName   ", dir.ProjectName)
	fmt.Println("ProjectURL    ", dir.ProjectURL)
	fmt.Println("VCS           ", dir.VCS)
	fmt.Println("Etag          ", dir.Etag)
	fmt.Println("BrowseURL     ", dir.BrowseURL)
	fmt.Println("Subdirectories", strings.Join(dir.Subdirectories, ", "))
	fmt.Println("LineFmt       ", dir.LineFmt)
	fmt.Println("Files:")
	for _, file := range dir.Files {
		fmt.Printf("%30s %5d %s\n", file.Name, len(file.Data), file.BrowseURL)
	}
}

func printPresentation(path string) {
	pres, err := gosrc.GetPresentation(http.DefaultClient, path)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", pres.Files[pres.Filename])
	for name, data := range pres.Files {
		if name != pres.Filename {
			fmt.Printf("---------- %s ----------\n%s\n", name, data)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

/*

This program is meant to run under remtcl ( See https://github.com/rra/remctl )

It will take values from stdin and the remctl environment to write a status
message to the nagios command file.

( From http://nagios.sourceforge.net/docs/3_0/passivechecks.html )

External applications can submit passive service check results to Nagios by writing a
PROCESS_SERVICE_CHECK_RESULT external command to the external command file.

The format of the command is as follows:

[<timestamp>] PROCESS_SERVICE_CHECK_RESULT;<host_name>;<svc_description>;<return_code>;<plugin_output>

where...

timestamp is the time in time_t format (seconds since the UNIX epoch) that the service check
was perfomed (or submitted). Please note the single space after the right bracket.

host_name is the short name of the host associated with the service in the service definition

svc_description is the description of the service as specified in the service definition

return_code is the return code of the check (0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN)

plugin_output is the text output of the service check (i.e. the plugin output)

(From http://www.eyrie.org/~eagle/software/remctl/remctld.html )

ENVIRONMENT

The following environment variables will be set for any commands run via remctld:

REMOTE_USER
REMUSER
Set to the Kerberos principal of the authenticated client. REMUSER has always been set by remctld;
REMOTE_USER is also set (to the same value) starting with remctl 2.1.

REMOTE_ADDR
The IP address of the remote host. Currently, this is always an IPv4 address, but in the future
it may be set to an IPv6 address. This environment variable was added in remctl 2.1.

REMOTE_HOST
The hostname of the remote host, if it was available. If reverse name resolution failed,
this environment variable will not be set. This variable was added in remctl 2.1.

REMCTL_COMMAND
The command string that caused this command to be run. This variable will contain only
the command, not the subcommand or any additional arguments (which are passed as command arguments).
This variable was added in remctl 2.16.

*/

/* Need to duplicate this code from nsca

CMT: writes service/host check results to the Nagios command file
static int write_check_result(char *host_name, char *svc_description, int return_code, char *plugin_output, time_t check_time){

        if(aggregate_writes==FALSE){
                if(open_command_file()==ERROR)
                        return ERROR;
                }

        if(!strcmp(svc_description,""))
                fprintf(command_file_fp,"[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n",(unsigned long)check_time,host_name,return_code,plugin_output);
        else
                fprintf(command_file_fp,"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,host_name,svc_description,return_code,plugin_output);

        if(aggregate_writes==FALSE)
                close_command_file();
        else
                CMT: if we don't fflush() then we're writing in 4k non-CR-terminated blocks, and
                 * anything else (eg. pscwatch) which writes to the file will be writing into
                 * the middle of our commands.

                fflush(command_file_fp);

        return OK;
        }

CMT: opens the command file for writing
static int open_command_file(void){
        struct stat statbuf;

        CMT: file is already open
        if(command_file_fp!=NULL)
                return OK;

        CMT: command file doesn't exist - monitoring app probably isn't running...
        if(stat(command_file,&statbuf)){

                if(debug==TRUE)
                        syslog(LOG_ERR,"Command file '%s' does not exist, attempting to use alternate dump file '%s' for output",command_file,alternate_dump_file);

                CMT: try and write checks to alternate dump file
                command_file_fp=fopen(alternate_dump_file,"a");
                if(command_file_fp==NULL){
                        if(debug==TRUE)
                                syslog(LOG_ERR,"Could not open alternate dump file '%s' for appending",alternate_dump_file);
                        return ERROR;
                        }

                return OK;
                }

        CMT: open the command file for writing or appending
        command_file_fp=fopen(command_file,(append_to_file==TRUE)?"a":"w");
        if(command_file_fp==NULL){
                if(debug==TRUE)
                        syslog(LOG_ERR,"Could not open command file '%s' for %s",command_file,(append_to_file==TRUE)?"appending":"writing");
                return ERROR;
                }

        return OK;
        }

CMT: closes the command file
static void close_command_file(void){

        fclose(command_file_fp);
        command_file_fp=NULL;

        return;
        }

*/

func send_pasv(cmd_file string, message string) bool {

	fd, err := os.OpenFile(cmd_file, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		panic(err)
	}

	defer fd.Close()

	if _, err = fd.WriteString(message); err != nil {
		panic(err)
	}
	return true
}

func get_remuser() string {
	remuser := os.Getenv("REMUSER")
	if len(remuser) == 0 {
		panic(errors.New("REMUSER not set"))
	}
	//REMUSER should look like host/foobar.slac.stanford.edu
	if strings.Index(remuser, "/") > -1 {
		remuser = strings.Split(remuser, "/")[1]
	}
	return remuser
}

func get_host() string {
	//First see if we have REMOTE_HOST
	remhost := os.Getenv("REMOTE_HOST")
	if len(remhost) == 0 {
		remhost = get_remuser()
	}
	//We should proably complain loudly at this point if we
	//don't have a string that looks like a FQDN.
	// Trim domain
	result := strings.Split(remhost, ".")[0]
	return result
}

func get_service() (service string, code int, message string) {
	return "ranger", 1, "ranger found an error"
}

/*
Need to return this string
"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,host_name,svc_description,return_code,plugin_output);
*/

func get_alert() string {
	epoch := int32(time.Now().Unix()) // This is 32 bit seconds since Unix epoch.
	host_name := get_host()
	service, code, message := get_service()
	alert := fmt.Sprintf("[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", epoch, host_name, service, code, message)
	return alert
}

// We need to find nagios cmd file, read config file or cmdline arg?
var (
	verbose = flag.Bool("verbose", false, "Verbose")
	cmdfile = flag.String("cmd", "/var/nagios/rw/nagios.cmd", "Path to nagios command file")
)

func main() {

	flag.Parse()
	// Read status and message from STDIN
	alert := get_alert()
	send_pasv(*cmdfile, alert)
	if *verbose {
		fmt.Printf("Sent alert: %q\n", alert)
	}
}
<commit_msg>First fully working version of server<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"
)

/*

This program is meant to run under remtcl ( See https://github.com/rra/remctl )

It will take values from stdin and the remctl environment to write a status
message to the nagios command file.

( From http://nagios.sourceforge.net/docs/3_0/passivechecks.html )

External applications can submit passive service check results to Nagios by writing a
PROCESS_SERVICE_CHECK_RESULT external command to the external command file.

The format of the command is as follows:

[<timestamp>] PROCESS_SERVICE_CHECK_RESULT;<hostName>;<svc_description>;<return_code>;<plugin_output>

where...

timestamp is the time in time_t format (seconds since the UNIX epoch) that the service check
was perfomed (or submitted). Please note the single space after the right bracket.

hostName is the short name of the host associated with the service in the service definition

svc_description is the description of the service as specified in the service definition

return_code is the return code of the check (0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN)

plugin_output is the text output of the service check (i.e. the plugin output)

(From http://www.eyrie.org/~eagle/software/remctl/remctld.html )

ENVIRONMENT

The following environment variables will be set for any commands run via remctld:

REMOTE_USER
REMUSER
Set to the Kerberos principal of the authenticated client. REMUSER has always been set by remctld;
REMOTE_USER is also set (to the same value) starting with remctl 2.1.

REMOTE_ADDR
The IP address of the remote host. Currently, this is always an IPv4 address, but in the future
it may be set to an IPv6 address. This environment variable was added in remctl 2.1.

REMOTE_HOST
The hostname of the remote host, if it was available. If reverse name resolution failed,
this environment variable will not be set. This variable was added in remctl 2.1.

REMCTL_COMMAND
The command string that caused this command to be run. This variable will contain only
the command, not the subcommand or any additional arguments (which are passed as command arguments).
This variable was added in remctl 2.16.

*/

/* Need to duplicate this code from nsca

CMT: writes service/host check results to the Nagios command file
static int write_check_result(char *hostName, char *svc_description, int return_code, char *plugin_output, time_t check_time){

        if(aggregate_writes==FALSE){
                if(open_command_file()==ERROR)
                        return ERROR;
                }

        if(!strcmp(svc_description,""))
                fprintf(command_file_fp,"[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n",(unsigned long)check_time,hostName,return_code,plugin_output);
        else
                fprintf(command_file_fp,"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,hostName,svc_description,return_code,plugin_output);

        if(aggregate_writes==FALSE)
                close_command_file();
        else
                CMT: if we don't fflush() then we're writing in 4k non-CR-terminated blocks, and
                 * anything else (eg. pscwatch) which writes to the file will be writing into
                 * the middle of our commands.

                fflush(command_file_fp);

        return OK;
        }

CMT: opens the command file for writing
static int open_command_file(void){
        struct stat statbuf;

        CMT: file is already open
        if(command_file_fp!=NULL)
                return OK;

        CMT: command file doesn't exist - monitoring app probably isn't running...
        if(stat(command_file,&statbuf)){

                if(debug==TRUE)
                        syslog(LOG_ERR,"Command file '%s' does not exist, attempting to use alternate dump file '%s' for output",command_file,alternate_dump_file);

                CMT: try and write checks to alternate dump file
                command_file_fp=fopen(alternate_dump_file,"a");
                if(command_file_fp==NULL){
                        if(debug==TRUE)
                                syslog(LOG_ERR,"Could not open alternate dump file '%s' for appending",alternate_dump_file);
                        return ERROR;
                        }

                return OK;
                }

        CMT: open the command file for writing or appending
        command_file_fp=fopen(command_file,(append_to_file==TRUE)?"a":"w");
        if(command_file_fp==NULL){
                if(debug==TRUE)
                        syslog(LOG_ERR,"Could not open command file '%s' for %s",command_file,(append_to_file==TRUE)?"appending":"writing");
                return ERROR;
                }

        return OK;
        }

CMT: closes the command file
static void close_command_file(void){

        fclose(command_file_fp);
        command_file_fp=NULL;

        return;
        }

*/

func sendPasv(cmdFile string, message string) bool {

	fd, err := os.OpenFile(cmdFile, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		panic(err)
	}

	defer fd.Close()

	if _, err = fd.WriteString(message); err != nil {
		panic(err)
	}
	return true
}

func getRemuser() string {
	remuser := os.Getenv("REMUSER")
	if len(remuser) == 0 {
		panic(errors.New("REMUSER not set"))
	}
	//REMUSER should look like host/foobar.slac.stanford.edu
	if strings.Index(remuser, "/") > -1 {
		remuser = strings.Split(remuser, "/")[1]
	}
	return remuser
}

func getHost() string {
	//First see if we have REMOTE_HOST
	remhost := os.Getenv("REMOTE_HOST")
	if len(remhost) == 0 {
		remhost = getRemuser()
	}
	//We should proably complain loudly at this point if we
	//don't have a string that looks like a FQDN.
	// Trim domain
	result := strings.Split(remhost, ".")[0]
	return result
}

//Read results from STDIN
func getService() (service string, code int, message string) {
	var err error
	//Validate data
	bio := bufio.NewScanner(os.Stdin)
	bio.Scan()
	line := bio.Text()
	tokens := strings.Split(line, ";")
	service = tokens[0]
	code, err = strconv.Atoi(tokens[1])
	if err != nil || code < 0 || code > 4 {
		if code < 0 || code > 4 {
			err = fmt.Errorf("nagios check code value is invalid: %d", code)
		}
		panic(err)
	}
	message = tokens[2]
	return
}

/*
Need to return this string
"[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",(unsigned long)check_time,hostName,svc_description,return_code,plugin_output);
*/

func getAlert() string {
	epoch := int32(time.Now().Unix()) // This is 32 bit seconds since Unix epoch.
	hostName := getHost()
	service, code, message := getService()
	alert := fmt.Sprintf("[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", epoch, hostName, service, code, message)
	return alert
}

// We need to find nagios cmd file, read config file or cmdline arg?
var (
	verbose = flag.Bool("verbose", false, "Verbose")
	cmdfile = flag.String("cmd", "/var/nagios/rw/nagios.cmd", "Path to nagios command file")
)

func main() {

	flag.Parse()
	// Read status and message from STDIN
	alert := getAlert()
	sendPasv(*cmdfile, alert)
	if *verbose {
		fmt.Printf("Sent alert: %q\n", alert)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package base

import (
	"flag"
	"fmt"

	"v.io/jiri/profiles"
	"v.io/jiri/tool"
	"v.io/x/lib/envvar"
)

const (
	profileName    = "base"
	profileVersion = "1"
)

// The base profile is just a shorthand for go+syncbase.
var baseProfiles = []string{"go", "syncbase"}

func init() {
	profiles.Register(profileName, &Manager{})
}

type Manager struct {
	root string
}

func (Manager) Name() string {
	return profileName
}

func (m Manager) String() string {
	return fmt.Sprintf("%s version:%s root:%s", profileName, profileVersion, m.root)
}

func (m Manager) Root() string {
	return m.root
}

func (m *Manager) SetRoot(root string) {
	m.root = root
}

func (m *Manager) AddFlags(flags *flag.FlagSet, action profiles.Action) {
}

func (m *Manager) Install(ctx *tool.Context, target profiles.Target) error {
	// Install packages
	if target.OS == "linux" {
		if err := profiles.InstallPackages(ctx, []string{"libssl-dev"}); err != nil {
			return err
		}
	}
	// Install profiles.
	for _, profile := range baseProfiles {
		if err := profiles.EnsureProfileTargetIsInstalled(ctx, profile, target, m.root); err != nil {
			return err
		}
	}
	// Merge the environments for go and syncbase and store it in the base profile.
	merged, err := profiles.MergeEnvFromProfiles(profiles.CommonConcatVariables(), profiles.CommonIgnoreVariables(), envvar.VarsFromSlice(target.Env.Vars), target, "syncbase", "go")
	if err != nil {
		return err
	}
	target.Env.Vars = merged
	target.Version = profileVersion
	return profiles.AddProfileTarget(profileName, target)
}

func (m *Manager) Uninstall(ctx *tool.Context, target profiles.Target) error {
	for _, profile := range baseProfiles {
		if err := profiles.EnsureProfileTargetIsUninstalled(ctx, profile, target, m.root); err != nil {
			return err
		}
	}
	profiles.RemoveProfileTarget(profileName, target)
	return nil
}

func (m *Manager) Update(ctx *tool.Context, target profiles.Target) error {
	update, err := profiles.ProfileTargetNeedsUpdate(profileName, target, profileVersion)
	if err != nil {
		return err
	}
	if !update {
		return nil
	}
	return profiles.ErrNoIncrementalUpdate
}
<commit_msg>v.io/x/devtools: make sure GOARCH, GOOS, GOPATH are written to profiles.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package base

import (
	"flag"
	"fmt"

	"v.io/jiri/profiles"
	"v.io/jiri/tool"
	"v.io/x/lib/envvar"
)

const (
	profileName    = "base"
	profileVersion = "1"
)

// The base profile is just a shorthand for go+syncbase.
var baseProfiles = []string{"go", "syncbase"}

func init() {
	profiles.Register(profileName, &Manager{})
}

type Manager struct {
	root string
}

func (Manager) Name() string {
	return profileName
}

func (m Manager) String() string {
	return fmt.Sprintf("%s version:%s root:%s", profileName, profileVersion, m.root)
}

func (m Manager) Root() string {
	return m.root
}

func (m *Manager) SetRoot(root string) {
	m.root = root
}

func (m *Manager) AddFlags(flags *flag.FlagSet, action profiles.Action) {
}

func (m *Manager) Install(ctx *tool.Context, target profiles.Target) error {
	// Install packages
	if target.OS == "linux" {
		if err := profiles.InstallPackages(ctx, []string{"libssl-dev"}); err != nil {
			return err
		}
	}
	// Install profiles.
	for _, profile := range baseProfiles {
		if err := profiles.EnsureProfileTargetIsInstalled(ctx, profile, target, m.root); err != nil {
			return err
		}
	}
	// Merge the environments for go and syncbase and store it in the base profile.
	merged, err := profiles.MergeEnvFromProfiles(profiles.CommonConcatVariables(), nil, envvar.VarsFromSlice(target.Env.Vars), target, "syncbase", "go")
	if err != nil {
		return err
	}
	target.Env.Vars = merged
	target.Version = profileVersion
	return profiles.AddProfileTarget(profileName, target)
}

func (m *Manager) Uninstall(ctx *tool.Context, target profiles.Target) error {
	for _, profile := range baseProfiles {
		if err := profiles.EnsureProfileTargetIsUninstalled(ctx, profile, target, m.root); err != nil {
			return err
		}
	}
	profiles.RemoveProfileTarget(profileName, target)
	return nil
}

func (m *Manager) Update(ctx *tool.Context, target profiles.Target) error {
	update, err := profiles.ProfileTargetNeedsUpdate(profileName, target, profileVersion)
	if err != nil {
		return err
	}
	if !update {
		return nil
	}
	return profiles.ErrNoIncrementalUpdate
}
<|endoftext|>


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

package identifiers

import (
	"context"
	"testing"

	"github.com/golang/protobuf/proto"

	"kythe.io/kythe/go/storage/table"
	"kythe.io/kythe/go/test/testutil"
	ipb "kythe.io/kythe/proto/identifier_proto"
	srvpb "kythe.io/kythe/proto/serving_proto"
)

var matchTable = Table{testProtoTable{
	"foo::bar": &srvpb.IdentifierMatch{
		Node: []*srvpb.IdentifierMatch_Node{
			{"kythe://corpus?lang=c++", "record", "class"},
			{"kythe://corpus?lang=rust", "record", "struct"},
		},
		BaseName:      "bar",
		QualifiedName: "foo::bar",
	},

	"com.java.package.Interface": &srvpb.IdentifierMatch{
		Node: []*srvpb.IdentifierMatch_Node{
			{"kythe://habeas?lang=java", "record", "interface"},
		},
		BaseName:      "Interface",
		QualifiedName: "com.java.package.Interface",
	},
}}

var tests = []testCase{
	{
		ipb.FindRequest{"foo::bar", nil, nil},
		[]*ipb.FindReply_Match{
			{"kythe://corpus?lang=c++", "record", "class", "bar", "foo::bar"},
			{"kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"},
		},
	},
	{
		ipb.FindRequest{"foo::bar", nil, []string{"rust"}},
		[]*ipb.FindReply_Match{
			{"kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"},
		},
	},
	{
		ipb.FindRequest{"com.java.package.Interface", []string{"habeas"}, nil},
		[]*ipb.FindReply_Match{
			{"kythe://habeas?lang=java", "record", "interface", "Interface", "com.java.package.Interface"},
		},
	},
	{
		ipb.FindRequest{"com.java.package.Interface", []string{"corpus"}, nil},
		[]*ipb.FindReply_Match{},
	},
}

func TestFind(t *testing.T) {
	for _, test := range tests {
		reply, err := matchTable.Find(context.TODO(), &test.FindRequest)
		if err != nil {
			t.Errorf("unexpected error for request %v: %v", test.FindRequest, err)
		}

		if err := testutil.DeepEqual(test.Matches, reply.Matches); err != nil {
			t.Error(err)
		}
	}
}

type testCase struct {
	ipb.FindRequest
	Matches []*ipb.FindReply_Match
}

type testProtoTable map[string]proto.Message

func (t testProtoTable) Put(_ context.Context, key []byte, val proto.Message) error {
	t[string(key)] = val
	return nil
}

func (t testProtoTable) Lookup(_ context.Context, key []byte, msg proto.Message) error {
	m, ok := t[string(key)]
	if !ok {
		return table.ErrNoSuchKey
	}
	proto.Merge(msg, m)
	return nil
}

func (t testProtoTable) Buffered() table.BufferedProto { panic("UNIMPLEMENTED") }

func (t testProtoTable) Close(_ context.Context) error { return nil }
<commit_msg>Proto-proof the identifiers_test<commit_after>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package identifiers

import (
	"context"
	"testing"

	"github.com/golang/protobuf/proto"

	"kythe.io/kythe/go/storage/table"
	"kythe.io/kythe/go/test/testutil"
	ipb "kythe.io/kythe/proto/identifier_proto"
	srvpb "kythe.io/kythe/proto/serving_proto"
)

var matchTable = Table{testProtoTable{
	"foo::bar": &srvpb.IdentifierMatch{
		Node: []*srvpb.IdentifierMatch_Node{
			node("kythe://corpus?lang=c++", "record", "class"),
			node("kythe://corpus?lang=rust", "record", "struct"),
		},
		BaseName:      "bar",
		QualifiedName: "foo::bar",
	},

	"com.java.package.Interface": &srvpb.IdentifierMatch{
		Node: []*srvpb.IdentifierMatch_Node{
			node("kythe://habeas?lang=java", "record", "interface"),
		},
		BaseName:      "Interface",
		QualifiedName: "com.java.package.Interface",
	},
}}

var tests = []testCase{
	{
		findRequest("foo::bar", nil, nil),
		[]*ipb.FindReply_Match{
			match("kythe://corpus?lang=c++", "record", "class", "bar", "foo::bar"),
			match("kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"),
		},
	},
	{
		findRequest("foo::bar", nil, []string{"rust"}),
		[]*ipb.FindReply_Match{
			match("kythe://corpus?lang=rust", "record", "struct", "bar", "foo::bar"),
		},
	},
	{
		findRequest("com.java.package.Interface", []string{"habeas"}, nil),
		[]*ipb.FindReply_Match{
			match("kythe://habeas?lang=java", "record", "interface", "Interface", "com.java.package.Interface"),
		},
	},
	{
		findRequest("com.java.package.Interface", []string{"corpus"}, nil),
		[]*ipb.FindReply_Match{},
	},
}

func TestFind(t *testing.T) {
	for _, test := range tests {
		reply, err := matchTable.Find(context.TODO(), &test.FindRequest)
		if err != nil {
			t.Errorf("unexpected error for request %v: %v", test.FindRequest, err)
		}

		if err := testutil.DeepEqual(test.Matches, reply.Matches); err != nil {
			t.Error(err)
		}
	}
}

func findRequest(qname string, corpora, langs []string) ipb.FindRequest {
	return ipb.FindRequest{
		Identifier: qname,
		Corpus:     corpora,
		Languages:  langs,
	}
}

func node(ticket, kind, subkind string) *srvpb.IdentifierMatch_Node {
	return &srvpb.IdentifierMatch_Node{
		Ticket:      ticket,
		NodeKind:    kind,
		NodeSubkind: subkind,
	}
}

func match(ticket, kind, subkind, bname, qname string) *ipb.FindReply_Match {
	return &ipb.FindReply_Match{
		Ticket:        ticket,
		NodeKind:      kind,
		NodeSubkind:   subkind,
		BaseName:      bname,
		QualifiedName: qname,
	}
}

type testCase struct {
	ipb.FindRequest
	Matches []*ipb.FindReply_Match
}

type testProtoTable map[string]proto.Message

func (t testProtoTable) Put(_ context.Context, key []byte, val proto.Message) error {
	t[string(key)] = val
	return nil
}

func (t testProtoTable) Lookup(_ context.Context, key []byte, msg proto.Message) error {
	m, ok := t[string(key)]
	if !ok {
		return table.ErrNoSuchKey
	}
	proto.Merge(msg, m)
	return nil
}

func (t testProtoTable) Buffered() table.BufferedProto { panic("UNIMPLEMENTED") }

func (t testProtoTable) Close(_ context.Context) error { return nil }
<|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 fuzz

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/golang/glog"
	computealpha "google.golang.org/api/compute/v0.alpha"
	computebeta "google.golang.org/api/compute/v0.beta"
	compute "google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
)

// ForwardingRule is a union of the API version types.
type ForwardingRule struct {
	GA    *compute.ForwardingRule
	Alpha *computealpha.ForwardingRule
	Beta  *computebeta.ForwardingRule
}

// TargetHTTPProxy is a union of the API version types.
type TargetHTTPProxy struct {
	GA    *compute.TargetHttpProxy
	Alpha *computealpha.TargetHttpProxy
	Beta  *computebeta.TargetHttpProxy
}

// TargetHTTPSProxy is a union of the API version types.
type TargetHTTPSProxy struct {
	GA    *compute.TargetHttpsProxy
	Alpha *computealpha.TargetHttpsProxy
	Beta  *computebeta.TargetHttpsProxy
}

// URLMap is a union of the API version types.
type URLMap struct {
	GA    *compute.UrlMap
	Alpha *computealpha.UrlMap
	Beta  *computebeta.UrlMap
}

// BackendService is a union of the API version types.
type BackendService struct {
	GA    *compute.BackendService
	Alpha *computealpha.BackendService
	Beta  *computebeta.BackendService
}

// GCLB contains the resources for a load balancer.
type GCLB struct {
	VIP string

	ForwardingRule   map[meta.Key]*ForwardingRule
	TargetHTTPProxy  map[meta.Key]*TargetHTTPProxy
	TargetHTTPSProxy map[meta.Key]*TargetHTTPSProxy
	URLMap           map[meta.Key]*URLMap
	BackendService   map[meta.Key]*BackendService
}

// NewGCLB returns an empty GCLB.
func NewGCLB(vip string) *GCLB {
	return &GCLB{
		VIP:              vip,
		ForwardingRule:   map[meta.Key]*ForwardingRule{},
		TargetHTTPProxy:  map[meta.Key]*TargetHTTPProxy{},
		TargetHTTPSProxy: map[meta.Key]*TargetHTTPSProxy{},
		URLMap:           map[meta.Key]*URLMap{},
		BackendService:   map[meta.Key]*BackendService{},
	}
}

// CheckResourceDeletion checks the existance of the resources. Returns nil if
// all of the associated resources no longer exist.
func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud) error {
	var resources []*meta.Key

	for k := range g.ForwardingRule {
		_, err := c.ForwardingRules().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.TargetHTTPProxy {
		_, err := c.TargetHttpProxies().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.TargetHTTPSProxy {
		_, err := c.TargetHttpsProxies().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.URLMap {
		_, err := c.UrlMaps().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.BackendService {
		_, err := c.BackendServices().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}

	if len(resources) != 0 {
		var s []string
		for _, r := range resources {
			s = append(s, r.String())
		}
		return fmt.Errorf("resources still exist (%s)", strings.Join(s, ", "))
	}

	return nil
}

func hasAlphaResource(resourceType string, validators []FeatureValidator) bool {
	for _, val := range validators {
		if val.HasAlphaResource("forwardingRule") {
			return true
		}
	}
	return false
}

func hasBetaResource(resourceType string, validators []FeatureValidator) bool {
	for _, val := range validators {
		if val.HasBetaResource("forwardingRule") {
			return true
		}
	}
	return false
}

// GCLBForVIP retrieves all of the resources associated with the GCLB for a
// given VIP.
func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []FeatureValidator) (*GCLB, error) {
	gclb := NewGCLB(vip)

	allGFRs, err := c.GlobalForwardingRules().List(ctx, filter.None)
	if err != nil {
		glog.Warningf("Error listing forwarding rules: %v", err)
		return nil, err
	}

	var gfrs []*compute.ForwardingRule
	for _, gfr := range allGFRs {
		if gfr.IPAddress == vip {
			gfrs = append(gfrs, gfr)
		}
	}

	var urlMapKey *meta.Key
	for _, gfr := range gfrs {
		frKey := meta.GlobalKey(gfr.Name)
		gclb.ForwardingRule[*frKey] = &ForwardingRule{GA: gfr}
		if hasAlphaResource("forwardingRule", validators) {
			fr, err := c.AlphaForwardingRules().Get(ctx, frKey)
			if err != nil {
				glog.Warningf("Error getting alpha forwarding rules: %v", err)
				return nil, err
			}
			gclb.ForwardingRule[*frKey].Alpha = fr
		}
		if hasBetaResource("forwardingRule", validators) {
			return nil, errors.New("unsupported forwardingRule version")
		}

		// ForwardingRule => TargetProxy
		resID, err := cloud.ParseResourceURL(gfr.Target)
		if err != nil {
			glog.Warningf("Error parsing Target (%q): %v", gfr.Target, err)
			return nil, err
		}
		switch resID.Resource {
		case "targetHttpProxies":
			p, err := c.TargetHttpProxies().Get(ctx, resID.Key)
			if err != nil {
				glog.Warningf("Error getting TargetHttpProxy %s: %v", resID.Key, err)
				return nil, err
			}
			gclb.TargetHTTPProxy[*resID.Key] = &TargetHTTPProxy{GA: p}
			if hasAlphaResource("targetHttpProxy", validators) || hasBetaResource("targetHttpProxy", validators) {
				return nil, errors.New("unsupported targetHttpProxy version")
			}

			urlMapResID, err := cloud.ParseResourceURL(p.UrlMap)
			if err != nil {
				glog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err)
				return nil, err
			}
			if urlMapKey == nil {
				urlMapKey = urlMapResID.Key
			}
			if *urlMapKey != *urlMapResID.Key {
				glog.Warningf("Error targetHttpProxy references are not the same (%s != %s)", *urlMapKey, *urlMapResID.Key)
				return nil, fmt.Errorf("targetHttpProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key)
			}
		case "targetHttpsProxies":
			p, err := c.TargetHttpsProxies().Get(ctx, resID.Key)
			if err != nil {
				glog.Warningf("Error getting targetHttpsProxy (%s): %v", resID.Key, err)
				return nil, err
			}
			gclb.TargetHTTPSProxy[*resID.Key] = &TargetHTTPSProxy{GA: p}
			if hasAlphaResource("targetHttpsProxy", validators) || hasBetaResource("targetHttpsProxy", validators) {
				return nil, errors.New("unsupported targetHttpsProxy version")
			}

			urlMapResID, err := cloud.ParseResourceURL(p.UrlMap)
			if err != nil {
				glog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err)
				return nil, err
			}
			if urlMapKey == nil {
				urlMapKey = urlMapResID.Key
			}
			if *urlMapKey != *urlMapResID.Key {
				glog.Warningf("Error targetHttpsProxy references are not the same (%s != %s)", *urlMapKey, *urlMapResID.Key)
				return nil, fmt.Errorf("targetHttpsProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key)
			}
		default:
			glog.Errorf("Unhandled resource: %q, grf = %+v", resID.Resource, gfr)
			return nil, fmt.Errorf("unhandled resource %q", resID.Resource)
		}
	}

	// TargetProxy => URLMap
	urlMap, err := c.UrlMaps().Get(ctx, urlMapKey)
	if err != nil {
		return nil, err
	}
	gclb.URLMap[*urlMapKey] = &URLMap{GA: urlMap}
	if hasAlphaResource("urlMap", validators) || hasBetaResource("urlMap", validators) {
		return nil, errors.New("unsupported urlMap version")
	}

	// URLMap => BackendService(s)
	var bsKeys []*meta.Key
	resID, err := cloud.ParseResourceURL(urlMap.DefaultService)
	if err != nil {
		return nil, err
	}
	bsKeys = append(bsKeys, resID.Key)

	for _, pm := range urlMap.PathMatchers {
		resID, err := cloud.ParseResourceURL(pm.DefaultService)
		if err != nil {
			return nil, err
		}
		bsKeys = append(bsKeys, resID.Key)

		for _, pr := range pm.PathRules {
			resID, err := cloud.ParseResourceURL(pr.Service)
			if err != nil {
				return nil, err
			}
			bsKeys = append(bsKeys, resID.Key)
		}
	}

	for _, bsKey := range bsKeys {
		bs, err := c.BackendServices().Get(ctx, bsKey)
		if err != nil {
			return nil, err
		}
		gclb.BackendService[*bsKey] = &BackendService{GA: bs}

		if hasAlphaResource("backendService", validators) {
			bs, err := c.AlphaBackendServices().Get(ctx, bsKey)
			if err != nil {
				return nil, err
			}
			gclb.BackendService[*bsKey].Alpha = bs
		}
		if hasBetaResource("backendService", validators) {
			bs, err := c.BetaBackendServices().Get(ctx, bsKey)
			if err != nil {
				return nil, err
			}
			gclb.BackendService[*bsKey].Beta = bs
		}
	}

	// TODO: fetch Backends

	return gclb, err
}
<commit_msg>Fix hasAlphaResource and hasBetaResource<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 fuzz

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/golang/glog"
	computealpha "google.golang.org/api/compute/v0.alpha"
	computebeta "google.golang.org/api/compute/v0.beta"
	compute "google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
)

// ForwardingRule is a union of the API version types.
type ForwardingRule struct {
	GA    *compute.ForwardingRule
	Alpha *computealpha.ForwardingRule
	Beta  *computebeta.ForwardingRule
}

// TargetHTTPProxy is a union of the API version types.
type TargetHTTPProxy struct {
	GA    *compute.TargetHttpProxy
	Alpha *computealpha.TargetHttpProxy
	Beta  *computebeta.TargetHttpProxy
}

// TargetHTTPSProxy is a union of the API version types.
type TargetHTTPSProxy struct {
	GA    *compute.TargetHttpsProxy
	Alpha *computealpha.TargetHttpsProxy
	Beta  *computebeta.TargetHttpsProxy
}

// URLMap is a union of the API version types.
type URLMap struct {
	GA    *compute.UrlMap
	Alpha *computealpha.UrlMap
	Beta  *computebeta.UrlMap
}

// BackendService is a union of the API version types.
type BackendService struct {
	GA    *compute.BackendService
	Alpha *computealpha.BackendService
	Beta  *computebeta.BackendService
}

// GCLB contains the resources for a load balancer.
type GCLB struct {
	VIP string

	ForwardingRule   map[meta.Key]*ForwardingRule
	TargetHTTPProxy  map[meta.Key]*TargetHTTPProxy
	TargetHTTPSProxy map[meta.Key]*TargetHTTPSProxy
	URLMap           map[meta.Key]*URLMap
	BackendService   map[meta.Key]*BackendService
}

// NewGCLB returns an empty GCLB.
func NewGCLB(vip string) *GCLB {
	return &GCLB{
		VIP:              vip,
		ForwardingRule:   map[meta.Key]*ForwardingRule{},
		TargetHTTPProxy:  map[meta.Key]*TargetHTTPProxy{},
		TargetHTTPSProxy: map[meta.Key]*TargetHTTPSProxy{},
		URLMap:           map[meta.Key]*URLMap{},
		BackendService:   map[meta.Key]*BackendService{},
	}
}

// CheckResourceDeletion checks the existance of the resources. Returns nil if
// all of the associated resources no longer exist.
func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud) error {
	var resources []*meta.Key

	for k := range g.ForwardingRule {
		_, err := c.ForwardingRules().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.TargetHTTPProxy {
		_, err := c.TargetHttpProxies().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.TargetHTTPSProxy {
		_, err := c.TargetHttpsProxies().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.URLMap {
		_, err := c.UrlMaps().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}
	for k := range g.BackendService {
		_, err := c.BackendServices().Get(ctx, &k)
		if err != nil {
			if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound {
				return err
			}
		} else {
			resources = append(resources, &k)
		}
	}

	if len(resources) != 0 {
		var s []string
		for _, r := range resources {
			s = append(s, r.String())
		}
		return fmt.Errorf("resources still exist (%s)", strings.Join(s, ", "))
	}

	return nil
}

func hasAlphaResource(resourceType string, validators []FeatureValidator) bool {
	for _, val := range validators {
		if val.HasAlphaResource(resourceType) {
			return true
		}
	}
	return false
}

func hasBetaResource(resourceType string, validators []FeatureValidator) bool {
	for _, val := range validators {
		if val.HasBetaResource(resourceType) {
			return true
		}
	}
	return false
}

// GCLBForVIP retrieves all of the resources associated with the GCLB for a
// given VIP.
func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []FeatureValidator) (*GCLB, error) {
	gclb := NewGCLB(vip)

	allGFRs, err := c.GlobalForwardingRules().List(ctx, filter.None)
	if err != nil {
		glog.Warningf("Error listing forwarding rules: %v", err)
		return nil, err
	}

	var gfrs []*compute.ForwardingRule
	for _, gfr := range allGFRs {
		if gfr.IPAddress == vip {
			gfrs = append(gfrs, gfr)
		}
	}

	var urlMapKey *meta.Key
	for _, gfr := range gfrs {
		frKey := meta.GlobalKey(gfr.Name)
		gclb.ForwardingRule[*frKey] = &ForwardingRule{GA: gfr}
		if hasAlphaResource("forwardingRule", validators) {
			fr, err := c.AlphaForwardingRules().Get(ctx, frKey)
			if err != nil {
				glog.Warningf("Error getting alpha forwarding rules: %v", err)
				return nil, err
			}
			gclb.ForwardingRule[*frKey].Alpha = fr
		}
		if hasBetaResource("forwardingRule", validators) {
			return nil, errors.New("unsupported forwardingRule version")
		}

		// ForwardingRule => TargetProxy
		resID, err := cloud.ParseResourceURL(gfr.Target)
		if err != nil {
			glog.Warningf("Error parsing Target (%q): %v", gfr.Target, err)
			return nil, err
		}
		switch resID.Resource {
		case "targetHttpProxies":
			p, err := c.TargetHttpProxies().Get(ctx, resID.Key)
			if err != nil {
				glog.Warningf("Error getting TargetHttpProxy %s: %v", resID.Key, err)
				return nil, err
			}
			gclb.TargetHTTPProxy[*resID.Key] = &TargetHTTPProxy{GA: p}
			if hasAlphaResource("targetHttpProxy", validators) || hasBetaResource("targetHttpProxy", validators) {
				return nil, errors.New("unsupported targetHttpProxy version")
			}

			urlMapResID, err := cloud.ParseResourceURL(p.UrlMap)
			if err != nil {
				glog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err)
				return nil, err
			}
			if urlMapKey == nil {
				urlMapKey = urlMapResID.Key
			}
			if *urlMapKey != *urlMapResID.Key {
				glog.Warningf("Error targetHttpProxy references are not the same (%s != %s)", *urlMapKey, *urlMapResID.Key)
				return nil, fmt.Errorf("targetHttpProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key)
			}
		case "targetHttpsProxies":
			p, err := c.TargetHttpsProxies().Get(ctx, resID.Key)
			if err != nil {
				glog.Warningf("Error getting targetHttpsProxy (%s): %v", resID.Key, err)
				return nil, err
			}
			gclb.TargetHTTPSProxy[*resID.Key] = &TargetHTTPSProxy{GA: p}
			if hasAlphaResource("targetHttpsProxy", validators) || hasBetaResource("targetHttpsProxy", validators) {
				return nil, errors.New("unsupported targetHttpsProxy version")
			}

			urlMapResID, err := cloud.ParseResourceURL(p.UrlMap)
			if err != nil {
				glog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err)
				return nil, err
			}
			if urlMapKey == nil {
				urlMapKey = urlMapResID.Key
			}
			if *urlMapKey != *urlMapResID.Key {
				glog.Warningf("Error targetHttpsProxy references are not the same (%s != %s)", *urlMapKey, *urlMapResID.Key)
				return nil, fmt.Errorf("targetHttpsProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key)
			}
		default:
			glog.Errorf("Unhandled resource: %q, grf = %+v", resID.Resource, gfr)
			return nil, fmt.Errorf("unhandled resource %q", resID.Resource)
		}
	}

	// TargetProxy => URLMap
	urlMap, err := c.UrlMaps().Get(ctx, urlMapKey)
	if err != nil {
		return nil, err
	}
	gclb.URLMap[*urlMapKey] = &URLMap{GA: urlMap}
	if hasAlphaResource("urlMap", validators) || hasBetaResource("urlMap", validators) {
		return nil, errors.New("unsupported urlMap version")
	}

	// URLMap => BackendService(s)
	var bsKeys []*meta.Key
	resID, err := cloud.ParseResourceURL(urlMap.DefaultService)
	if err != nil {
		return nil, err
	}
	bsKeys = append(bsKeys, resID.Key)

	for _, pm := range urlMap.PathMatchers {
		resID, err := cloud.ParseResourceURL(pm.DefaultService)
		if err != nil {
			return nil, err
		}
		bsKeys = append(bsKeys, resID.Key)

		for _, pr := range pm.PathRules {
			resID, err := cloud.ParseResourceURL(pr.Service)
			if err != nil {
				return nil, err
			}
			bsKeys = append(bsKeys, resID.Key)
		}
	}

	for _, bsKey := range bsKeys {
		bs, err := c.BackendServices().Get(ctx, bsKey)
		if err != nil {
			return nil, err
		}
		gclb.BackendService[*bsKey] = &BackendService{GA: bs}

		if hasAlphaResource("backendService", validators) {
			bs, err := c.AlphaBackendServices().Get(ctx, bsKey)
			if err != nil {
				return nil, err
			}
			gclb.BackendService[*bsKey].Alpha = bs
		}
		if hasBetaResource("backendService", validators) {
			bs, err := c.BetaBackendServices().Get(ctx, bsKey)
			if err != nil {
				return nil, err
			}
			gclb.BackendService[*bsKey].Beta = bs
		}
	}

	// TODO: fetch Backends

	return gclb, err
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/jinzhu/gorm"

	"github.com/doubledutch/dd-vote/api/auth"
	"github.com/doubledutch/dd-vote/api/models/resp"
	"github.com/doubledutch/dd-vote/api/models/table"
	"github.com/gin-gonic/gin"
)

// ExportHandler manages api endpoints for exporting reports
type ExportHandler struct {
	db gorm.DB
}

// NewExportHandler creates a new instance
func NewExportHandler(db gorm.DB) *ExportHandler {
	return &ExportHandler{db: db}
}

// GetAllQuestionsCSV serves a csv file report of all the questions in a group
// Columns: Question, Upvotes, Downvotes, Created by
func (handler ExportHandler) GetAllQuestionsCSV(c *gin.Context) {
	gname := c.Param("gname")
	if !auth.HasAccessToGroup(auth.GetUserIDFromCookie(c), gname, handler.db) {
		c.JSON(http.StatusForbidden, resp.APIResponse{IsError: true, Message: "You don't have permission to access this group"})
		return
	}

	var group table.Group
	if err := handler.db.Where("name = ?", gname).First(&group).Error; err != nil {
		c.JSON(http.StatusNotFound, resp.APIResponse{IsError: true, Message: "Group does not exist"})
		return
	}

	// get all posts for a group with comments and users for those comments
	var posts []table.Post
	handler.db.First(&group, table.Group{Name: gname})
	handler.db.Model(&group).Order("id").Preload("User").Association("Posts").Find(&posts)
	output := "Question,Upvotes,Downvotes,Created by" + "\n"
	for _, post := range posts {
		data := []string{post.Name, fmt.Sprintf("%v", post.Upvotes), fmt.Sprintf("%v", post.Downvotes), fmt.Sprintf("%v", post.User.FullName())}
		for i := range data {
			data[i] = escapeForCSV(data[i])
		}
		output += strings.Join(data[:], ",") + "\n"
	}

	c.Writer.Header().Set("Content-Disposition", "attachment; filename=questions.csv")
	c.Writer.Header().Set("Content-Type", c.Request.Header.Get("Content-Type"))

	c.String(http.StatusOK, output)
}

// GetTopUsersCSV serves a csv file report of users with the most votes
// Columns: Name, Total votes
func (handler ExportHandler) GetTopUsersCSV(c *gin.Context) {
	gname := c.Param("gname")
	if !auth.HasAccessToGroup(auth.GetUserIDFromCookie(c), gname, handler.db) {
		c.JSON(http.StatusForbidden, resp.APIResponse{IsError: true, Message: "You don't have permission to access this group"})
		return
	}

	var group table.Group
	if err := handler.db.Where("name = ?", gname).First(&group).Error; err != nil {
		c.JSON(http.StatusNotFound, resp.APIResponse{IsError: true, Message: "Group does not exist"})
		return
	}

	handler.db.First(&group, table.Group{Name: gname})
	rows, err := handler.db.Table("users").Select("users.firstname, users.lastname, count(*) as total_votes").Joins("join votes on votes.user_id = users.id join posts on posts.id = votes.post_id join groups on groups.id = posts.group_id").Where("groups.id = ?", group.ID).Group("users.id, users.firstname, users.lastname").Rows()
	if err != nil {
		log.Printf("Unable to get top user rows: %s", err)
		c.JSON(http.StatusInternalServerError, resp.APIResponse{IsError: true, Message: "Unable to export top users"})
		return
	}
	output := "Name,Total votes" + "\n"
	for rows.Next() {
		var firstname string
		var lastname string
		var totalVotes int
		rows.Scan(&firstname, &lastname, &totalVotes)
		data := []string{firstname + " " + lastname, fmt.Sprintf("%v", totalVotes)}
		for i := range data {
			data[i] = escapeForCSV(data[i])
		}
		output += strings.Join(data[:], ",") + "\n"
	}

	c.Writer.Header().Set("Content-Disposition", "attachment; filename=top_users.csv")
	c.Writer.Header().Set("Content-Type", c.Request.Header.Get("Content-Type"))

	c.String(http.StatusOK, output)
}

func escapeForCSV(data string) string {
	if strings.ContainsAny(data, "\",") {
		data = strings.Replace(data, "\"", "\"\"", -1)
		return "\"" + data + "\""
	}
	return data
}
<commit_msg>add score and total votes to questions export cvs<commit_after>package handlers

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/jinzhu/gorm"

	"github.com/doubledutch/dd-vote/api/auth"
	"github.com/doubledutch/dd-vote/api/models/resp"
	"github.com/doubledutch/dd-vote/api/models/table"
	"github.com/gin-gonic/gin"
)

// ExportHandler manages api endpoints for exporting reports
type ExportHandler struct {
	db gorm.DB
}

// NewExportHandler creates a new instance
func NewExportHandler(db gorm.DB) *ExportHandler {
	return &ExportHandler{db: db}
}

// GetAllQuestionsCSV serves a csv file report of all the questions in a group
// Columns: Question, Score (upvotes - downvotes), Total votes (upvotes + downvotes), Upvotes, Downvotes, Created by
func (handler ExportHandler) GetAllQuestionsCSV(c *gin.Context) {
	gname := c.Param("gname")
	if !auth.HasAccessToGroup(auth.GetUserIDFromCookie(c), gname, handler.db) {
		c.JSON(http.StatusForbidden, resp.APIResponse{IsError: true, Message: "You don't have permission to access this group"})
		return
	}

	var group table.Group
	if err := handler.db.Where("name = ?", gname).First(&group).Error; err != nil {
		c.JSON(http.StatusNotFound, resp.APIResponse{IsError: true, Message: "Group does not exist"})
		return
	}

	// get all posts for a group with comments and users for those comments
	var posts []table.Post
	handler.db.First(&group, table.Group{Name: gname})
	handler.db.Model(&group).Order("id").Preload("User").Association("Posts").Find(&posts)
	output := "Question,Score (upvotes - downvotes),Total votes (upvotes + downvotes),Upvotes,Downvotes,Created by" + "\n"
	for _, post := range posts {
		data := []string{post.Name, fmt.Sprintf("%v", int(post.Upvotes)-int(post.Downvotes)), fmt.Sprintf("%v", post.Upvotes+post.Downvotes), fmt.Sprintf("%v", post.Upvotes), fmt.Sprintf("%v", post.Downvotes), fmt.Sprintf("%v", post.User.FullName())}
		for i := range data {
			data[i] = escapeForCSV(data[i])
		}
		output += strings.Join(data[:], ",") + "\n"
	}

	c.Writer.Header().Set("Content-Disposition", "attachment; filename=questions.csv")
	c.Writer.Header().Set("Content-Type", c.Request.Header.Get("Content-Type"))

	c.String(http.StatusOK, output)
}

// GetTopUsersCSV serves a csv file report of users with the most votes
// Columns: Name, Total votes
func (handler ExportHandler) GetTopUsersCSV(c *gin.Context) {
	gname := c.Param("gname")
	if !auth.HasAccessToGroup(auth.GetUserIDFromCookie(c), gname, handler.db) {
		c.JSON(http.StatusForbidden, resp.APIResponse{IsError: true, Message: "You don't have permission to access this group"})
		return
	}

	var group table.Group
	if err := handler.db.Where("name = ?", gname).First(&group).Error; err != nil {
		c.JSON(http.StatusNotFound, resp.APIResponse{IsError: true, Message: "Group does not exist"})
		return
	}

	handler.db.First(&group, table.Group{Name: gname})
	rows, err := handler.db.Table("users").Select("users.firstname, users.lastname, count(*) as total_votes").Joins("join votes on votes.user_id = users.id join posts on posts.id = votes.post_id join groups on groups.id = posts.group_id").Where("groups.id = ?", group.ID).Group("users.id, users.firstname, users.lastname").Rows()
	if err != nil {
		log.Printf("Unable to get top user rows: %s", err)
		c.JSON(http.StatusInternalServerError, resp.APIResponse{IsError: true, Message: "Unable to export top users"})
		return
	}
	output := "Name,Total votes" + "\n"
	for rows.Next() {
		var firstname string
		var lastname string
		var totalVotes int
		rows.Scan(&firstname, &lastname, &totalVotes)
		data := []string{firstname + " " + lastname, fmt.Sprintf("%v", totalVotes)}
		for i := range data {
			data[i] = escapeForCSV(data[i])
		}
		output += strings.Join(data[:], ",") + "\n"
	}

	c.Writer.Header().Set("Content-Disposition", "attachment; filename=top_users.csv")
	c.Writer.Header().Set("Content-Type", c.Request.Header.Get("Content-Type"))

	c.String(http.StatusOK, output)
}

func escapeForCSV(data string) string {
	if strings.ContainsAny(data, "\",") {
		data = strings.Replace(data, "\"", "\"\"", -1)
		return "\"" + data + "\""
	}
	return data
}
<|endoftext|>


<commit_before>package functions

// FuncNames defines the set of available function names available to the CLI
var FuncNames = []string{
	"BroadbandProductType",
	"DataPumpVersion",
	"DataReceived",
	"DataSent",
	"DhcpPoolStart",
	"DhcpPoolEnd",
	"DhcpSubnetMask",
	"DownstreamSyncSpeed",
	"EnableDebug",
	"HardwareVersion",
	"InternetConnectionStatus",
	"LightStatus",
	"LocalTime",
	"MaintenaceFirmwareVersion",
	"PublicIPAddress",
	"PublicSubnetMask",
	"Reboot",
	"SambaIP",
	"SambaHost",
	"SerialNumber",
	"SoftwareVersion",
	"UpstreamSyncSpeed",
	"Version",
	"WiFiSecurityMode",
	"WiFiSSID"}
<commit_msg>Add event log support<commit_after>package functions

// FuncNames defines the set of available function names available to the CLI
var FuncNames = []string{
	"BroadbandProductType",
	"DataPumpVersion",
	"DataReceived",
	"DataSent",
	"DhcpPoolStart",
	"DhcpPoolEnd",
	"DhcpSubnetMask",
	"DownstreamSyncSpeed",
	"EnableDebug",
	"EventLog",
	"HardwareVersion",
	"InternetConnectionStatus",
	"LightStatus",
	"LocalTime",
	"MaintenaceFirmwareVersion",
	"PublicIPAddress",
	"PublicSubnetMask",
	"Reboot",
	"SambaIP",
	"SambaHost",
	"SerialNumber",
	"SoftwareVersion",
	"UpstreamSyncSpeed",
	"Version",
	"WiFiSecurityMode",
	"WiFiSSID"}
<|endoftext|>