<commit_before>package bq_test

import (
	"errors"
	"log"
	"os"
	"testing"
	"time"

	"cloud.google.com/go/bigquery"

	"github.com/m-lab/etl/bq"
	"github.com/m-lab/etl/etl"
	"github.com/m-lab/etl/fake"
)

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func foobar(vs bigquery.ValueSaver) {
	_, _, _ = vs.Save()
}

func TestMapSaver(t *testing.T) {
	fns := bq.MapSaver{map[string]bigquery.Value{"filename": "foobar"}}
	foobar(&fns)
}

// Item represents a row item.
type Item struct {
	Name   string
	Count  int
	Foobar int `json:"foobar"`
}

//==================================================================================
// These tests hit the backend, to verify expected behavior of table creation and
// access to partitions.  They deliberately have a leading "x" to prevent running
// them in Travis.  We need to find a better way to control whether they run or
// not.
//==================================================================================
func xTestRealPartitionInsert(t *testing.T) {
	tag := "new"
	items := []interface{}{
		Item{Name: tag + "_x0", Count: 17, Foobar: 44},
		Item{Name: tag + "_x1", Count: 12, Foobar: 44}}

	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "_20160201", 10 * time.Second, 1, 0 * time.Second}, nil)
	if err != nil {
		t.Fatal(err)
	}

	if err = in.InsertRow(Item{Name: tag + "_x0", Count: 17, Foobar: 44}); err != nil {
		t.Error(err)
	}
	if err = in.InsertRows(items); err != nil {
		t.Error(err)
	}

	if in.Accepted() != 3 {
		t.Error("Should have accepted three rows")
	}
	in.Flush()
}

//==================================================================================

func TestBasicInsert(t *testing.T) {
	tag := "new"
	items := []interface{}{
		Item{Name: tag + "_x0", Count: 17, Foobar: 44},
		Item{Name: tag + "_x1", Count: 12, Foobar: 44}}

	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "", 10 * time.Second, 1, 0 * time.Second},
		fake.NewFakeUploader())
	if err != nil {
		t.Fatal(err)
	}

	if err = in.InsertRow(Item{Name: tag + "_x0", Count: 17, Foobar: 44}); err != nil {
		t.Error(err)
	}
	if err = in.InsertRows(items); err != nil {
		t.Error(err)
	}

	if in.Accepted() != 3 {
		t.Error("Should have accepted three rows")
	}
	in.Flush()
}

func TestInsertConfig(t *testing.T) {
	os.Setenv("GCLOUD_PROJECT", "mlab-oti")
	in, err := bq.NewInserter(etl.SS, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	if in.Dataset() != "private" {
		t.Errorf("Want private, got %s", in.Dataset())
	}
	if in.Project() != "mlab-oti" {
		t.Errorf("Want private, got %s", in.Project())
	}

	in, err = bq.NewInserter(etl.NDT, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	if in.Dataset() != "base_tables" {
		t.Errorf("Want private, got %s", in.Dataset())
	}
	if in.Project() != "measurement-lab" {
		t.Errorf("Want measurement-lab, got %s", in.Project())
	}
}

func TestBufferingAndFlushing(t *testing.T) {
	var items []interface{}
	items = append(items, Item{Name: "x1", Count: 17, Foobar: 44})
	items = append(items, Item{Name: "x2", Count: 12, Foobar: 44})

	// Set up an Inserter with a fake Uploader backend for testing.
	// Buffer 3 rows, so that we can test the buffering.
	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "", 10 * time.Second, 3, 0 * time.Second},
		fake.NewFakeUploader())
	if err != nil {
		log.Printf("%v\n", err)
		t.Fatal()
	}

	// Try inserting a single row.  Should stay in the buffer.
	if err = in.InsertRow(Item{Name: "x0", Count: 17, Foobar: 44}); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 1 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}

	// Insert two more rows, which should trigger a flush.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 0 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 3 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Insert two more rows, which should NOT trigger a flush.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 2 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 5 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Insert two more rows, which should trigger a flush, and leave one
	// row in the buffer.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 1 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 7 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Flush the final row.
	in.Flush()
	if in.RowsInBuffer() != 0 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 7 {
		t.Error("Count = ", in.Accepted())
	}

}

// Just manual testing for now - need to assert something useful.
func TestHandleInsertErrors(t *testing.T) {
	in, e := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "table", "", time.Minute, 5, 0 * time.Second},
		fake.NewFakeUploader())
	if e != nil {
		log.Printf("%v\n", e)
		t.Fatal()
	}

	rie := bigquery.RowInsertionError{InsertID: "1234", RowIndex: 123}
	var bqe bigquery.Error
	bqe.Location = "location"
	bqe.Message = "message"
	bqe.Reason = "invalid"
	// This is a little wierd.  MultiError we receive from insert contain
	// *bigquery.Error.  So that is what we test here.
	rie.Errors = append(rie.Errors, &bqe)

	var pme bigquery.PutMultiError
	pme = append(pme, rie)
	in.(*bq.BQInserter).HandleInsertErrors(pme)

	// TODO - assert something.
}

func TestQuotaError(t *testing.T) {
	fakeUploader := fake.NewFakeUploader()

	// Set up an Inserter with a fake Uploader backend for testing.
	// Buffer 3 rows, so that we can test the buffering.
	in, e := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "table", "", time.Minute, 5, 1 * time.Millisecond},
		fakeUploader)
	if e != nil {
		log.Printf("%v\n", e)
		t.Fatal()
	}

	var items []interface{}
	items = append(items, Item{Name: "x1", Count: 17, Foobar: 44})
	items = append(items, Item{Name: "x2", Count: 12, Foobar: 44})

	// Insert two rows.
	if err := in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.Accepted() != 2 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Set up an arbitrary error and ensure it causes a failure.
	fakeUploader.SetErr(errors.New("Foobar"))
	err := in.Flush()

	if err != nil {
		t.Error("Error should have been consumed.")
	}
	if fakeUploader.CallCount != 1 {
		t.Error("Call count should be 1: ", fakeUploader.CallCount)
	}
	if in.Failed() != 2 {
		// Should have failed two rows.
		t.Error("Should have increased Failed to 2: ", in.Failed())
	}

	// Insert the rows again, since they were lost in previous Flush call.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.Accepted() != 4 {
		t.Error("Accepted = ", in.Accepted())
	}
	// This should fail, because the uploader has a preloaded error.
	fakeUploader.SetErr(errors.New("Quota exceeded:"))
	err = in.Flush()

	if err != nil {
		t.Error("Error should have been consumed.")
	}
	// The Quota exceeded error should have caused a retry, resulting in 2 additional calls.
	if fakeUploader.CallCount != 3 {
		t.Error("Call count should be 3: ", fakeUploader.CallCount)
	}
	// The second call should have succeeded, increasing the Committed count.
	if in.Committed() != 2 {
		t.Error("Should have increased Committed to 2: ", in.Committed())
	}

}
<commit_msg>disable mlab-oti tests in travis<commit_after>package bq_test

import (
	"errors"
	"log"
	"os"
	"testing"
	"time"

	"cloud.google.com/go/bigquery"

	"github.com/m-lab/etl/bq"
	"github.com/m-lab/etl/etl"
	"github.com/m-lab/etl/fake"
)

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func foobar(vs bigquery.ValueSaver) {
	_, _, _ = vs.Save()
}

func TestMapSaver(t *testing.T) {
	fns := bq.MapSaver{map[string]bigquery.Value{"filename": "foobar"}}
	foobar(&fns)
}

// Item represents a row item.
type Item struct {
	Name   string
	Count  int
	Foobar int `json:"foobar"`
}

//==================================================================================
// These tests hit the backend, to verify expected behavior of table creation and
// access to partitions.  They deliberately have a leading "x" to prevent running
// them in Travis.  We need to find a better way to control whether they run or
// not.
//==================================================================================
func xTestRealPartitionInsert(t *testing.T) {
	tag := "new"
	items := []interface{}{
		Item{Name: tag + "_x0", Count: 17, Foobar: 44},
		Item{Name: tag + "_x1", Count: 12, Foobar: 44}}

	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "_20160201", 10 * time.Second, 1, 0 * time.Second}, nil)
	if err != nil {
		t.Fatal(err)
	}

	if err = in.InsertRow(Item{Name: tag + "_x0", Count: 17, Foobar: 44}); err != nil {
		t.Error(err)
	}
	if err = in.InsertRows(items); err != nil {
		t.Error(err)
	}

	if in.Accepted() != 3 {
		t.Error("Should have accepted three rows")
	}
	in.Flush()
}

//==================================================================================

func TestBasicInsert(t *testing.T) {
	tag := "new"
	items := []interface{}{
		Item{Name: tag + "_x0", Count: 17, Foobar: 44},
		Item{Name: tag + "_x1", Count: 12, Foobar: 44}}

	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "", 10 * time.Second, 1, 0 * time.Second},
		fake.NewFakeUploader())
	if err != nil {
		t.Fatal(err)
	}

	if err = in.InsertRow(Item{Name: tag + "_x0", Count: 17, Foobar: 44}); err != nil {
		t.Error(err)
	}
	if err = in.InsertRows(items); err != nil {
		t.Error(err)
	}

	if in.Accepted() != 3 {
		t.Error("Should have accepted three rows")
	}
	in.Flush()
}

// This does not currently work with mlab-testing credentials, and we
// probably don't want it to.  So disabling it in travis.
func TestInsertConfig(t *testing.T) {
	_, isTravis := os.LookupEnv("TRAVIS")
	if isTravis {
		return
	}
	os.Setenv("GCLOUD_PROJECT", "mlab-oti")
	in, err := bq.NewInserter(etl.SS, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	if in.Dataset() != "private" {
		t.Errorf("Want private, got %s", in.Dataset())
	}
	if in.Project() != "mlab-oti" {
		t.Errorf("Want mlab-oti, got %s", in.Project())
	}

	in, err = bq.NewInserter(etl.NDT, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	if in.Dataset() != "base_tables" {
		t.Errorf("Want private, got %s", in.Dataset())
	}
	if in.Project() != "measurement-lab" {
		t.Errorf("Want measurement-lab, got %s", in.Project())
	}
}

func TestBufferingAndFlushing(t *testing.T) {
	var items []interface{}
	items = append(items, Item{Name: "x1", Count: 17, Foobar: 44})
	items = append(items, Item{Name: "x2", Count: 12, Foobar: 44})

	// Set up an Inserter with a fake Uploader backend for testing.
	// Buffer 3 rows, so that we can test the buffering.
	in, err := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "test2", "", 10 * time.Second, 3, 0 * time.Second},
		fake.NewFakeUploader())
	if err != nil {
		log.Printf("%v\n", err)
		t.Fatal()
	}

	// Try inserting a single row.  Should stay in the buffer.
	if err = in.InsertRow(Item{Name: "x0", Count: 17, Foobar: 44}); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 1 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}

	// Insert two more rows, which should trigger a flush.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 0 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 3 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Insert two more rows, which should NOT trigger a flush.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 2 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 5 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Insert two more rows, which should trigger a flush, and leave one
	// row in the buffer.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.RowsInBuffer() != 1 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 7 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Flush the final row.
	in.Flush()
	if in.RowsInBuffer() != 0 {
		t.Error("RowsInBuffer = ", in.RowsInBuffer())
	}
	if in.Accepted() != 7 {
		t.Error("Count = ", in.Accepted())
	}

}

// Just manual testing for now - need to assert something useful.
func TestHandleInsertErrors(t *testing.T) {
	in, e := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "table", "", time.Minute, 5, 0 * time.Second},
		fake.NewFakeUploader())
	if e != nil {
		log.Printf("%v\n", e)
		t.Fatal()
	}

	rie := bigquery.RowInsertionError{InsertID: "1234", RowIndex: 123}
	var bqe bigquery.Error
	bqe.Location = "location"
	bqe.Message = "message"
	bqe.Reason = "invalid"
	// This is a little wierd.  MultiError we receive from insert contain
	// *bigquery.Error.  So that is what we test here.
	rie.Errors = append(rie.Errors, &bqe)

	var pme bigquery.PutMultiError
	pme = append(pme, rie)
	in.(*bq.BQInserter).HandleInsertErrors(pme)

	// TODO - assert something.
}

func TestQuotaError(t *testing.T) {
	fakeUploader := fake.NewFakeUploader()

	// Set up an Inserter with a fake Uploader backend for testing.
	// Buffer 3 rows, so that we can test the buffering.
	in, e := bq.NewBQInserter(
		etl.InserterParams{"mlab-testing", "dataset", "table", "", time.Minute, 5, 1 * time.Millisecond},
		fakeUploader)
	if e != nil {
		log.Printf("%v\n", e)
		t.Fatal()
	}

	var items []interface{}
	items = append(items, Item{Name: "x1", Count: 17, Foobar: 44})
	items = append(items, Item{Name: "x2", Count: 12, Foobar: 44})

	// Insert two rows.
	if err := in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.Accepted() != 2 {
		t.Error("Accepted = ", in.Accepted())
	}

	// Set up an arbitrary error and ensure it causes a failure.
	fakeUploader.SetErr(errors.New("Foobar"))
	err := in.Flush()

	if err != nil {
		t.Error("Error should have been consumed.")
	}
	if fakeUploader.CallCount != 1 {
		t.Error("Call count should be 1: ", fakeUploader.CallCount)
	}
	if in.Failed() != 2 {
		// Should have failed two rows.
		t.Error("Should have increased Failed to 2: ", in.Failed())
	}

	// Insert the rows again, since they were lost in previous Flush call.
	if err = in.InsertRows(items); err != nil {
		t.Fatal()
	}
	if in.Accepted() != 4 {
		t.Error("Accepted = ", in.Accepted())
	}
	// This should fail, because the uploader has a preloaded error.
	fakeUploader.SetErr(errors.New("Quota exceeded:"))
	err = in.Flush()

	if err != nil {
		t.Error("Error should have been consumed.")
	}
	// The Quota exceeded error should have caused a retry, resulting in 2 additional calls.
	if fakeUploader.CallCount != 3 {
		t.Error("Call count should be 3: ", fakeUploader.CallCount)
	}
	// The second call should have succeeded, increasing the Committed count.
	if in.Committed() != 2 {
		t.Error("Should have increased Committed to 2: ", in.Committed())
	}

}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 main

import (
	"github.com/osrg/gobgp/api"
	"github.com/spf13/cobra"
)

var globalOpts struct {
	Host  string `short:"u" long:"url" description:"specifying an url" default:"127.0.0.1"`
	Port  int    `short:"p" long:"port" description:"specifying a port" default:"8080"`
	Debug bool   `short:"d" long:"debug" description:"use debug"`
	Quiet bool   `short:"q" long:"quiet" description:"use quiet"`
	Json  bool   `short:"j" long:"json" description:"use json format to output format"`
}

var cmds []string
var client api.GrpcClient

func main() {
	rootCmd := &cobra.Command{
		Use: "gobgp",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			conn := connGrpc()
			client = api.NewGrpcClient(conn)
		},
	}

	rootCmd.PersistentFlags().StringVarP(&globalOpts.Host, "host", "u", "127.0.0.1", "host")
	rootCmd.PersistentFlags().IntVarP(&globalOpts.Port, "port", "p", 8080, "port")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Json, "json", "j", false, "use json format to output format")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Debug, "debug", "d", false, "use debug")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Quiet, "quiet", "q", false, "use quiet")

	globalCmd := NewGlobalCmd()
	neighborCmd := NewNeighborCmd()
	policyCmd := NewPolicyCmd()
	rootCmd.AddCommand(globalCmd)
	rootCmd.AddCommand(neighborCmd)
	rootCmd.AddCommand(policyCmd)

	rootCmd.Execute()
}
<commit_msg>cli: add a flag to generate bash completion file<commit_after>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 main

import (
	"github.com/osrg/gobgp/api"
	"github.com/spf13/cobra"
)

var globalOpts struct {
	Host         string `short:"u" long:"url" description:"specifying an url" default:"127.0.0.1"`
	Port         int    `short:"p" long:"port" description:"specifying a port" default:"8080"`
	Debug        bool   `short:"d" long:"debug" description:"use debug"`
	Quiet        bool   `short:"q" long:"quiet" description:"use quiet"`
	Json         bool   `short:"j" long:"json" description:"use json format to output format"`
	GenCmpl      bool   `short:"c" long:"genbashcmpl" description:"use json format to output format"`
	BashCmplFile string
}

var cmds []string
var client api.GrpcClient

func main() {
	rootCmd := &cobra.Command{
		Use: "gobgp",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if !globalOpts.GenCmpl {
				conn := connGrpc()
				client = api.NewGrpcClient(conn)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.GenBashCompletionFile(globalOpts.BashCmplFile)
		},
	}

	rootCmd.PersistentFlags().StringVarP(&globalOpts.Host, "host", "u", "127.0.0.1", "host")
	rootCmd.PersistentFlags().IntVarP(&globalOpts.Port, "port", "p", 8080, "port")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Json, "json", "j", false, "use json format to output format")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Debug, "debug", "d", false, "use debug")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.Quiet, "quiet", "q", false, "use quiet")
	rootCmd.PersistentFlags().BoolVarP(&globalOpts.GenCmpl, "gen-cmpl", "c", false, "generate completion file")
	rootCmd.PersistentFlags().StringVarP(&globalOpts.BashCmplFile, "bash-cmpl-file", "", "gobgp_completion.bash", "bash cmpl filename")

	globalCmd := NewGlobalCmd()
	neighborCmd := NewNeighborCmd()
	policyCmd := NewPolicyCmd()
	rootCmd.AddCommand(globalCmd)
	rootCmd.AddCommand(neighborCmd)
	rootCmd.AddCommand(policyCmd)

	rootCmd.Execute()
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Stefan Schroeder, NY, 2014-03-10
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file

package gocal_test

import (
	"github.com/StefanSchroeder/gocal"
	"os"
	"runtime"
	"testing"
)

var outdir = "test-output" + string(os.PathSeparator)

func Test_Example01(t *testing.T) {
	g := gocal.New(1, 12, 2010)
	g.CreateCalendar(outdir + "test-example01.pdf")
}

func Test_Example02(t *testing.T) {
	g := gocal.New(1, 1, 2011)
	g.SetNocolor()
	g.SetOrientation("L")
	g.CreateCalendar(outdir + "test-example02.pdf")
}

func Test_Example03(t *testing.T) {
	g := gocal.New(1, 1, 2015)
	g.SetOrientation("P")
	g.SetLocale("fr_FR")
	g.SetFont("sans")
	g.CreateCalendar(outdir + "test-example03.pdf")
}

func Test_Example04(t *testing.T) {
	g := gocal.New(1, 1, 2015)
	g.SetOrientation("P")
	g.SetPhotos("gocalendar" + string(os.PathSeparator) + "pics")
	g.CreateCalendar(outdir + "test-example04.pdf")
}

func Test_Example05(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetOrientation("L")
	g.SetFont("mono")
	g.SetLocale("de_DE")
	g.CreateCalendar(outdir + "test-example05.pdf")
}

func Test_Example06(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetOrientation("P")
	g.SetPlain()
	g.SetLocale("nl_NL")
	g.CreateCalendar(outdir + "test-example06.pdf")
}

func Test_Example07(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	if runtime.GOOS == "windows" {
		g.SetFont("c:\\windows\\Fonts\\cabalett.ttf")
	}
	g.SetFooter("Windows specific Font inclusion example")
	g.CreateCalendar(outdir + "test-example07.pdf")
}

func Test_Example08(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetPhoto("gocalendar" + string(os.PathSeparator) + "pics" + string(os.PathSeparator) + "taxi.JPG")
	g.SetOrientation("P")
	g.CreateCalendar(outdir + "test-example08.pdf")
}

func Test_Example09(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetLocale("fi_FI")
	g.CreateCalendar(outdir + "test-example09.pdf")
}

func Test_Example10(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetFontScale(0.5)
	g.CreateCalendar(outdir + "test-example10.pdf")
}

func Test_Example11(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetSmall()
	g.CreateCalendar(outdir + "test-example11.pdf")
}

func Test_Example12(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetHideOtherMonth()
	g.CreateCalendar(outdir + "test-example12.pdf")
}

func Test_Example13(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetHideWeek()
	g.AddEvent(15, 3, "One Event", "")
	g.AddEvent(16, 3, "Another Event", "")
	g.AddEvent(17, 4, "Hegdehog\\nvisits", "")
	g.AddEvent(18, 4, "Day\\nof the\\nDay", "")
	g.SetHideMoon()
	g.CreateCalendar(outdir + "test-example13.pdf")
}

func Test_Example14(t *testing.T) {
	g := gocal.New(1, 12, 2013)
	g.SetConfig("test-gocal.xml")
	g.CreateCalendar(outdir + "test-example14.pdf")
}

func Test_Example15(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(2)
	g.SetFooter("Spread 2")
	g.CreateYearCalendar(outdir + "test-example15.pdf")
}

func Test_Example16(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.CreateYearCalendarInverse(outdir + "test-example16.pdf")
}

func Test_Example17(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(4)
	g.SetFooter("Spread 4")
	g.CreateYearCalendarInverse(outdir + "test-example17.pdf")
}

func Test_Example18(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(4)
	g.SetFooter("Spread 4")
	g.CreateYearCalendarInverse(outdir + "test-example18.pdf")
}

func Test_Example19(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(3)
	g.SetFooter("Spread 3")
	g.CreateYearCalendarInverse(outdir + "test-example19.pdf")
}
<commit_msg>fixed upper case<commit_after>// Copyright (c) 2014 Stefan Schroeder, NY, 2014-03-10
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file

package gocal_test

import (
	"github.com/StefanSchroeder/Gocal"
	"os"
	"runtime"
	"testing"
)

var outdir = "test-output" + string(os.PathSeparator)

func Test_Example01(t *testing.T) {
	g := gocal.New(1, 12, 2010)
	g.CreateCalendar(outdir + "test-example01.pdf")
}

func Test_Example02(t *testing.T) {
	g := gocal.New(1, 1, 2011)
	g.SetNocolor()
	g.SetOrientation("L")
	g.CreateCalendar(outdir + "test-example02.pdf")
}

func Test_Example03(t *testing.T) {
	g := gocal.New(1, 1, 2015)
	g.SetOrientation("P")
	g.SetLocale("fr_FR")
	g.SetFont("sans")
	g.CreateCalendar(outdir + "test-example03.pdf")
}

func Test_Example04(t *testing.T) {
	g := gocal.New(1, 1, 2015)
	g.SetOrientation("P")
	g.SetPhotos("gocalendar" + string(os.PathSeparator) + "pics")
	g.CreateCalendar(outdir + "test-example04.pdf")
}

func Test_Example05(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetOrientation("L")
	g.SetFont("mono")
	g.SetLocale("de_DE")
	g.CreateCalendar(outdir + "test-example05.pdf")
}

func Test_Example06(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetOrientation("P")
	g.SetPlain()
	g.SetLocale("nl_NL")
	g.CreateCalendar(outdir + "test-example06.pdf")
}

func Test_Example07(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	if runtime.GOOS == "windows" {
		g.SetFont("c:\\windows\\Fonts\\cabalett.ttf")
	}
	g.SetFooter("Windows specific Font inclusion example")
	g.CreateCalendar(outdir + "test-example07.pdf")
}

func Test_Example08(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetPhoto("gocalendar" + string(os.PathSeparator) + "pics" + string(os.PathSeparator) + "taxi.JPG")
	g.SetOrientation("P")
	g.CreateCalendar(outdir + "test-example08.pdf")
}

func Test_Example09(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetLocale("fi_FI")
	g.CreateCalendar(outdir + "test-example09.pdf")
}

func Test_Example10(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetFontScale(0.5)
	g.CreateCalendar(outdir + "test-example10.pdf")
}

func Test_Example11(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetSmall()
	g.CreateCalendar(outdir + "test-example11.pdf")
}

func Test_Example12(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetHideOtherMonth()
	g.CreateCalendar(outdir + "test-example12.pdf")
}

func Test_Example13(t *testing.T) {
	g := gocal.New(3, 4, 2013)
	g.SetHideWeek()
	g.AddEvent(15, 3, "One Event", "")
	g.AddEvent(16, 3, "Another Event", "")
	g.AddEvent(17, 4, "Hegdehog\\nvisits", "")
	g.AddEvent(18, 4, "Day\\nof the\\nDay", "")
	g.SetHideMoon()
	g.CreateCalendar(outdir + "test-example13.pdf")
}

func Test_Example14(t *testing.T) {
	g := gocal.New(1, 12, 2013)
	g.SetConfig("test-gocal.xml")
	g.CreateCalendar(outdir + "test-example14.pdf")
}

func Test_Example15(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(2)
	g.SetFooter("Spread 2")
	g.CreateYearCalendar(outdir + "test-example15.pdf")
}

func Test_Example16(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.CreateYearCalendarInverse(outdir + "test-example16.pdf")
}

func Test_Example17(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(4)
	g.SetFooter("Spread 4")
	g.CreateYearCalendarInverse(outdir + "test-example17.pdf")
}

func Test_Example18(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(4)
	g.SetFooter("Spread 4")
	g.CreateYearCalendarInverse(outdir + "test-example18.pdf")
}

func Test_Example19(t *testing.T) {
	g := gocal.New(1, 12, 2019)
	g.SetYearSpread(3)
	g.SetFooter("Spread 3")
	g.CreateYearCalendarInverse(outdir + "test-example19.pdf")
}
<|endoftext|>


<commit_before>/*
 * gocli
 * Copyright (c) 2015 Yieldbot, Inc.
 * For the full copyright and license information, please view the LICENSE.txt file.
 */

package gocli_test

import (
	"flag"
	"os"
	"testing"

	"github.com/yieldbot/gocli"
)

var (
	argFlag     string
	usageFlag   bool
	versionFlag bool
)

func init() {
	// Init flags
	flag.StringVar(&argFlag, "arg", "test", "Arg flag")
	flag.BoolVar(&usageFlag, "h", false, "Display usage")
	flag.BoolVar(&usageFlag, "help", false, "Display usage")
	flag.BoolVar(&versionFlag, "version", false, "Display version information")
	flag.BoolVar(&versionFlag, "v", false, "Display version information")
}

func TestInit_1(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.Name != "test" {
		t.Error("invalid Name")
	}

	if cli.Version != "1.0.0" {
		t.Error("invalid Version")
	}

	if cli.Description != "test desc" {
		t.Error("invalid Description")
	}

	if len(cli.Commands) != 1 {
		t.Error("invalid Commands")
	}

	if cli.Commands["cmd"] != "Test command" {
		t.Error("invalid Commands")
	}

	if cli.SubCommand != "" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) > 0 {
		t.Error("invalid SubCommandArgs")
	}
}

func TestInit_2(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]
	os.Args = append(os.Args, "cmd", "arg1")

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.SubCommand != "cmd" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) != 1 {
		t.Error("invalid SubCommandArgs")
	}

	if cli.SubCommandArgs[0] != "arg1" {
		t.Error("invalid SubCommandArgs arg")
	}
}

func TestInit_3(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]
	os.Args = append(os.Args, "cmd", "--arg2", "arg3", "arg4")

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.SubCommand != "cmd" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) != 3 {
		t.Error("invalid SubCommandArgs", cli.SubCommandArgs)
	}

	if cli.SubCommandArgs[0] != "--arg2" {
		t.Error("invalid SubCommandArgs arg", cli.SubCommandArgs)
	}

	if cli.SubCommandArgsMap["arg2"] != "arg3" {
		t.Error("invalid SubCommandArgsMap arg", cli.SubCommandArgsMap)
	}

	if _, ok := cli.SubCommandArgsMap["arg4"]; !ok {
		t.Error("invalid SubCommandArgsMap arg", cli.SubCommandArgsMap)
	}
}

func ExampleF_PrintVersion() {
	var cli = gocli.Cli{
		Version: "1.0.0",
	}
	cli.Init()

	cli.PrintVersion(false)
	// Output: 1.0.0
}

func ExampleF_PrintVersionExtra() {
	var cli = gocli.Cli{
		Version: "1.0.0",
	}
	cli.Init()

	cli.PrintVersion(true)
}

func ExampleF_PrintUsage() {

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	cli.PrintUsage()
	// Output:
	// Usage: test [OPTIONS] COMMAND [arg...]
	//
	// test desc
	//
	// Options:
	//   --arg         : Arg flag (default "test")
	//   -h, --help    : Display usage
	//   -v, --version : Display version information
	//
	// Commands:
	//   cmd           : Test command
}
<commit_msg>Remove unnecessary output<commit_after>/*
 * gocli
 * Copyright (c) 2015 Yieldbot, Inc.
 * For the full copyright and license information, please view the LICENSE.txt file.
 */

package gocli_test

import (
	"flag"
	"os"
	"testing"

	"github.com/yieldbot/gocli"
)

var (
	argFlag     string
	usageFlag   bool
	versionFlag bool
)

func init() {
	// Init flags
	flag.StringVar(&argFlag, "arg", "test", "Arg flag")
	flag.BoolVar(&usageFlag, "h", false, "Display usage")
	flag.BoolVar(&usageFlag, "help", false, "Display usage")
	flag.BoolVar(&versionFlag, "version", false, "Display version information")
	flag.BoolVar(&versionFlag, "v", false, "Display version information")
}

func TestInit_1(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.Name != "test" {
		t.Error("invalid Name")
	}

	if cli.Version != "1.0.0" {
		t.Error("invalid Version")
	}

	if cli.Description != "test desc" {
		t.Error("invalid Description")
	}

	if len(cli.Commands) != 1 {
		t.Error("invalid Commands")
	}

	if cli.Commands["cmd"] != "Test command" {
		t.Error("invalid Commands")
	}

	if cli.SubCommand != "" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) > 0 {
		t.Error("invalid SubCommandArgs")
	}
}

func TestInit_2(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]
	os.Args = append(os.Args, "cmd", "arg1")

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.SubCommand != "cmd" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) != 1 {
		t.Error("invalid SubCommandArgs")
	}

	if cli.SubCommandArgs[0] != "arg1" {
		t.Error("invalid SubCommandArgs arg")
	}
}

func TestInit_3(t *testing.T) {

	// Reset the args
	os.Args = os.Args[:2]
	os.Args = append(os.Args, "cmd", "--arg2", "arg3", "arg4")

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	if cli.SubCommand != "cmd" {
		t.Error("invalid SubCommand")
	}

	if len(cli.SubCommandArgs) != 3 {
		t.Error("invalid SubCommandArgs")
	}

	if cli.SubCommandArgs[0] != "--arg2" {
		t.Error("invalid SubCommandArgs arg")
	}

	if cli.SubCommandArgsMap["arg2"] != "arg3" {
		t.Error("invalid SubCommandArgsMap arg")
	}

	if _, ok := cli.SubCommandArgsMap["arg4"]; !ok {
		t.Error("invalid SubCommandArgsMap arg")
	}
}

func ExampleF_PrintVersion() {
	var cli = gocli.Cli{
		Version: "1.0.0",
	}
	cli.Init()

	cli.PrintVersion(false)
	// Output: 1.0.0
}

func ExampleF_PrintVersionExtra() {
	var cli = gocli.Cli{
		Version: "1.0.0",
	}
	cli.Init()

	cli.PrintVersion(true)
}

func ExampleF_PrintUsage() {

	// Init cli
	var cli = gocli.Cli{
		Name:        "test",
		Version:     "1.0.0",
		Description: "test desc",
		Commands: map[string]string{
			"cmd": "Test command",
		},
	}
	cli.Init()

	cli.PrintUsage()
	// Output:
	// Usage: test [OPTIONS] COMMAND [arg...]
	//
	// test desc
	//
	// Options:
	//   --arg         : Arg flag (default "test")
	//   -h, --help    : Display usage
	//   -v, --version : Display version information
	//
	// Commands:
	//   cmd           : Test command
}
<|endoftext|>


<commit_before>// Network utility functions.

package netutils

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net"
	"strings"

	"github.com/vishvananda/netlink"
)

var (
	// ErrNetworkOverlapsWithNameservers preformatted error
	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
	// ErrNetworkOverlaps preformatted error
	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
	// ErrNoDefaultRoute preformatted error
	ErrNoDefaultRoute = errors.New("no default route")

	networkGetRoutesFct = netlink.RouteList
)

// ErrInvalidProtocolBinding is returned when the port binding protocol is not valid.
type ErrInvalidProtocolBinding string

func (ipb ErrInvalidProtocolBinding) Error() string {
	return fmt.Sprintf("invalid transport protocol: %s", string(ipb))
}

// TransportPort represent a local Layer 4 endpoint
type TransportPort struct {
	Proto Protocol
	Port  uint16
}

// PortBinding represent a port binding between the container an the host
type PortBinding struct {
	Proto    Protocol
	IP       net.IP
	Port     uint16
	HostIP   net.IP
	HostPort uint16
}

// HostAddr returns the host side tranport address
func (p PortBinding) HostAddr() (net.Addr, error) {
	switch p.Proto {
	case UDP:
		return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
	case TCP:
		return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
	default:
		return nil, ErrInvalidProtocolBinding(p.Proto.String())
	}
}

// ContainerAddr returns the container side tranport address
func (p PortBinding) ContainerAddr() (net.Addr, error) {
	switch p.Proto {
	case UDP:
		return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
	case TCP:
		return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
	default:
		return nil, ErrInvalidProtocolBinding(p.Proto.String())
	}
}

// GetCopy returns a copy of this PortBinding structure instance
func (p *PortBinding) GetCopy() PortBinding {
	return PortBinding{
		Proto:    p.Proto,
		IP:       GetIPCopy(p.IP),
		Port:     p.Port,
		HostIP:   GetIPCopy(p.HostIP),
		HostPort: p.HostPort,
	}
}

// Equal checks if this instance of PortBinding is equal to the passed one
func (p *PortBinding) Equal(o *PortBinding) bool {
	if p == o {
		return true
	}

	if o == nil {
		return false
	}

	if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
		return false
	}

	if p.IP != nil {
		if !p.IP.Equal(o.IP) {
			return false
		}
	} else {
		if o.IP != nil {
			return false
		}
	}

	if p.HostIP != nil {
		if !p.HostIP.Equal(o.HostIP) {
			return false
		}
	} else {
		if o.HostIP != nil {
			return false
		}
	}

	return true
}

const (
	// ICMP is for the ICMP ip protocol
	ICMP = 1
	// TCP is for the TCP ip protocol
	TCP = 6
	// UDP is for the UDP ip protocol
	UDP = 17
)

// Protocol represents a IP protocol number
type Protocol uint8

func (p Protocol) String() string {
	switch p {
	case 1:
		return "icmp"
	case 6:
		return "tcp"
	case 17:
		return "udp"
	default:
		return fmt.Sprintf("%d", p)
	}
}

// ParseProtocol returns the respective Protocol type for the passed string
func ParseProtocol(s string) Protocol {
	switch strings.ToLower(s) {
	case "icmp":
		return 1
	case "udp":
		return 17
	case "tcp":
		return 6
	default:
		return 0
	}
}

// CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
	if len(nameservers) > 0 {
		for _, ns := range nameservers {
			_, nsNetwork, err := net.ParseCIDR(ns)
			if err != nil {
				return err
			}
			if NetworkOverlaps(toCheck, nsNetwork) {
				return ErrNetworkOverlapsWithNameservers
			}
		}
	}
	return nil
}

// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
func CheckRouteOverlaps(toCheck *net.IPNet) error {
	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
	if err != nil {
		return err
	}

	for _, network := range networks {
		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
			return ErrNetworkOverlaps
		}
	}
	return nil
}

// NetworkOverlaps detects overlap between one IPNet and another
func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	if len(netX.IP) == len(netY.IP) {
		if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
			return true
		}
		if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
			return true
		}
	}
	return false
}

// NetworkRange calculates the first and last IP addresses in an IPNet
func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
	var netIP net.IP
	if network.IP.To4() != nil {
		netIP = network.IP.To4()
	} else if network.IP.To16() != nil {
		netIP = network.IP.To16()
	} else {
		return nil, nil
	}

	lastIP := make([]byte, len(netIP), len(netIP))
	for i := 0; i < len(netIP); i++ {
		lastIP[i] = netIP[i] | ^network.Mask[i]
	}
	return netIP.Mask(network.Mask), net.IP(lastIP)
}

// GetIfaceAddr returns the first IPv4 address and slice of IPv6 addresses for the specified network interface
func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
	iface, err := net.InterfaceByName(name)
	if err != nil {
		return nil, nil, err
	}
	addrs, err := iface.Addrs()
	if err != nil {
		return nil, nil, err
	}
	var addrs4 []net.Addr
	var addrs6 []net.Addr
	for _, addr := range addrs {
		ip := (addr.(*net.IPNet)).IP
		if ip4 := ip.To4(); ip4 != nil {
			addrs4 = append(addrs4, addr)
		} else if ip6 := ip.To16(); len(ip6) == net.IPv6len {
			addrs6 = append(addrs6, addr)
		}
	}
	switch {
	case len(addrs4) == 0:
		return nil, nil, fmt.Errorf("Interface %v has no IPv4 addresses", name)
	case len(addrs4) > 1:
		fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
			name, (addrs4[0].(*net.IPNet)).IP)
	}
	return addrs4[0], addrs6, nil
}

// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
func GenerateRandomMAC() net.HardwareAddr {
	hw := make(net.HardwareAddr, 6)
	// The first byte of the MAC address has to comply with these rules:
	// 1. Unicast: Set the least-significant bit to 0.
	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
	hw[0] = 0x02
	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
	// Since this address is locally administered, we can do whatever we want as long as
	// it doesn't conflict with other addresses.
	hw[1] = 0x42
	// Randomly generate the remaining 4 bytes (2^32)
	_, err := rand.Read(hw[2:])
	if err != nil {
		return nil
	}
	return hw
}

// GenerateRandomName returns a new name joined with a prefix.  This size
// specified is used to truncate the randomly generated value
func GenerateRandomName(prefix string, size int) (string, error) {
	id := make([]byte, 32)
	if _, err := io.ReadFull(rand.Reader, id); err != nil {
		return "", err
	}
	return prefix + hex.EncodeToString(id)[:size], nil
}

// GetIPCopy returns a copy of the passed IP address
func GetIPCopy(from net.IP) net.IP {
	to := make(net.IP, len(from))
	copy(to, from)
	return to
}

// GetIPNetCopy returns a copy of the passed IP Network
func GetIPNetCopy(from *net.IPNet) *net.IPNet {
	if from == nil {
		return nil
	}
	bm := make(net.IPMask, len(from.Mask))
	copy(bm, from.Mask)
	return &net.IPNet{IP: GetIPCopy(from.IP), Mask: bm}
}

// CompareIPNet returns equal if the two IP Networks are equal
func CompareIPNet(a, b *net.IPNet) bool {
	if a == b {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	return a.IP.Equal(b.IP) && bytes.Equal(a.Mask, b.Mask)
}
<commit_msg>Replaced all proto numbers in netutils with the defined const<commit_after>// Network utility functions.

package netutils

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net"
	"strings"

	"github.com/vishvananda/netlink"
)

var (
	// ErrNetworkOverlapsWithNameservers preformatted error
	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
	// ErrNetworkOverlaps preformatted error
	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
	// ErrNoDefaultRoute preformatted error
	ErrNoDefaultRoute = errors.New("no default route")

	networkGetRoutesFct = netlink.RouteList
)

// ErrInvalidProtocolBinding is returned when the port binding protocol is not valid.
type ErrInvalidProtocolBinding string

func (ipb ErrInvalidProtocolBinding) Error() string {
	return fmt.Sprintf("invalid transport protocol: %s", string(ipb))
}

// TransportPort represent a local Layer 4 endpoint
type TransportPort struct {
	Proto Protocol
	Port  uint16
}

// PortBinding represent a port binding between the container an the host
type PortBinding struct {
	Proto    Protocol
	IP       net.IP
	Port     uint16
	HostIP   net.IP
	HostPort uint16
}

// HostAddr returns the host side tranport address
func (p PortBinding) HostAddr() (net.Addr, error) {
	switch p.Proto {
	case UDP:
		return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
	case TCP:
		return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
	default:
		return nil, ErrInvalidProtocolBinding(p.Proto.String())
	}
}

// ContainerAddr returns the container side tranport address
func (p PortBinding) ContainerAddr() (net.Addr, error) {
	switch p.Proto {
	case UDP:
		return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
	case TCP:
		return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
	default:
		return nil, ErrInvalidProtocolBinding(p.Proto.String())
	}
}

// GetCopy returns a copy of this PortBinding structure instance
func (p *PortBinding) GetCopy() PortBinding {
	return PortBinding{
		Proto:    p.Proto,
		IP:       GetIPCopy(p.IP),
		Port:     p.Port,
		HostIP:   GetIPCopy(p.HostIP),
		HostPort: p.HostPort,
	}
}

// Equal checks if this instance of PortBinding is equal to the passed one
func (p *PortBinding) Equal(o *PortBinding) bool {
	if p == o {
		return true
	}

	if o == nil {
		return false
	}

	if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
		return false
	}

	if p.IP != nil {
		if !p.IP.Equal(o.IP) {
			return false
		}
	} else {
		if o.IP != nil {
			return false
		}
	}

	if p.HostIP != nil {
		if !p.HostIP.Equal(o.HostIP) {
			return false
		}
	} else {
		if o.HostIP != nil {
			return false
		}
	}

	return true
}

const (
	// ICMP is for the ICMP ip protocol
	ICMP = 1
	// TCP is for the TCP ip protocol
	TCP = 6
	// UDP is for the UDP ip protocol
	UDP = 17
)

// Protocol represents a IP protocol number
type Protocol uint8

func (p Protocol) String() string {
	switch p {
	case ICMP:
		return "icmp"
	case TCP:
		return "tcp"
	case UDP:
		return "udp"
	default:
		return fmt.Sprintf("%d", p)
	}
}

// ParseProtocol returns the respective Protocol type for the passed string
func ParseProtocol(s string) Protocol {
	switch strings.ToLower(s) {
	case "icmp":
		return ICMP
	case "udp":
		return UDP
	case "tcp":
		return TCP
	default:
		return 0
	}
}

// CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
	if len(nameservers) > 0 {
		for _, ns := range nameservers {
			_, nsNetwork, err := net.ParseCIDR(ns)
			if err != nil {
				return err
			}
			if NetworkOverlaps(toCheck, nsNetwork) {
				return ErrNetworkOverlapsWithNameservers
			}
		}
	}
	return nil
}

// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
func CheckRouteOverlaps(toCheck *net.IPNet) error {
	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
	if err != nil {
		return err
	}

	for _, network := range networks {
		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
			return ErrNetworkOverlaps
		}
	}
	return nil
}

// NetworkOverlaps detects overlap between one IPNet and another
func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	if len(netX.IP) == len(netY.IP) {
		if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
			return true
		}
		if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
			return true
		}
	}
	return false
}

// NetworkRange calculates the first and last IP addresses in an IPNet
func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
	var netIP net.IP
	if network.IP.To4() != nil {
		netIP = network.IP.To4()
	} else if network.IP.To16() != nil {
		netIP = network.IP.To16()
	} else {
		return nil, nil
	}

	lastIP := make([]byte, len(netIP), len(netIP))
	for i := 0; i < len(netIP); i++ {
		lastIP[i] = netIP[i] | ^network.Mask[i]
	}
	return netIP.Mask(network.Mask), net.IP(lastIP)
}

// GetIfaceAddr returns the first IPv4 address and slice of IPv6 addresses for the specified network interface
func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
	iface, err := net.InterfaceByName(name)
	if err != nil {
		return nil, nil, err
	}
	addrs, err := iface.Addrs()
	if err != nil {
		return nil, nil, err
	}
	var addrs4 []net.Addr
	var addrs6 []net.Addr
	for _, addr := range addrs {
		ip := (addr.(*net.IPNet)).IP
		if ip4 := ip.To4(); ip4 != nil {
			addrs4 = append(addrs4, addr)
		} else if ip6 := ip.To16(); len(ip6) == net.IPv6len {
			addrs6 = append(addrs6, addr)
		}
	}
	switch {
	case len(addrs4) == 0:
		return nil, nil, fmt.Errorf("Interface %v has no IPv4 addresses", name)
	case len(addrs4) > 1:
		fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
			name, (addrs4[0].(*net.IPNet)).IP)
	}
	return addrs4[0], addrs6, nil
}

// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
func GenerateRandomMAC() net.HardwareAddr {
	hw := make(net.HardwareAddr, 6)
	// The first byte of the MAC address has to comply with these rules:
	// 1. Unicast: Set the least-significant bit to 0.
	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
	hw[0] = 0x02
	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
	// Since this address is locally administered, we can do whatever we want as long as
	// it doesn't conflict with other addresses.
	hw[1] = 0x42
	// Randomly generate the remaining 4 bytes (2^32)
	_, err := rand.Read(hw[2:])
	if err != nil {
		return nil
	}
	return hw
}

// GenerateRandomName returns a new name joined with a prefix.  This size
// specified is used to truncate the randomly generated value
func GenerateRandomName(prefix string, size int) (string, error) {
	id := make([]byte, 32)
	if _, err := io.ReadFull(rand.Reader, id); err != nil {
		return "", err
	}
	return prefix + hex.EncodeToString(id)[:size], nil
}

// GetIPCopy returns a copy of the passed IP address
func GetIPCopy(from net.IP) net.IP {
	to := make(net.IP, len(from))
	copy(to, from)
	return to
}

// GetIPNetCopy returns a copy of the passed IP Network
func GetIPNetCopy(from *net.IPNet) *net.IPNet {
	if from == nil {
		return nil
	}
	bm := make(net.IPMask, len(from.Mask))
	copy(bm, from.Mask)
	return &net.IPNet{IP: GetIPCopy(from.IP), Mask: bm}
}

// CompareIPNet returns equal if the two IP Networks are equal
func CompareIPNet(a, b *net.IPNet) bool {
	if a == b {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	return a.IP.Equal(b.IP) && bytes.Equal(a.Mask, b.Mask)
}
<|endoftext|>


<commit_before>// Copyright 2015 The rkt 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.

// kvm.go file provides networking supporting functions for kvm flavor
package networking

import (
	"encoding/json"
	"fmt"
	"log"
	"net"

	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/cni/pkg/ip"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/cni/pkg/plugin"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/vishvananda/netlink"

	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/networking/tuntap"
)

// setupTapDevice creates persistent tap devices
// and returns a newly created netlink.Link structure
func setupTapDevice() (netlink.Link, error) {
	ifName, err := tuntap.CreatePersistentIface(tuntap.Tap)
	if err != nil {
		return nil, fmt.Errorf("tuntap persist %v", err)
	}
	link, err := netlink.LinkByName(ifName)
	if err != nil {
		return nil, fmt.Errorf("cannot find link %q: %v", ifName, err)
	}
	err = netlink.LinkSetUp(link)
	if err != nil {
		return nil, fmt.Errorf("cannot set link up %q: %v", ifName, err)
	}
	return link, nil
}

// kvmSetupNetAddressing calls IPAM plugin (with a hack) to reserve an IP to be
// used by newly create tuntap pair
// in result it updates activeNet.runtime configuration with IP, Mask and HostIP
func kvmSetupNetAddressing(network *Networking, n activeNet, ifName string) error {
	// TODO: very ugly hack, that go through upper plugin, down to ipam plugin
	n.conf.Type = n.conf.IPAM.Type
	output, err := network.execNetPlugin("ADD", &n, ifName)
	if err != nil {
		return fmt.Errorf("problem executing network plugin %q (%q): %v", n.conf.Type, ifName, err)
	}

	result := plugin.Result{}
	if err = json.Unmarshal(output, &result); err != nil {
		return fmt.Errorf("error parsing %q result: %v", n.conf.Name, err)
	}

	if result.IP4 == nil {
		return fmt.Errorf("net-plugin returned no IPv4 configuration")
	}

	n.runtime.IP, n.runtime.Mask, n.runtime.HostIP = result.IP4.IP.IP, net.IP(result.IP4.IP.Mask), result.IP4.Gateway
	return nil
}

// kvmSetup prepare new Networking to be used in kvm environment based on tuntap pair interfaces
// to allow communication with virtual machine created by lkvm tool
// right now it only supports default "ptp" network type (other types ends with error)
func kvmSetup(podRoot string, podID types.UUID, fps []ForwardedPort, privateNetList common.PrivateNetList, localConfig string) (*Networking, error) {
	network := Networking{
		podEnv: podEnv{
			podRoot:      podRoot,
			podID:        podID,
			netsLoadList: privateNetList,
			localConfig:  localConfig,
		},
	}
	var e error
	network.nets, e = network.loadNets()
	if e != nil {
		return nil, fmt.Errorf("error loading network definitions: %v", e)
	}

	for _, n := range network.nets {
		switch n.conf.Type {
		case "ptp":
			link, err := setupTapDevice()
			if err != nil {
				return nil, err
			}
			ifName := link.Attrs().Name
			n.runtime.IfName = ifName

			err = kvmSetupNetAddressing(&network, n, ifName)
			if err != nil {
				return nil, err
			}

			// add address to host tap device
			err = netlink.AddrAdd(
				link,
				&netlink.Addr{
					IPNet: &net.IPNet{
						IP:   n.runtime.HostIP,
						Mask: net.IPMask(n.runtime.Mask),
					},
					Label: ifName,
				})
			if err != nil {
				return nil, fmt.Errorf("cannot add address to host tap device %q: %v", ifName, err)
			}

			if n.conf.IPMasq {
				chain := "CNI-" + n.conf.Name
				if err = ip.SetupIPMasq(&net.IPNet{
					IP:   n.runtime.IP,
					Mask: net.IPMask(n.runtime.Mask),
				}, chain); err != nil {
					return nil, err
				}
			}
		default:
			return nil, fmt.Errorf("network %q have unsupported type: %q", n.conf.Name, n.conf.Type)
		}
	}
	err := network.forwardPorts(fps, network.GetDefaultIP())
	if err != nil {
		return nil, err
	}

	return &network, nil
}

/*
extend Networking struct with methods to clean up kvm specific network configurations
*/

// teardownKvmNets teardown every active networking from networking by
// removing tuntap interface and releasing its ip from IPAM plugin
func (n *Networking) teardownKvmNets() {
	for _, an := range n.nets {
		switch an.conf.Type {
		case "ptp":
			// remove tuntap interface
			tuntap.RemovePersistentIface(an.runtime.IfName, tuntap.Tap)
			// remove masquerading if it was prepared
			if an.conf.IPMasq {
				chain := "CNI-" + an.conf.Name
				ip.TeardownIPMasq(&net.IPNet{
					IP:   an.runtime.IP,
					Mask: net.IPMask(an.runtime.Mask),
				}, chain)
			}
			// ugly hack again to directly call IPAM plugin to release IP
			an.conf.Type = an.conf.IPAM.Type

			_, err := n.execNetPlugin("DEL", &an, an.runtime.IfName)
			if err != nil {
				log.Printf("Error executing network plugin: %q", err)
			}
		default:
			log.Printf("Unsupported network type: %q", an.conf.Type)
		}
	}
}

// kvmTeardown network teardown for kvm flavor based pods
// similar to Networking.Teardown but without host namespaces
func (n *Networking) kvmTeardown() {

	if err := n.unforwardPorts(); err != nil {
		log.Printf("Error removing forwarded ports (kvm): %v", err)
	}
	n.teardownKvmNets()

}

// NetParams exposes conf(NetConf)/runtime(NetInfo) data to stage1/init client
type NetParams struct {
	// runtime based information
	HostIP  net.IP
	GuestIP net.IP
	Mask    net.IP
	IfName  string
	// TODO: required for other type of plugins, not yet available because what networking.Networking stores
	// Net net.IPNet

	// configuration based information
	Name   string
	Type   string
	IPMasq bool
}

// GetNetworkParameters returns network parameters created
// by plugins, which are required for stage1 executor to run (only for KVM)
func (e *Networking) GetNetworkParameters() []NetParams {
	np := []NetParams{}
	_ = np
	for _, an := range e.nets {
		np = append(np, NetParams{
			HostIP:  an.runtime.HostIP,
			GuestIP: an.runtime.IP,
			IfName:  an.runtime.IfName,
			Mask:    an.runtime.Mask,
			// Net: // TODO: from where
			Name:   an.conf.Name,
			Type:   an.conf.Type,
			IPMasq: an.conf.IPMasq,
		})
	}

	return np
}
<commit_msg>kvm: add ip4forward check in time of network setup.<commit_after>// Copyright 2015 The rkt 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.

// kvm.go file provides networking supporting functions for kvm flavor
package networking

import (
	"encoding/json"
	"fmt"
	"log"
	"net"

	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/cni/pkg/ip"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/cni/pkg/plugin"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/vishvananda/netlink"

	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/networking/tuntap"
)

// setupTapDevice creates persistent tap devices
// and returns a newly created netlink.Link structure
func setupTapDevice() (netlink.Link, error) {
	ifName, err := tuntap.CreatePersistentIface(tuntap.Tap)
	if err != nil {
		return nil, fmt.Errorf("tuntap persist %v", err)
	}
	link, err := netlink.LinkByName(ifName)
	if err != nil {
		return nil, fmt.Errorf("cannot find link %q: %v", ifName, err)
	}
	err = netlink.LinkSetUp(link)
	if err != nil {
		return nil, fmt.Errorf("cannot set link up %q: %v", ifName, err)
	}
	return link, nil
}

// kvmSetupNetAddressing calls IPAM plugin (with a hack) to reserve an IP to be
// used by newly create tuntap pair
// in result it updates activeNet.runtime configuration with IP, Mask and HostIP
func kvmSetupNetAddressing(network *Networking, n activeNet, ifName string) error {
	// TODO: very ugly hack, that go through upper plugin, down to ipam plugin
	if err := ip.EnableIP4Forward(); err != nil {
		return fmt.Errorf("failed to enable forwarding: %v", err)
	}
	n.conf.Type = n.conf.IPAM.Type
	output, err := network.execNetPlugin("ADD", &n, ifName)
	if err != nil {
		return fmt.Errorf("problem executing network plugin %q (%q): %v", n.conf.Type, ifName, err)
	}

	result := plugin.Result{}
	if err = json.Unmarshal(output, &result); err != nil {
		return fmt.Errorf("error parsing %q result: %v", n.conf.Name, err)
	}

	if result.IP4 == nil {
		return fmt.Errorf("net-plugin returned no IPv4 configuration")
	}

	n.runtime.IP, n.runtime.Mask, n.runtime.HostIP = result.IP4.IP.IP, net.IP(result.IP4.IP.Mask), result.IP4.Gateway
	return nil
}

// kvmSetup prepare new Networking to be used in kvm environment based on tuntap pair interfaces
// to allow communication with virtual machine created by lkvm tool
// right now it only supports default "ptp" network type (other types ends with error)
func kvmSetup(podRoot string, podID types.UUID, fps []ForwardedPort, privateNetList common.PrivateNetList, localConfig string) (*Networking, error) {
	network := Networking{
		podEnv: podEnv{
			podRoot:      podRoot,
			podID:        podID,
			netsLoadList: privateNetList,
			localConfig:  localConfig,
		},
	}
	var e error
	network.nets, e = network.loadNets()
	if e != nil {
		return nil, fmt.Errorf("error loading network definitions: %v", e)
	}

	for _, n := range network.nets {
		switch n.conf.Type {
		case "ptp":
			link, err := setupTapDevice()
			if err != nil {
				return nil, err
			}
			ifName := link.Attrs().Name
			n.runtime.IfName = ifName

			err = kvmSetupNetAddressing(&network, n, ifName)
			if err != nil {
				return nil, err
			}

			// add address to host tap device
			err = netlink.AddrAdd(
				link,
				&netlink.Addr{
					IPNet: &net.IPNet{
						IP:   n.runtime.HostIP,
						Mask: net.IPMask(n.runtime.Mask),
					},
					Label: ifName,
				})
			if err != nil {
				return nil, fmt.Errorf("cannot add address to host tap device %q: %v", ifName, err)
			}

			if n.conf.IPMasq {
				chain := "CNI-" + n.conf.Name
				if err = ip.SetupIPMasq(&net.IPNet{
					IP:   n.runtime.IP,
					Mask: net.IPMask(n.runtime.Mask),
				}, chain); err != nil {
					return nil, err
				}
			}
		default:
			return nil, fmt.Errorf("network %q have unsupported type: %q", n.conf.Name, n.conf.Type)
		}
	}
	err := network.forwardPorts(fps, network.GetDefaultIP())
	if err != nil {
		return nil, err
	}

	return &network, nil
}

/*
extend Networking struct with methods to clean up kvm specific network configurations
*/

// teardownKvmNets teardown every active networking from networking by
// removing tuntap interface and releasing its ip from IPAM plugin
func (n *Networking) teardownKvmNets() {
	for _, an := range n.nets {
		switch an.conf.Type {
		case "ptp":
			// remove tuntap interface
			tuntap.RemovePersistentIface(an.runtime.IfName, tuntap.Tap)
			// remove masquerading if it was prepared
			if an.conf.IPMasq {
				chain := "CNI-" + an.conf.Name
				ip.TeardownIPMasq(&net.IPNet{
					IP:   an.runtime.IP,
					Mask: net.IPMask(an.runtime.Mask),
				}, chain)
			}
			// ugly hack again to directly call IPAM plugin to release IP
			an.conf.Type = an.conf.IPAM.Type

			_, err := n.execNetPlugin("DEL", &an, an.runtime.IfName)
			if err != nil {
				log.Printf("Error executing network plugin: %q", err)
			}
		default:
			log.Printf("Unsupported network type: %q", an.conf.Type)
		}
	}
}

// kvmTeardown network teardown for kvm flavor based pods
// similar to Networking.Teardown but without host namespaces
func (n *Networking) kvmTeardown() {

	if err := n.unforwardPorts(); err != nil {
		log.Printf("Error removing forwarded ports (kvm): %v", err)
	}
	n.teardownKvmNets()

}

// NetParams exposes conf(NetConf)/runtime(NetInfo) data to stage1/init client
type NetParams struct {
	// runtime based information
	HostIP  net.IP
	GuestIP net.IP
	Mask    net.IP
	IfName  string
	// TODO: required for other type of plugins, not yet available because what networking.Networking stores
	// Net net.IPNet

	// configuration based information
	Name   string
	Type   string
	IPMasq bool
}

// GetNetworkParameters returns network parameters created
// by plugins, which are required for stage1 executor to run (only for KVM)
func (e *Networking) GetNetworkParameters() []NetParams {
	np := []NetParams{}
	_ = np
	for _, an := range e.nets {
		np = append(np, NetParams{
			HostIP:  an.runtime.HostIP,
			GuestIP: an.runtime.IP,
			IfName:  an.runtime.IfName,
			Mask:    an.runtime.Mask,
			// Net: // TODO: from where
			Name:   an.conf.Name,
			Type:   an.conf.Type,
			IPMasq: an.conf.IPMasq,
		})
	}

	return np
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/thinkofdeath/steven/chat"
	"github.com/thinkofdeath/steven/console"
	"github.com/thinkofdeath/steven/render"
	"github.com/thinkofdeath/steven/ui"
	"github.com/thinkofdeath/steven/ui/scene"
)

var con consoleScreen

type consoleScreen struct {
	scene *scene.Type

	container  *ui.Container
	background *ui.Image
	inputText  *ui.Text

	lastLine  chat.AnyComponent
	lastWidth float64

	lines []*ui.Formatted

	pos     float64
	visible bool

	prevKey  glfw.KeyCallback
	prevChar glfw.CharCallback

	input      string
	cursorTick float64
}

func (cs *consoleScreen) init() {
	cs.scene = scene.New(true)
	cs.container = ui.NewContainer(0, -220, 854, 220)
	cs.container.SetLayer(-200)
	cs.background = ui.NewImage(render.GetTexture("solid"), 0, 0, 854, 220, 0, 0, 1, 1, 0, 0, 0)
	cs.background.SetA(180)
	cs.background.AttachTo(cs.container)
	cs.scene.AddDrawable(cs.background.Attach(ui.Top, ui.Left))

	cs.inputText = ui.NewText("", 5, 200, 255, 255, 255)
	cs.inputText.AttachTo(cs.container)
	cs.scene.AddDrawable(cs.inputText.Attach(ui.Top, ui.Left))
	cs.pos = -220
	cs.visible = false
}

func (cs *consoleScreen) focus() {
	cs.visible = true

	cs.prevKey = window.SetKeyCallback(cs.onKey)
	cs.prevChar = window.SetCharCallback(cs.onChar)
}

func (cs *consoleScreen) onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if key == glfw.KeyGraveAccent && action == glfw.Release {
		cs.visible = false
		window.SetKeyCallback(cs.prevKey)
		window.SetCharCallback(cs.prevChar)
		cs.input = cs.input[:len(cs.input)-1]
	}
	if key == glfw.KeyBackspace && action != glfw.Release {
		if len(cs.input) > 0 {
			cs.input = cs.input[:len(cs.input)-1]
		}
	}
	if key == glfw.KeyEnter && action == glfw.Release {
		err := console.Execute(cs.input)
		cs.input = ""
		if err != nil {
			console.Component(chat.
				Build("Error").
				Color(chat.Red).
				Append(": ").
				Color(chat.Yellow).
				Append(err.Error()).
				Color(chat.Red).
				Create(),
			)
		}
	}
}

func (cs *consoleScreen) onChar(w *glfw.Window, char rune) {
	cs.input += string(char)
}

func (cs *consoleScreen) tick(delta float64) {
	if cs.visible {
		if cs.pos == -220 {
			cs.lastWidth = -1 // Force a redraw
		}
		if cs.pos < 0 {
			cs.pos += delta * 4
		} else {
			cs.pos = 0
		}
	} else {
		if cs.pos > -220 {
			cs.pos -= delta * 4
		} else {
			cs.pos = -220
		}
		if cs.pos == -220 {
			cs.scene.Hide()
			return
		}
	}
	cs.container.SetY(cs.pos)
	// Not the most efficent way but handles the alpha issue for
	// now
	cs.scene.Hide()
	cs.scene.Show()

	// Resize to fill the screen width
	width, _ := window.GetFramebufferSize()
	sw := 854 / float64(width)
	var w float64
	if ui.DrawMode == ui.Unscaled {
		sw = ui.Scale
		w = 854 / sw
	} else {
		w = float64(width)
	}
	cs.container.SetWidth(w)
	cs.background.SetWidth(w)

	if cs.lastLine != console.History(1)[0] || cs.lastWidth != w {
		for _, l := range cs.lines {
			l.Remove()
		}
		cs.lines = cs.lines[:0]
		hist := console.History(-1)
		offset := 200.0
		for i := 0; i < len(hist) && offset > 0; i++ {
			line := hist[i]
			if line.Value == nil {
				break
			}
			fmt := ui.NewFormattedWidth(line, 5, 0, w-10)
			offset -= fmt.Height
			fmt.SetY(offset)
			fmt.AttachTo(cs.container)
			cs.lines = append(cs.lines, fmt)
			cs.scene.AddDrawable(fmt.Attach(ui.Top, ui.Left))
		}
	}

	cs.lastWidth = w
	cs.lastLine = console.History(1)[0]

	cs.cursorTick += delta
	// Add on our cursor
	if int(cs.cursorTick/30)%2 == 0 {
		cs.inputText.Update(string(cs.input) + "|")
	} else {
		cs.inputText.Update(string(cs.input))
	}
}
<commit_msg>steven: log commands executed in the console<commit_after>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/thinkofdeath/steven/chat"
	"github.com/thinkofdeath/steven/console"
	"github.com/thinkofdeath/steven/render"
	"github.com/thinkofdeath/steven/ui"
	"github.com/thinkofdeath/steven/ui/scene"
)

var con consoleScreen

type consoleScreen struct {
	scene *scene.Type

	container  *ui.Container
	background *ui.Image
	inputText  *ui.Text

	lastLine  chat.AnyComponent
	lastWidth float64

	lines []*ui.Formatted

	pos     float64
	visible bool

	prevKey  glfw.KeyCallback
	prevChar glfw.CharCallback

	input      string
	cursorTick float64
}

func (cs *consoleScreen) init() {
	cs.scene = scene.New(true)
	cs.container = ui.NewContainer(0, -220, 854, 220)
	cs.container.SetLayer(-200)
	cs.background = ui.NewImage(render.GetTexture("solid"), 0, 0, 854, 220, 0, 0, 1, 1, 0, 0, 0)
	cs.background.SetA(180)
	cs.background.AttachTo(cs.container)
	cs.scene.AddDrawable(cs.background.Attach(ui.Top, ui.Left))

	cs.inputText = ui.NewText("", 5, 200, 255, 255, 255)
	cs.inputText.AttachTo(cs.container)
	cs.scene.AddDrawable(cs.inputText.Attach(ui.Top, ui.Left))
	cs.pos = -220
	cs.visible = false
}

func (cs *consoleScreen) focus() {
	cs.visible = true

	cs.prevKey = window.SetKeyCallback(cs.onKey)
	cs.prevChar = window.SetCharCallback(cs.onChar)
}

func (cs *consoleScreen) onKey(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if key == glfw.KeyGraveAccent && action == glfw.Release {
		cs.visible = false
		window.SetKeyCallback(cs.prevKey)
		window.SetCharCallback(cs.prevChar)
		cs.input = cs.input[:len(cs.input)-1]
	}
	if key == glfw.KeyBackspace && action != glfw.Release {
		if len(cs.input) > 0 {
			cs.input = cs.input[:len(cs.input)-1]
		}
	}
	if key == glfw.KeyEnter && action == glfw.Release {
		console.Component(chat.
			Build("> ").
			Color(chat.Yellow).
			Append(cs.input).
			Create(),
		)
		err := console.Execute(cs.input)
		cs.input = ""
		if err != nil {
			console.Component(chat.
				Build("Error").
				Color(chat.Red).
				Append(": ").
				Color(chat.Yellow).
				Append(err.Error()).
				Color(chat.Red).
				Create(),
			)
		}
	}
}

func (cs *consoleScreen) onChar(w *glfw.Window, char rune) {
	cs.input += string(char)
}

func (cs *consoleScreen) tick(delta float64) {
	if cs.visible {
		if cs.pos == -220 {
			cs.lastWidth = -1 // Force a redraw
		}
		if cs.pos < 0 {
			cs.pos += delta * 4
		} else {
			cs.pos = 0
		}
	} else {
		if cs.pos > -220 {
			cs.pos -= delta * 4
		} else {
			cs.pos = -220
		}
		if cs.pos == -220 {
			cs.scene.Hide()
			return
		}
	}
	cs.container.SetY(cs.pos)
	// Not the most efficent way but handles the alpha issue for
	// now
	cs.scene.Hide()
	cs.scene.Show()

	// Resize to fill the screen width
	width, _ := window.GetFramebufferSize()
	sw := 854 / float64(width)
	var w float64
	if ui.DrawMode == ui.Unscaled {
		sw = ui.Scale
		w = 854 / sw
	} else {
		w = float64(width)
	}
	cs.container.SetWidth(w)
	cs.background.SetWidth(w)

	if cs.lastLine != console.History(1)[0] || cs.lastWidth != w {
		for _, l := range cs.lines {
			l.Remove()
		}
		cs.lines = cs.lines[:0]
		hist := console.History(-1)
		offset := 200.0
		for i := 0; i < len(hist) && offset > 0; i++ {
			line := hist[i]
			if line.Value == nil {
				break
			}
			fmt := ui.NewFormattedWidth(line, 5, 0, w-10)
			offset -= fmt.Height
			fmt.SetY(offset)
			fmt.AttachTo(cs.container)
			cs.lines = append(cs.lines, fmt)
			cs.scene.AddDrawable(fmt.Attach(ui.Top, ui.Left))
		}
	}

	cs.lastWidth = w
	cs.lastLine = console.History(1)[0]

	cs.cursorTick += delta
	// Add on our cursor
	if int(cs.cursorTick/30)%2 == 0 {
		cs.inputText.Update(string(cs.input) + "|")
	} else {
		cs.inputText.Update(string(cs.input))
	}
}
<|endoftext|>


<commit_before>package session

import (
	"errors"
	"sync"
	"time"

	"github.com/Shopify/gozk"
)

type ZKSessionEvent uint

// NewZKSession is passed a logger to log ZK events.
type stdLogger interface {
	Printf(format string, v ...interface{})
}

// nullLogger is used when a nil interface is given
type nullLogger struct{}

func (l *nullLogger) Printf(format string, v ...interface{}) {}

// ErrZKSessionNotConnected is analogous to the SessionFailed event, but returned as an error from NewZKSession on initialization.
var ErrZKSessionNotConnected = errors.New("unable to connect to ZooKeeper")

// ErrZKSessionDisconnected indicates the session *was* connected, but has
// become disconnected in a way deemed unrecoverable.
var ErrZKSessionDisconnected = errors.New("connection to ZooKeeper was lost")

const (
	// SessionClosed is normally only returned as a direct result of calling Close() on the ZKSession object. It is a
	// terminal state; the connection will not be re-established.
	SessionClosed ZKSessionEvent = iota
	// SessionDisconnected is a transient state indicating that the connection to ZooKeeper was lost. The library is
	// attempting to reconnect and you will receive another event when it has. In the meantime, if you're using ZooKeeper
	// to implement, for example, a lock, assume you have lost the lock.
	SessionDisconnected
	// SessionReconnected is returned after a SessionDisconnected event, to indicate that the library was able to re-establish
	// its connection to the zookeeper cluster before the session timed out. Ephemeral nodes have not been torn down, so
	// any created by the previous connection still exist.
	SessionReconnected
	// SessionExpiredReconnected indicates that the session was reconnected (also happens strictly after a SessionDisconnected
	// event), but that the reconnection took longer than the session timeout, and all ephemeral nodes were purged.
	SessionExpiredReconnected
	// SessionFailed indicates that the session failed unrecoverably. This may mean incorrect credentials, or broken quorum,
	// or a partition from the entire ZooKeeper cluster, or any other mode of absolute failure.
	SessionFailed
)

type ZKSession struct {
	servers     string
	recvTimeout time.Duration
	conn        *zookeeper.Conn
	clientID    *zookeeper.ClientId
	events      <-chan zookeeper.Event
	mu          sync.Mutex

	subscriptions []chan<- ZKSessionEvent
	log           stdLogger
}

func ResumeZKSession(servers string, recvTimeout time.Duration, logger stdLogger, clientId *zookeeper.ClientId) (*ZKSession, error) {
	return newZKSession(servers, recvTimeout, logger, clientId)
}

func NewZKSession(servers string, recvTimeout time.Duration, logger stdLogger) (*ZKSession, error) {
	return newZKSession(servers, recvTimeout, logger, nil)
}

func newZKSession(servers string, recvTimeout time.Duration, logger stdLogger, clientId *zookeeper.ClientId) (*ZKSession, error) {
	var conn *zookeeper.Conn
	var events <-chan zookeeper.Event
	var err error

	if clientId == nil {
		conn, events, err = zookeeper.Dial(servers, recvTimeout)
	} else {
		conn, events, err = zookeeper.Redial(servers, recvTimeout, clientId)
	}
	if err != nil {
		return nil, err
	}

	if logger == nil {
		logger = &nullLogger{}
	}

	s := &ZKSession{
		servers:       servers,
		recvTimeout:   recvTimeout,
		conn:          conn,
		clientID:      conn.ClientId(),
		events:        events,
		subscriptions: make([]chan<- ZKSessionEvent, 0),
		log:           logger,
	}

	var event zookeeper.Event
	select {
	case event = <-events:
		if event.State == zookeeper.STATE_AUTH_FAILED || event.State == zookeeper.STATE_EXPIRED_SESSION {
			return nil, ErrZKSessionNotConnected
		}
	case <-time.After(5 * time.Second):
		return nil, ErrZKSessionNotConnected
	}

	go s.manage()

	return s, nil
}

func (s *ZKSession) Subscribe(subscription chan<- ZKSessionEvent) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.subscriptions = append(s.subscriptions, subscription)
}

func (s *ZKSession) notifySubscribers(event ZKSessionEvent) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for _, subscriber := range s.subscriptions {
		subscriber <- event
	}
}

func (s *ZKSession) manage() {
	expired := false
	for {
		select {
		case event := <-s.events:
			switch event.State {
			case zookeeper.STATE_EXPIRED_SESSION:
				expired = true
				conn, events, err := zookeeper.Redial(s.servers, s.recvTimeout, s.clientID)
				if err == nil {
					s.mu.Lock()
					s.conn = conn
					s.events = events
					s.clientID = conn.ClientId()
					s.mu.Unlock()
				}
				if err != nil {
					s.notifySubscribers(SessionFailed)
					s.log.Printf("gozk-recipes/session.SessionFailed: %s, session terminated", err.Error())
					return
				}

			case zookeeper.STATE_AUTH_FAILED:
				s.notifySubscribers(SessionFailed)
				s.log.Printf("gozk-recipes/session.SessionFailed: zookeeper.STATE_AUTH_FAILURE, session terminated")
				return

			case zookeeper.STATE_CONNECTING:
				s.notifySubscribers(SessionDisconnected)
				s.log.Printf("gozk-recipes/session.SessionDisconnected: attempting to reconnect")

			case zookeeper.STATE_ASSOCIATING:
				// No action to take, this is fine.

			case zookeeper.STATE_CONNECTED:
				if expired {
					s.notifySubscribers(SessionExpiredReconnected)
					s.log.Printf("gozk-recipes/session.SessionExpiredReconnected: all ephemeral nodes purged")
					expired = false
				} else {
					s.notifySubscribers(SessionReconnected)
					s.log.Printf("gozk-recipes/session.SessionReconnected: reconnected before timed out")
				}
			case zookeeper.STATE_CLOSED:
				s.notifySubscribers(SessionClosed)
				s.log.Printf("gozk-recipes/session.SessionClosed: normally caused by call to Close(), session terminated")
				return
			}
		}
	}
}

func (s *ZKSession) ACL(path string) ([]zookeeper.ACL, *zookeeper.Stat, error) {
	return s.conn.ACL(path)
}

func (s *ZKSession) AddAuth(scheme, cert string) error {
	return s.conn.AddAuth(scheme, cert)
}

func (s *ZKSession) Children(path string) ([]string, *zookeeper.Stat, error) {
	return s.conn.Children(path)
}

func (s *ZKSession) ChildrenW(path string) ([]string, *zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.ChildrenW(path)
}

func (s *ZKSession) ClientId() *zookeeper.ClientId {
	return s.conn.ClientId()
}

func (s *ZKSession) Close() error {
	return s.conn.Close()
}

func (s *ZKSession) Create(path string, value string, flags int, aclv []zookeeper.ACL) (string, error) {
	return s.conn.Create(path, value, flags, aclv)
}

func (s *ZKSession) Delete(path string, version int) error {
	return s.conn.Delete(path, version)
}

func (s *ZKSession) Exists(path string) (*zookeeper.Stat, error) {
	return s.conn.Exists(path)
}

func (s *ZKSession) ExistsW(path string) (*zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.ExistsW(path)
}

func (s *ZKSession) Get(path string) (string, *zookeeper.Stat, error) {
	return s.conn.Get(path)
}

func (s *ZKSession) GetW(path string) (string, *zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.GetW(path)
}

func (s *ZKSession) Set(path string, value string, version int) (*zookeeper.Stat, error) {
	return s.conn.Set(path, value, version)
}

func (s *ZKSession) RetryChange(path string, flags int, acl []zookeeper.ACL, changeFunc zookeeper.ChangeFunc) error {
	return s.conn.RetryChange(path, flags, acl, changeFunc)
}

func (s *ZKSession) SetACL(path string, aclv []zookeeper.ACL, version int) error {
	return s.conn.SetACL(path, aclv, version)
}
<commit_msg>wait in for loop to ensure connected state<commit_after>package session

import (
	"errors"
	"sync"
	"time"

	"github.com/Shopify/gozk"
)

type ZKSessionEvent uint

// NewZKSession is passed a logger to log ZK events.
type stdLogger interface {
	Printf(format string, v ...interface{})
}

// nullLogger is used when a nil interface is given
type nullLogger struct{}

func (l *nullLogger) Printf(format string, v ...interface{}) {}

// ErrZKSessionNotConnected is analogous to the SessionFailed event, but returned as an error from NewZKSession on initialization.
var ErrZKSessionNotConnected = errors.New("unable to connect to ZooKeeper")

// ErrZKSessionDisconnected indicates the session *was* connected, but has
// become disconnected in a way deemed unrecoverable.
var ErrZKSessionDisconnected = errors.New("connection to ZooKeeper was lost")

const (
	// SessionClosed is normally only returned as a direct result of calling Close() on the ZKSession object. It is a
	// terminal state; the connection will not be re-established.
	SessionClosed ZKSessionEvent = iota
	// SessionDisconnected is a transient state indicating that the connection to ZooKeeper was lost. The library is
	// attempting to reconnect and you will receive another event when it has. In the meantime, if you're using ZooKeeper
	// to implement, for example, a lock, assume you have lost the lock.
	SessionDisconnected
	// SessionReconnected is returned after a SessionDisconnected event, to indicate that the library was able to re-establish
	// its connection to the zookeeper cluster before the session timed out. Ephemeral nodes have not been torn down, so
	// any created by the previous connection still exist.
	SessionReconnected
	// SessionExpiredReconnected indicates that the session was reconnected (also happens strictly after a SessionDisconnected
	// event), but that the reconnection took longer than the session timeout, and all ephemeral nodes were purged.
	SessionExpiredReconnected
	// SessionFailed indicates that the session failed unrecoverably. This may mean incorrect credentials, or broken quorum,
	// or a partition from the entire ZooKeeper cluster, or any other mode of absolute failure.
	SessionFailed
)

type ZKSession struct {
	servers     string
	recvTimeout time.Duration
	conn        *zookeeper.Conn
	clientID    *zookeeper.ClientId
	events      <-chan zookeeper.Event
	mu          sync.Mutex

	subscriptions []chan<- ZKSessionEvent
	log           stdLogger
}

func ResumeZKSession(servers string, recvTimeout time.Duration, logger stdLogger, clientId *zookeeper.ClientId) (*ZKSession, error) {
	return newZKSession(servers, recvTimeout, logger, clientId)
}

func NewZKSession(servers string, recvTimeout time.Duration, logger stdLogger) (*ZKSession, error) {
	return newZKSession(servers, recvTimeout, logger, nil)
}

func newZKSession(servers string, recvTimeout time.Duration, logger stdLogger, clientId *zookeeper.ClientId) (*ZKSession, error) {
	var conn *zookeeper.Conn
	var events <-chan zookeeper.Event
	var err error

	if clientId == nil {
		conn, events, err = zookeeper.Dial(servers, recvTimeout)
	} else {
		conn, events, err = zookeeper.Redial(servers, recvTimeout, clientId)
	}
	if err != nil {
		return nil, err
	}

	if logger == nil {
		logger = &nullLogger{}
	}

	s := &ZKSession{
		servers:       servers,
		recvTimeout:   recvTimeout,
		conn:          conn,
		clientID:      conn.ClientId(),
		events:        events,
		subscriptions: make([]chan<- ZKSessionEvent, 0),
		log:           logger,
	}

	var event zookeeper.Event

	Loop:
		for {
			select {
			case event = <-events:
				switch event.State {
					case zookeeper.STATE_AUTH_FAILED:
						return nil, ErrZKSessionNotConnected
					case zookeeper.STATE_EXPIRED_SESSION:
						return nil, ErrZKSessionNotConnected
					case zookeeper.STATE_CLOSED:
						return nil, ErrZKSessionNotConnected
					case zookeeper.STATE_CONNECTED:
						break Loop
				}
			case <-time.After(5 * time.Second):
				return nil, ErrZKSessionNotConnected
			}
		}

	go s.manage()

	return s, nil
}

func (s *ZKSession) Subscribe(subscription chan<- ZKSessionEvent) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.subscriptions = append(s.subscriptions, subscription)
}

func (s *ZKSession) notifySubscribers(event ZKSessionEvent) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for _, subscriber := range s.subscriptions {
		subscriber <- event
	}
}

func (s *ZKSession) manage() {
	expired := false
	for {
		select {
		case event := <-s.events:
			switch event.State {
			case zookeeper.STATE_EXPIRED_SESSION:
				expired = true
				conn, events, err := zookeeper.Redial(s.servers, s.recvTimeout, s.clientID)
				if err == nil {
					s.mu.Lock()
					s.conn = conn
					s.events = events
					s.clientID = conn.ClientId()
					s.mu.Unlock()
				}
				if err != nil {
					s.notifySubscribers(SessionFailed)
					s.log.Printf("gozk-recipes/session.SessionFailed: %s, session terminated", err.Error())
					return
				}

			case zookeeper.STATE_AUTH_FAILED:
				s.notifySubscribers(SessionFailed)
				s.log.Printf("gozk-recipes/session.SessionFailed: zookeeper.STATE_AUTH_FAILURE, session terminated")
				return

			case zookeeper.STATE_CONNECTING:
				s.notifySubscribers(SessionDisconnected)
				s.log.Printf("gozk-recipes/session.SessionDisconnected: attempting to reconnect")

			case zookeeper.STATE_ASSOCIATING:
				// No action to take, this is fine.

			case zookeeper.STATE_CONNECTED:
				if expired {
					s.notifySubscribers(SessionExpiredReconnected)
					s.log.Printf("gozk-recipes/session.SessionExpiredReconnected: all ephemeral nodes purged")
					expired = false
				} else {
					s.notifySubscribers(SessionReconnected)
					s.log.Printf("gozk-recipes/session.SessionReconnected: reconnected before timed out")
				}
			case zookeeper.STATE_CLOSED:
				s.notifySubscribers(SessionClosed)
				s.log.Printf("gozk-recipes/session.SessionClosed: normally caused by call to Close(), session terminated")
				return
			}
		}
	}
}

func (s *ZKSession) ACL(path string) ([]zookeeper.ACL, *zookeeper.Stat, error) {
	return s.conn.ACL(path)
}

func (s *ZKSession) AddAuth(scheme, cert string) error {
	return s.conn.AddAuth(scheme, cert)
}

func (s *ZKSession) Children(path string) ([]string, *zookeeper.Stat, error) {
	return s.conn.Children(path)
}

func (s *ZKSession) ChildrenW(path string) ([]string, *zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.ChildrenW(path)
}

func (s *ZKSession) ClientId() *zookeeper.ClientId {
	return s.conn.ClientId()
}

func (s *ZKSession) Close() error {
	return s.conn.Close()
}

func (s *ZKSession) Create(path string, value string, flags int, aclv []zookeeper.ACL) (string, error) {
	return s.conn.Create(path, value, flags, aclv)
}

func (s *ZKSession) Delete(path string, version int) error {
	return s.conn.Delete(path, version)
}

func (s *ZKSession) Exists(path string) (*zookeeper.Stat, error) {
	return s.conn.Exists(path)
}

func (s *ZKSession) ExistsW(path string) (*zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.ExistsW(path)
}

func (s *ZKSession) Get(path string) (string, *zookeeper.Stat, error) {
	return s.conn.Get(path)
}

func (s *ZKSession) GetW(path string) (string, *zookeeper.Stat, <-chan zookeeper.Event, error) {
	return s.conn.GetW(path)
}

func (s *ZKSession) Set(path string, value string, version int) (*zookeeper.Stat, error) {
	return s.conn.Set(path, value, version)
}

func (s *ZKSession) RetryChange(path string, flags int, acl []zookeeper.ACL, changeFunc zookeeper.ChangeFunc) error {
	return s.conn.RetryChange(path, flags, acl, changeFunc)
}

func (s *ZKSession) SetACL(path string, aclv []zookeeper.ACL, version int) error {
	return s.conn.SetACL(path, aclv, version)
}
<|endoftext|>


<commit_before>package dns

import (
	"fmt"
	"net"
	"sort"

	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceDnsARecordSet() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceDnsARecordSetRead,
		Schema: map[string]*schema.Schema{
			"host": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"addrs": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Computed: true,
			},
		},
	}
}

func dataSourceDnsARecordSetRead(d *schema.ResourceData, meta interface{}) error {
	host := d.Get("host").(string)

	records, err := net.LookupIP(host)
	if err != nil {
		return fmt.Errorf("error looking up A records for %q: %s", host, err)
	}

	addrs := make([]string, 0)

	for _, ip := range records {
		// LookupIP returns A (IPv4) and AAAA (IPv6) records
		// Filter out AAAA records
		if ipv4 := ip.To4(); ipv4 != nil {
			addrs = append(addrs, ipv4.String())
		}
	}

	sort.Strings(addrs)

	d.Set("addrs", addrs)
	d.SetId(host)

	return nil
}<commit_msg>gofmt a file<commit_after>package dns

import (
	"fmt"
	"net"
	"sort"

	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceDnsARecordSet() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceDnsARecordSetRead,
		Schema: map[string]*schema.Schema{
			"host": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"addrs": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Computed: true,
			},
		},
	}
}

func dataSourceDnsARecordSetRead(d *schema.ResourceData, meta interface{}) error {
	host := d.Get("host").(string)

	records, err := net.LookupIP(host)
	if err != nil {
		return fmt.Errorf("error looking up A records for %q: %s", host, err)
	}

	addrs := make([]string, 0)

	for _, ip := range records {
		// LookupIP returns A (IPv4) and AAAA (IPv6) records
		// Filter out AAAA records
		if ipv4 := ip.To4(); ipv4 != nil {
			addrs = append(addrs, ipv4.String())
		}
	}

	sort.Strings(addrs)

	d.Set("addrs", addrs)
	d.SetId(host)

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Prometheus 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.

// A simple example exposing fictional RPC latencies with different types of
// random distributions (uniform, normal, and exponential) as Prometheus
// metrics.
package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"math/rand"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	addr              = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
	uniformDomain     = flag.Float64("uniform.domain", 0.0002, "The domain for the uniform distribution.")
	normDomain        = flag.Float64("normal.domain", 0.0002, "The domain for the normal distribution.")
	normMean          = flag.Float64("normal.mean", 0.00001, "The mean for the normal distribution.")
	oscillationPeriod = flag.Duration("oscillation-period", 10*time.Minute, "The duration of the rate oscillation period.")
)

var (
	// Create a summary to track fictional interservice RPC latencies for three
	// distinct services with different latency distributions. These services are
	// differentiated via a "service" label.
	rpcDurations = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Name:       "rpc_durations_seconds",
			Help:       "RPC latency distributions.",
			Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
		},
		[]string{"service"},
	)
	// The same as above, but now as a histogram, and only for the normal
	// distribution. The buckets are targeted to the parameters of the
	// normal distribution, with 20 buckets centered on the mean, each
	// half-sigma wide.
	rpcDurationsHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{
		Name:    "rpc_durations_histogram_seconds",
		Help:    "RPC latency distributions.",
		Buckets: prometheus.LinearBuckets(*normMean-5**normDomain, .5**normDomain, 20),
	})
)

func init() {
	// Register the summary and the histogram with Prometheus's default registry.
	prometheus.MustRegister(rpcDurations)
	prometheus.MustRegister(rpcDurationsHistogram)
	// Add Go module build info.
	prometheus.MustRegister(prometheus.NewBuildInfoCollector())
}

func main() {
	flag.Parse()

	start := time.Now()

	oscillationFactor := func() float64 {
		return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
	}

	// Periodically record some sample latencies for the three services.
	go func() {
		for {
			v := rand.Float64() * *uniformDomain
			rpcDurations.WithLabelValues("uniform").Observe(v)
			time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
		}
	}()

	go func() {
		for {
			v := (rand.NormFloat64() * *normDomain) + *normMean
			rpcDurations.WithLabelValues("normal").Observe(v)
			// Demonstrate exemplar support with a dummy ID. This
			// would be something like a trace ID in a real
			// application.  Note the necessary type assertion. We
			// already know that rpcDurationsHistogram implements
			// the ExemplarObserver interface and thus don't need to
			// check the outcome of the type assertion.
			rpcDurationsHistogram.(prometheus.ExemplarObserver).ObserveWithExemplar(
				v, prometheus.Labels{"dummyID": fmt.Sprint(rand.Intn(100000))},
			)
			time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond)
		}
	}()

	go func() {
		for {
			v := rand.ExpFloat64() / 1e6
			rpcDurations.WithLabelValues("exponential").Observe(v)
			time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond)
		}
	}()

	// Expose the registered metrics via HTTP.
	http.Handle("/metrics", promhttp.HandlerFor(
		prometheus.DefaultGatherer,
		promhttp.HandlerOpts{
			// Opt into OpenMetrics to support exemplars.
			EnableOpenMetrics: true,
		},
	))
	log.Fatal(http.ListenAndServe(*addr, nil))
}
<commit_msg>Move flags and metrics into main()<commit_after>// Copyright 2015 The Prometheus 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.

// A simple example exposing fictional RPC latencies with different types of
// random distributions (uniform, normal, and exponential) as Prometheus
// metrics.
package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"math/rand"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
	var (
		addr              = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
		uniformDomain     = flag.Float64("uniform.domain", 0.0002, "The domain for the uniform distribution.")
		normDomain        = flag.Float64("normal.domain", 0.0002, "The domain for the normal distribution.")
		normMean          = flag.Float64("normal.mean", 0.00001, "The mean for the normal distribution.")
		oscillationPeriod = flag.Duration("oscillation-period", 10*time.Minute, "The duration of the rate oscillation period.")
	)

	flag.Parse()

	var (
		// Create a summary to track fictional interservice RPC latencies for three
		// distinct services with different latency distributions. These services are
		// differentiated via a "service" label.
		rpcDurations = prometheus.NewSummaryVec(
			prometheus.SummaryOpts{
				Name:       "rpc_durations_seconds",
				Help:       "RPC latency distributions.",
				Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
			},
			[]string{"service"},
		)
		// The same as above, but now as a histogram, and only for the normal
		// distribution. The buckets are targeted to the parameters of the
		// normal distribution, with 20 buckets centered on the mean, each
		// half-sigma wide.
		rpcDurationsHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{
			Name:    "rpc_durations_histogram_seconds",
			Help:    "RPC latency distributions.",
			Buckets: prometheus.LinearBuckets(*normMean-5**normDomain, .5**normDomain, 20),
		})
	)

	// Register the summary and the histogram with Prometheus's default registry.
	prometheus.MustRegister(rpcDurations)
	prometheus.MustRegister(rpcDurationsHistogram)
	// Add Go module build info.
	prometheus.MustRegister(prometheus.NewBuildInfoCollector())

	start := time.Now()

	oscillationFactor := func() float64 {
		return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
	}

	// Periodically record some sample latencies for the three services.
	go func() {
		for {
			v := rand.Float64() * *uniformDomain
			rpcDurations.WithLabelValues("uniform").Observe(v)
			time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
		}
	}()

	go func() {
		for {
			v := (rand.NormFloat64() * *normDomain) + *normMean
			rpcDurations.WithLabelValues("normal").Observe(v)
			// Demonstrate exemplar support with a dummy ID. This
			// would be something like a trace ID in a real
			// application.  Note the necessary type assertion. We
			// already know that rpcDurationsHistogram implements
			// the ExemplarObserver interface and thus don't need to
			// check the outcome of the type assertion.
			rpcDurationsHistogram.(prometheus.ExemplarObserver).ObserveWithExemplar(
				v, prometheus.Labels{"dummyID": fmt.Sprint(rand.Intn(100000))},
			)
			time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond)
		}
	}()

	go func() {
		for {
			v := rand.ExpFloat64() / 1e6
			rpcDurations.WithLabelValues("exponential").Observe(v)
			time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond)
		}
	}()

	// Expose the registered metrics via HTTP.
	http.Handle("/metrics", promhttp.HandlerFor(
		prometheus.DefaultGatherer,
		promhttp.HandlerOpts{
			// Opt into OpenMetrics to support exemplars.
			EnableOpenMetrics: true,
		},
	))
	log.Fatal(http.ListenAndServe(*addr, nil))
}
<|endoftext|>