<commit_before>// ************
// Inspired by : https://semaphoreci.com/community/tutorials/building-and-testing-a-rest-api-in-go-with-gorilla-mux-and-postgresql
// ************

package main_test

import (
	"."
	"bytes"
	"encoding/json"
	"github.com/spf13/viper"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"strings"
	"testing"
)

var app main.App

const tableCreationQuery = `CREATE TABLE IF NOT EXISTS orders
(
id SERIAL,
NAME TEXT NOT NULL,
price NUMERIC (10, 2) NOT NULL DEFAULT 0.00,
CONSTRAINT orders_pkey PRIMARY KEY (id)
)`

func TestMain(m *testing.M) {

	viper.SetConfigName("config")
	viper.AddConfigPath(".")
	viper.ReadInConfig()

	app = main.App{}
	app.Initialize(
		viper.GetString("testing.dbUser"),
		viper.GetString("testing.dbPass"),
		viper.GetString("testing.db"))

	ensureTableExists()
	code := m.Run()
	clearTable()

	os.Exit(code)
}

func ensureTableExists() {
	if _, err := app.DB.Exec(tableCreationQuery); err != nil {
		log.Fatal(err)
	}
}

func clearTable() {
	app.DB.Exec("DELETE FROM orders")
	app.DB.Exec("ALTER SEQUENCE orders_id_seq RESTART WITH 1")
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {
	rr := httptest.NewRecorder()
	app.Router.ServeHTTP(rr, req)

	return rr
}

func checkResponseCode(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected response code %d. Got %d\n", expected, actual)
	}
}

// Model: TODOs
func TestGetTodos(t *testing.T) {
	req, _ := http.NewRequest("GET", "/todos", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

// Model: Order
func TestEmptyTable(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)

	if body := response.Body.String(); strings.TrimSpace(body) != "[]" {
		t.Errorf("Expected an empty array. Got %s", body)
	}
}

func TestGetNonExistentProduct(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/order/999", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusNotFound, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["text"] != "order not found" {
		t.Errorf("Expected the 'text' key of the response to be set to 'order not found'. Got '%s'", m["text"])
	}
}

func TestGetOrders(t *testing.T) {
	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func TestGetOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func addProducts(count int) {
	if count < 1 {
		count = 1
	}

	for i := 0; i < count; i++ {
		app.DB.Exec("INSERT INTO orders(name, price) VALUES($1, $2)", "Order "+strconv.Itoa(i), (i+1.0)*10)
	}
}

func TestCreateorder(t *testing.T) {
	clearTable()
	payload := []byte(`{"name": "test order", "price": 11.22 }`)

	req, _ := http.NewRequest("POST", "/order", bytes.NewBuffer(payload))
	response := executeRequest(req)
	checkResponseCode(t, http.StatusCreated, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["name"] != "test order" {
		t.Errorf("expected name to be 'test order'. Got %v", m["name"])
	}

	if m["price"] != 11.22 {
		t.Errorf("expected price to be '11.22'. Got %v", m["price"])
	}

	// m[string]interface{} converts int to float
	if m["id"] != 1.0 {
		t.Errorf("expected id to be '1.0'. Got %v", m["id"])
	}

}

func TestUpdateOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var originalOrder map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &originalOrder)

	payload := []byte(`{"name": "updated order", "price": 11.22 }`)

	req, _ = http.NewRequest("PUT", "/order/1", bytes.NewBuffer(payload))
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["id"] != originalOrder["id"] {
		t.Errorf("Expected the id to remain the same (%v). Got %v", originalOrder["id"], m["id"])
	}

	if m["name"] == originalOrder["name"] {
		t.Errorf("Expected the name to change from '%v' to '%v'. Got '%v'", originalOrder["name"], m["name"], m["name"])
	}

	if m["price"] == originalOrder["price"] {
		t.Errorf("Expected the price to change from '%v' to '%v'. Got '%v'", originalOrder["price"], m["price"], m["price"])
	}
}

func TestDeleteOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("DELETE", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("GET", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusNotFound, response.Code)

}
<commit_msg>v3: Middleware for logging<commit_after>// ************
// Inspired by : https://semaphoreci.com/community/tutorials/building-and-testing-a-rest-api-in-go-with-gorilla-mux-and-postgresql
// ************

package main_test

import (
	"."
	"bytes"
	"encoding/json"
	"github.com/spf13/viper"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"strings"
	"testing"
)

var app main.App

const tableCreationQuery = `CREATE TABLE IF NOT EXISTS orders
(
id SERIAL,
NAME TEXT NOT NULL,
price NUMERIC (10, 2) NOT NULL DEFAULT 0.00,
CONSTRAINT orders_pkey PRIMARY KEY (id)
)`

func TestMain(m *testing.M) {

	viper.SetConfigName("config")
	viper.AddConfigPath(".")
	viper.ReadInConfig()

	app = main.App{}
	app.Initialize(
		viper.GetString("testing.dbUser"),
		viper.GetString("testing.dbPass"),
		viper.GetString("testing.db"))

	ensureTableExists()
	code := m.Run()
	clearTable()

	os.Exit(code)
}

func ensureTableExists() {
	if _, err := app.DB.Exec(tableCreationQuery); err != nil {
		log.Fatal(err)
	}
}

func clearTable() {
	app.DB.Exec("DELETE FROM orders")
	app.DB.Exec("ALTER SEQUENCE orders_id_seq RESTART WITH 1")
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {
	rr := httptest.NewRecorder()
	app.Router.ServeHTTP(rr, req)

	return rr
}

func checkResponseCode(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected response code %d. Got %d\n", expected, actual)
	}
}

// Model: TODOs
func Test_GetTodos(t *testing.T) {
	req, _ := http.NewRequest("GET", "/todos", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

// Model: Order
func Test_EmptyTable(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)

	if body := response.Body.String(); strings.TrimSpace(body) != "[]" {
		t.Errorf("Expected an empty array. Got %s", body)
	}
}

func Test_GetNonExistentProduct(t *testing.T) {
	clearTable()

	req, _ := http.NewRequest("GET", "/order/999", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusNotFound, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["text"] != "order not found" {
		t.Errorf("Expected the 'text' key of the response to be set to 'order not found'. Got '%s'", m["text"])
	}
}

func Test_GetOrders(t *testing.T) {
	req, _ := http.NewRequest("GET", "/orders", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func Test_GetOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)

	checkResponseCode(t, http.StatusOK, response.Code)
}

func addProducts(count int) {
	if count < 1 {
		count = 1
	}

	for i := 0; i < count; i++ {
		app.DB.Exec("INSERT INTO orders(name, price) VALUES($1, $2)", "Order "+strconv.Itoa(i), (i+1.0)*10)
	}
}

func Test_Createorder(t *testing.T) {
	clearTable()
	payload := []byte(`{"name": "test order", "price": 11.22 }`)

	req, _ := http.NewRequest("POST", "/order", bytes.NewBuffer(payload))
	response := executeRequest(req)
	checkResponseCode(t, http.StatusCreated, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["name"] != "test order" {
		t.Errorf("expected name to be 'test order'. Got %v", m["name"])
	}

	if m["price"] != 11.22 {
		t.Errorf("expected price to be '11.22'. Got %v", m["price"])
	}

	// m[string]interface{} converts int to float
	if m["id"] != 1.0 {
		t.Errorf("expected id to be '1.0'. Got %v", m["id"])
	}

}

func Test_UpdateOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var originalOrder map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &originalOrder)

	payload := []byte(`{"name": "updated order", "price": 11.22 }`)

	req, _ = http.NewRequest("PUT", "/order/1", bytes.NewBuffer(payload))
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	var m map[string]interface{}
	json.Unmarshal(response.Body.Bytes(), &m)

	if m["id"] != originalOrder["id"] {
		t.Errorf("Expected the id to remain the same (%v). Got %v", originalOrder["id"], m["id"])
	}

	if m["name"] == originalOrder["name"] {
		t.Errorf("Expected the name to change from '%v' to '%v'. Got '%v'", originalOrder["name"], m["name"], m["name"])
	}

	if m["price"] == originalOrder["price"] {
		t.Errorf("Expected the price to change from '%v' to '%v'. Got '%v'", originalOrder["price"], m["price"], m["price"])
	}
}

func Test_DeleteOrder(t *testing.T) {
	clearTable()
	addProducts(1)

	req, _ := http.NewRequest("GET", "/order/1", nil)
	response := executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("DELETE", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusOK, response.Code)

	req, _ = http.NewRequest("GET", "/order/1", nil)
	response = executeRequest(req)
	checkResponseCode(t, http.StatusNotFound, response.Code)

}
<|endoftext|>


<commit_before>package srtp

import (
	"context"
	"encoding/binary"

	"v2ray.com/core/common"
	"v2ray.com/core/common/dice"
)

type SRTP struct {
	header uint16
	number uint16
}

func (*SRTP) Size() int32 {
	return 4
}

// Serialize implements PacketHeader.
func (s *SRTP) Serialize(b []byte) {
	s.number++
	binary.BigEndian.PutUint16(b, s.number)
	binary.BigEndian.PutUint16(b[2:], s.number)
}

// New returns a new SRTP instance based on the given config.
func New(ctx context.Context, config interface{}) (interface{}, error) {
	return &SRTP{
		header: 0xB5E8,
		number: dice.RollUint16(),
	}, nil
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), New))
}
<commit_msg>fix srtp header<commit_after>package srtp

import (
	"context"
	"encoding/binary"

	"v2ray.com/core/common"
	"v2ray.com/core/common/dice"
)

type SRTP struct {
	header uint16
	number uint16
}

func (*SRTP) Size() int32 {
	return 4
}

// Serialize implements PacketHeader.
func (s *SRTP) Serialize(b []byte) {
	s.number++
	binary.BigEndian.PutUint16(b, s.header)
	binary.BigEndian.PutUint16(b[2:], s.number)
}

// New returns a new SRTP instance based on the given config.
func New(ctx context.Context, config interface{}) (interface{}, error) {
	return &SRTP{
		header: 0xB5E8,
		number: dice.RollUint16(),
	}, nil
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), New))
}
<|endoftext|>


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

package terminalapi

// color_mode.go defines the terminal color modes.

// ColorMode represents
type ColorMode int

// String implements fmt.Stringer()
func (cm ColorMode) String() string {
	if n, ok := colorModeNames[cm]; ok {
		return n
	}
	return "ColorModeUnknown"
}

// colorModeNames maps ColorMode values to human readable names.
var colorModeNames = map[ColorMode]string{
	ColorModeNormal:    "ColorModeNormal",
	ColorMode256:       "ColorMode256",
	ColorMode216:       "ColorMode216",
	ColorModeGrayscale: "ColorModeGrayscale",
}

// Supported color modes.
const (
	// ColorModeNormal supports 8 "system" colors.
	// These are defined as constants in the cell package.
	ColorModeNormal ColorMode = iota

	// ColorMode256 enables using any of the 256 terminal colors.
	//     0-7: the 8 "system" colors accessible in ColorModeNormal.
	//    8-15: the 8 "bright system" colors.
	//  16-231: the 216 different terminal colors.
	// 232-255: the 24 different shades of grey.
	ColorMode256

	// ColorMode216 supports only the third range of the ColorMode256, i.e the
	// 216 different terminal colors. However in this mode the colors are zero
	// based, so the caller doesn't need to provide an offset.
	ColorMode216

	// ColorModeGrayscale supports only the fourth range of the ColorMode256,
	// i.e the 24 different shades of grey. However in this mode the colors are
	// zero based, so the caller doesn't need to provide an offset.
	ColorModeGrayscale
)
<commit_msg>Finishing unfinished comment.<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package terminalapi

// color_mode.go defines the terminal color modes.

// ColorMode represents a color mode of a terminal.
type ColorMode int

// String implements fmt.Stringer()
func (cm ColorMode) String() string {
	if n, ok := colorModeNames[cm]; ok {
		return n
	}
	return "ColorModeUnknown"
}

// colorModeNames maps ColorMode values to human readable names.
var colorModeNames = map[ColorMode]string{
	ColorModeNormal:    "ColorModeNormal",
	ColorMode256:       "ColorMode256",
	ColorMode216:       "ColorMode216",
	ColorModeGrayscale: "ColorModeGrayscale",
}

// Supported color modes.
const (
	// ColorModeNormal supports 8 "system" colors.
	// These are defined as constants in the cell package.
	ColorModeNormal ColorMode = iota

	// ColorMode256 enables using any of the 256 terminal colors.
	//     0-7: the 8 "system" colors accessible in ColorModeNormal.
	//    8-15: the 8 "bright system" colors.
	//  16-231: the 216 different terminal colors.
	// 232-255: the 24 different shades of grey.
	ColorMode256

	// ColorMode216 supports only the third range of the ColorMode256, i.e the
	// 216 different terminal colors. However in this mode the colors are zero
	// based, so the caller doesn't need to provide an offset.
	ColorMode216

	// ColorModeGrayscale supports only the fourth range of the ColorMode256,
	// i.e the 24 different shades of grey. However in this mode the colors are
	// zero based, so the caller doesn't need to provide an offset.
	ColorModeGrayscale
)
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

import (
	. "github.com/FactomProject/factom"
	"testing"

	"os"

	"github.com/FactomProject/factom/wallet"
	"github.com/FactomProject/factom/wallet/wsapi"
)

func TestImportKoinify(t *testing.T) {
	var (
		good_mnemonic = "yellow yellow yellow yellow yellow yellow yellow"+
		" yellow yellow yellow yellow yellow"   // good
		koinifyexpect = "FA3cih2o2tjEUsnnFR4jX1tQXPpSXFwsp3rhVp6odL5PNCHWvZV1"

		bad_mnemonic = []string{
			"",                        // bad empty
			"yellow yellow yellow yellow yellow yellow yellow yellow yellow"+
			" yellow yellow",          // bad short
			"yellow yellow yellow yellow yellow yellow yellow yellow yellow"+
			" yellow yellow asdfasdf", // bad word
		}
	)

	// start the test wallet
	done, err := StartTestWallet()
	if err != nil {
		t.Error(err)
	}
	defer func() { done <- 1 }()

	// check the import for koinify names
	fa, err := ImportKoinify(good_mnemonic)
	if err != nil {
		t.Error(err)
	}
	if fa.String() != koinifyexpect {
		t.Error("Incorrect address from Koinify mnemonic", fa, koinifyexpect)
	}

	for _, m := range bad_mnemonic {
		if _, err := ImportKoinify(m); err == nil {
			t.Error("No error for bad address:", m)
		}
	}
}

// helper functions for testing

func populateTestWallet() error {
	//FA3T1gTkuKGG2MWpAkskSoTnfjxZDKVaAYwziNTC1pAYH5B9A1rh
	//Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA
	//
	//FA3oaS2D2GkrZJuWuiDohnLruxV3AWbrM3PmG3HSSE7DHzPWio36
	//Fs1os7xg2mN9fTuJmaYZLk6EXz51x2wmmHr2365UAuPMJW3aNr25
	//
	//EC2CyGKaNddLFxrjkFgiaRZnk77b8iQia3Zj6h5fxFReAcDwCo3i
	//Es4KmwK65t9HCsibYzVDFrijvkgTFZKdEaEAgfMtYTPSVtM3NDSx
	//
	//EC2R4bPDj9WQ8eWA4X3K8NYfTkBh4HFvCopLBq48FyrNXNumSK6w
	//Es355qB6tWo1ZZRTK8cXpHjxGECXaPGw98AFCRJ6kxZ3J6vp1M2i

	_, _, err := ImportAddresses(
		"Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA",
		"Fs1os7xg2mN9fTuJmaYZLk6EXz51x2wmmHr2365UAuPMJW3aNr25",
		"Es4KmwK65t9HCsibYzVDFrijvkgTFZKdEaEAgfMtYTPSVtM3NDSx",
		"Es355qB6tWo1ZZRTK8cXpHjxGECXaPGw98AFCRJ6kxZ3J6vp1M2i",
	)
	if err != nil {
		return err
	}

	return nil
}

// StartTestWallet runs a test wallet and serves the wallet api. The caller
// must write an int to the chan when compleate to stop the wallet api and
// remove the test db.
func StartTestWallet() (chan int, error) {
	var (
		walletdbfile = os.TempDir() + "/testingwallet.bolt"
		txdbfile     = os.TempDir() + "/testingtxdb.bolt"
	)

	// make a chan to signal when the test is finished with the wallet
	done := make(chan int, 1)

	// setup a testing wallet
	fctWallet, err := wallet.NewOrOpenBoltDBWallet(walletdbfile)
	if err != nil {
		return nil, err
	}
	defer os.Remove(walletdbfile)

	txdb, err := wallet.NewTXBoltDB(txdbfile)
	if err != nil {
		return nil, err
	} else {
		fctWallet.AddTXDB(txdb)
	}
	defer os.Remove(txdbfile)

	RpcConfig = &RPCConfig{
		WalletTLSEnable:   false,
		WalletTLSKeyFile:  "",
		WalletTLSCertFile: "",
		WalletRPCUser:     "",
		WalletRPCPassword: "",
		WalletServer:      "localhost:8089",
	}

	go wsapi.Start(fctWallet, ":8089", *RpcConfig)
	go func() {
		<-done
		wsapi.Stop()
		fctWallet.Close()
		txdb.Close()
	}()

	return done, nil
}

<commit_msg>added test for ImportAddress<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom_test

import (
	. "github.com/FactomProject/factom"
	"testing"

	"os"

	"github.com/FactomProject/factom/wallet"
	"github.com/FactomProject/factom/wallet/wsapi"
)

func TestImportAddress(t *testing.T) {
	var (
		fs1 = "Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA"
		fa1 = "FA3T1gTkuKGG2MWpAkskSoTnfjxZDKVaAYwziNTC1pAYH5B9A1rh"
		es1 = "Es4KmwK65t9HCsibYzVDFrijvkgTFZKdEaEAgfMtYTPSVtM3NDSx"
		ec1 = "EC2CyGKaNddLFxrjkFgiaRZnk77b8iQia3Zj6h5fxFReAcDwCo3i"

		bads = []string{
			"Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeX",  //short
			"Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeeA", //check
			"",                                                     //empty
			"Fc2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA", //prefix
		}
	)

	// start the test wallet
	done, err := StartTestWallet()
	if err != nil {
		t.Error(err)
	}
	defer func() { done <- 1 }()

	// import the good addresses
	if _, _, err := ImportAddresses(fs1, es1); err != nil {
		t.Error(err)
	}

	if f, err := FetchFactoidAddress(fa1); err != nil {
		t.Error(err)
	} else if f == nil {
		t.Error("Wallet returned nil factoid address")
	} else if f.SecString() != fs1 {
		t.Error("Wallet returned incorrect address", fs1, f.SecString())
	}

	if e, err := FetchECAddress(ec1); err != nil {
		t.Error(err)
	} else if e == nil {
		t.Error("Wallet returned nil ec address")
	} else if e.SecString() != es1 {
		t.Error("Wallet returned incorrect address", es1, e.SecString())
	}

	// try to import the bad addresses
	for _, bad := range bads {
		if _, _, err := ImportAddresses(bad); err == nil {
			t.Error("Bad address was imported without error", bad)
		}
	}
}

func TestImportKoinify(t *testing.T) {
	var (
		good_mnemonic = "yellow yellow yellow yellow yellow yellow yellow"+
		" yellow yellow yellow yellow yellow"   // good
		koinifyexpect = "FA3cih2o2tjEUsnnFR4jX1tQXPpSXFwsp3rhVp6odL5PNCHWvZV1"

		bad_mnemonic = []string{
			"",                        // bad empty
			"yellow yellow yellow yellow yellow yellow yellow yellow yellow"+
			" yellow yellow",          // bad short
			"yellow yellow yellow yellow yellow yellow yellow yellow yellow"+
			" yellow yellow asdfasdf", // bad word
		}
	)

	// start the test wallet
	done, err := StartTestWallet()
	if err != nil {
		t.Error(err)
	}
	defer func() { done <- 1 }()

	// check the import for koinify names
	fa, err := ImportKoinify(good_mnemonic)
	if err != nil {
		t.Error(err)
	}
	if fa.String() != koinifyexpect {
		t.Error("Incorrect address from Koinify mnemonic", fa, koinifyexpect)
	}

	for _, m := range bad_mnemonic {
		if _, err := ImportKoinify(m); err == nil {
			t.Error("No error for bad address:", m)
		}
	}
}

// helper functions for testing

func populateTestWallet() error {
	//FA3T1gTkuKGG2MWpAkskSoTnfjxZDKVaAYwziNTC1pAYH5B9A1rh
	//Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA
	//
	//FA3oaS2D2GkrZJuWuiDohnLruxV3AWbrM3PmG3HSSE7DHzPWio36
	//Fs1os7xg2mN9fTuJmaYZLk6EXz51x2wmmHr2365UAuPMJW3aNr25
	//
	//EC2CyGKaNddLFxrjkFgiaRZnk77b8iQia3Zj6h5fxFReAcDwCo3i
	//Es4KmwK65t9HCsibYzVDFrijvkgTFZKdEaEAgfMtYTPSVtM3NDSx
	//
	//EC2R4bPDj9WQ8eWA4X3K8NYfTkBh4HFvCopLBq48FyrNXNumSK6w
	//Es355qB6tWo1ZZRTK8cXpHjxGECXaPGw98AFCRJ6kxZ3J6vp1M2i

	_, _, err := ImportAddresses(
		"Fs2TCa7Mo4XGy9FQSoZS8JPnDfv7SjwUSGqrjMWvc1RJ9sKbJeXA",
		"Fs1os7xg2mN9fTuJmaYZLk6EXz51x2wmmHr2365UAuPMJW3aNr25",
		"Es4KmwK65t9HCsibYzVDFrijvkgTFZKdEaEAgfMtYTPSVtM3NDSx",
		"Es355qB6tWo1ZZRTK8cXpHjxGECXaPGw98AFCRJ6kxZ3J6vp1M2i",
	)
	if err != nil {
		return err
	}

	return nil
}

// StartTestWallet runs a test wallet and serves the wallet api. The caller
// must write an int to the chan when compleate to stop the wallet api and
// remove the test db.
func StartTestWallet() (chan int, error) {
	var (
		walletdbfile = os.TempDir() + "/testingwallet.bolt"
		txdbfile     = os.TempDir() + "/testingtxdb.bolt"
	)

	// make a chan to signal when the test is finished with the wallet
	done := make(chan int, 1)

	// setup a testing wallet
	fctWallet, err := wallet.NewOrOpenBoltDBWallet(walletdbfile)
	if err != nil {
		return nil, err
	}
	defer os.Remove(walletdbfile)

	txdb, err := wallet.NewTXBoltDB(txdbfile)
	if err != nil {
		return nil, err
	} else {
		fctWallet.AddTXDB(txdb)
	}
	defer os.Remove(txdbfile)

	RpcConfig = &RPCConfig{
		WalletTLSEnable:   false,
		WalletTLSKeyFile:  "",
		WalletTLSCertFile: "",
		WalletRPCUser:     "",
		WalletRPCPassword: "",
		WalletServer:      "localhost:8089",
	}

	go wsapi.Start(fctWallet, ":8089", *RpcConfig)
	go func() {
		<-done
		wsapi.Stop()
		fctWallet.Close()
		txdb.Close()
	}()

	return done, nil
}

<|endoftext|>


<commit_before>// Package intern implements fast, immutable string interning.
//
// The package is a cgo binding for libintern:
//
//	https://github.com/chriso/intern
//
// Interning is a way of storing distinct strings only once in memory:
//
//	https://en.wikipedia.org/wiki/String_interning
//
// Each string is assigned an ID of type uint32. IDs start at 1 and
// increment towards 2^32-1:
//
//	repository := intern.NewRepository()
//
// 	id := repository.intern("foo")
// 	fmt.Println(id) // => 1
//
// 	id := repository.intern("bar")
// 	fmt.Println(id) // => 2
//
// 	id := repository.intern("foo")
// 	fmt.Println(id) // => 1
//
// 	id := repository.intern("qux")
// 	fmt.Println(id) // => 3
//
// Two-way lookup is provided:
//
//  if id, ok := repository.Lookup("foo"); ok {
//    fmt.Printf("string 'foo' has ID: %v", id)
//  }
//
//  if str, ok := repository.LookupID(1); ok {
//    fmt.Printf("string with ID 1: %v", str)
//  }
//
// The package also provides a way to iterate unique strings in order
// of ID, optimize string repositories using frequency analysis, and
// restore string repositories to a previous snapshot.
//
// This package is *NOT* safe to use from multiple goroutines without
// locking, e.g. https://golang.org/pkg/sync/#Mutex
package intern

// #include <intern/strings.h>
// #include <intern/optimize.h>
// #cgo LDFLAGS: -lintern
import "C"

import (
	"fmt"
	"runtime"
)

// ErrInvalidSnapshot is returned by Repository.Restore when the
// repository and snapshot are incompatible
var ErrInvalidSnapshot = fmt.Errorf("invalid snapshot")

// Repository stores a collection of unique strings
type Repository struct {
	ptr *C.struct_strings
}

// NewRepository creates a new string repository
func NewRepository() *Repository {
	ptr := C.strings_new()
	return newRepositoryFromPtr(ptr)
}

func newRepositoryFromPtr(ptr *C.struct_strings) *Repository {
	if ptr == nil {
		outOfMemory()
	}
	repo := &Repository{ptr}
	runtime.SetFinalizer(repo, (*Repository).free)
	return repo
}

func outOfMemory() {
	panic("out of memory")
}

func (repo *Repository) free() {
	C.strings_free(repo.ptr)
}

// Count returns the total number of unique strings in the repository
func (repo *Repository) Count() uint32 {
	return uint32(C.strings_count(repo.ptr))
}

// Intern interns a string and returns its unique ID. Note that IDs increment
// from 1. This function will panic if the string does not fit in one page -
// len(string) < repo.PageSize() - or if the uint32 IDs overflow. It is the
// caller's responsibility to check that these constraints are met
func (repo *Repository) Intern(str string) uint32 {
	id := uint32(C.strings_intern(repo.ptr, C.CString(str)))
	if id == 0 {
		outOfMemory()
	}
	return id
}

// Lookup returns the ID associated with a string, or false if the ID
// does not exist in the repository
func (repo *Repository) Lookup(str string) (uint32, bool) {
	id := uint32(C.strings_lookup(repo.ptr, C.CString(str)))
	return id, id != 0
}

// LookupID returns the string associated with an ID, or false if the string
// does not exist in the repository
func (repo *Repository) LookupID(id uint32) (string, bool) {
	str := C.strings_lookup_id(repo.ptr, C.uint32_t(id))
	if str == nil {
		return "", false
	}
	return C.GoString(str), true
}

// AllocatedBytes returns the total number of bytes allocated by the string
// repository
func (repo *Repository) AllocatedBytes() uint64 {
	return uint64(C.strings_allocated_bytes(repo.ptr))
}

// Cursor creates a new cursor for iterating strings
func (repo *Repository) Cursor() *Cursor {
	cursor := _Ctype_struct_strings_cursor{}
	C.strings_cursor_init(&cursor, repo.ptr)
	return &Cursor{repo, &cursor}
}

// Optimize creates a new, optimized string repository which stores the most
// frequently seen strings together. The string with the lowest ID (1) is the
// most frequently seen string
func (repo *Repository) Optimize(freq *Frequency) *Repository {
	ptr := C.strings_optimize(repo.ptr, freq.ptr)
	return newRepositoryFromPtr(ptr)
}

// Snapshot creates a new snapshot of the repository. It can later be
// restored to this position
func (repo *Repository) Snapshot() *Snapshot {
	snapshot := _Ctype_struct_strings_snapshot{}
	C.strings_snapshot(repo.ptr, &snapshot)
	return &Snapshot{repo, &snapshot}
}

// Restore restores the string repository to a previous snapshot
func (repo *Repository) Restore(snapshot *Snapshot) error {
	if ok := C.strings_restore(repo.ptr, snapshot.ptr); !ok {
		return ErrInvalidSnapshot
	}
	return nil
}

// PageSize returns the compile-time page size setting
func (repo *Repository) PageSize() uint64 {
	return uint64(C.strings_page_size())
}

// Snapshot is a snapshot of a string repository
type Snapshot struct {
	repo *Repository
	ptr  *C.struct_strings_snapshot
}

// Cursor is used to iterate strings in a repository
type Cursor struct {
	repo *Repository
	ptr  *C.struct_strings_cursor
}

// ID returns the ID that the cursor currently points to
func (cursor *Cursor) ID() uint32 {
	return uint32(C.strings_cursor_id(cursor.ptr))
}

// String returns the string that the cursor currently points to
func (cursor *Cursor) String() string {
	str := C.strings_cursor_string(cursor.ptr)
	if str == nil {
		return ""
	}
	return C.GoString(str)
}

// Next advances the cursor. It returns true if there is another
// string, and false otherwise
func (cursor *Cursor) Next() bool {
	return bool(C.strings_cursor_next(cursor.ptr))
}

// Frequency is used to track string frequencies
type Frequency struct {
	ptr *C.struct_strings_frequency
}

// NewFrequency creates a new string frequency tracker
func NewFrequency() *Frequency {
	ptr := C.strings_frequency_new()
	if ptr == nil {
		outOfMemory()
	}
	freq := &Frequency{ptr}
	runtime.SetFinalizer(freq, (*Frequency).free)
	return freq
}

func (freq *Frequency) free() {
	C.strings_frequency_free(freq.ptr)
}

// Add adds a string ID. This should be called after interning a string and
// getting back the ID
func (freq *Frequency) Add(id uint32) {
	if ok := C.strings_frequency_add(freq.ptr, C.uint32_t(id)); !ok {
		outOfMemory()
	}
}

// AddAll adds all string IDs, to ensure that each string is present in the
// optimized repository
func (freq *Frequency) AddAll(repo *Repository) {
	if ok := C.strings_frequency_add_all(freq.ptr, repo.ptr); !ok {
		outOfMemory()
	}
}
<commit_msg>Use a random hash seed<commit_after>// Package intern implements fast, immutable string interning.
//
// The package is a cgo binding for libintern:
//
//	https://github.com/chriso/intern
//
// Interning is a way of storing distinct strings only once in memory:
//
//	https://en.wikipedia.org/wiki/String_interning
//
// Each string is assigned an ID of type uint32. IDs start at 1 and
// increment towards 2^32-1:
//
//	repository := intern.NewRepository()
//
// 	id := repository.intern("foo")
// 	fmt.Println(id) // => 1
//
// 	id := repository.intern("bar")
// 	fmt.Println(id) // => 2
//
// 	id := repository.intern("foo")
// 	fmt.Println(id) // => 1
//
// 	id := repository.intern("qux")
// 	fmt.Println(id) // => 3
//
// Two-way lookup is provided:
//
//  if id, ok := repository.Lookup("foo"); ok {
//    fmt.Printf("string 'foo' has ID: %v", id)
//  }
//
//  if str, ok := repository.LookupID(1); ok {
//    fmt.Printf("string with ID 1: %v", str)
//  }
//
// The package also provides a way to iterate unique strings in order
// of ID, optimize string repositories using frequency analysis, and
// restore string repositories to a previous snapshot.
//
// This package is *NOT* safe to use from multiple goroutines without
// locking, e.g. https://golang.org/pkg/sync/#Mutex
package intern

// #include <intern/strings.h>
// #include <intern/optimize.h>
// #cgo LDFLAGS: -lintern
import "C"

import (
	"fmt"
	"math/rand"
	"runtime"
)

// ErrInvalidSnapshot is returned by Repository.Restore when the
// repository and snapshot are incompatible
var ErrInvalidSnapshot = fmt.Errorf("invalid snapshot")

// Repository stores a collection of unique strings
type Repository struct {
	ptr *C.struct_strings
}

// NewRepository creates a new string repository
func NewRepository() *Repository {
	ptr := C.strings_new()
	return newRepositoryFromPtr(ptr)
}

func newRepositoryFromPtr(ptr *C.struct_strings) *Repository {
	if ptr == nil {
		outOfMemory()
	}
	hashSeed := rand.Uint32()
	C.strings_hash_seed(ptr, C.uint32_t(hashSeed))
	repo := &Repository{ptr}
	runtime.SetFinalizer(repo, (*Repository).free)
	return repo
}

func outOfMemory() {
	panic("out of memory")
}

func (repo *Repository) free() {
	C.strings_free(repo.ptr)
}

// Count returns the total number of unique strings in the repository
func (repo *Repository) Count() uint32 {
	return uint32(C.strings_count(repo.ptr))
}

// Intern interns a string and returns its unique ID. Note that IDs increment
// from 1. This function will panic if the string does not fit in one page -
// len(string) < repo.PageSize() - or if the uint32 IDs overflow. It is the
// caller's responsibility to check that these constraints are met
func (repo *Repository) Intern(str string) uint32 {
	id := uint32(C.strings_intern(repo.ptr, C.CString(str)))
	if id == 0 {
		outOfMemory()
	}
	return id
}

// Lookup returns the ID associated with a string, or false if the ID
// does not exist in the repository
func (repo *Repository) Lookup(str string) (uint32, bool) {
	id := uint32(C.strings_lookup(repo.ptr, C.CString(str)))
	return id, id != 0
}

// LookupID returns the string associated with an ID, or false if the string
// does not exist in the repository
func (repo *Repository) LookupID(id uint32) (string, bool) {
	str := C.strings_lookup_id(repo.ptr, C.uint32_t(id))
	if str == nil {
		return "", false
	}
	return C.GoString(str), true
}

// AllocatedBytes returns the total number of bytes allocated by the string
// repository
func (repo *Repository) AllocatedBytes() uint64 {
	return uint64(C.strings_allocated_bytes(repo.ptr))
}

// Cursor creates a new cursor for iterating strings
func (repo *Repository) Cursor() *Cursor {
	cursor := _Ctype_struct_strings_cursor{}
	C.strings_cursor_init(&cursor, repo.ptr)
	return &Cursor{repo, &cursor}
}

// Optimize creates a new, optimized string repository which stores the most
// frequently seen strings together. The string with the lowest ID (1) is the
// most frequently seen string
func (repo *Repository) Optimize(freq *Frequency) *Repository {
	ptr := C.strings_optimize(repo.ptr, freq.ptr)
	return newRepositoryFromPtr(ptr)
}

// Snapshot creates a new snapshot of the repository. It can later be
// restored to this position
func (repo *Repository) Snapshot() *Snapshot {
	snapshot := _Ctype_struct_strings_snapshot{}
	C.strings_snapshot(repo.ptr, &snapshot)
	return &Snapshot{repo, &snapshot}
}

// Restore restores the string repository to a previous snapshot
func (repo *Repository) Restore(snapshot *Snapshot) error {
	if ok := C.strings_restore(repo.ptr, snapshot.ptr); !ok {
		return ErrInvalidSnapshot
	}
	return nil
}

// PageSize returns the compile-time page size setting
func (repo *Repository) PageSize() uint64 {
	return uint64(C.strings_page_size())
}

// Snapshot is a snapshot of a string repository
type Snapshot struct {
	repo *Repository
	ptr  *C.struct_strings_snapshot
}

// Cursor is used to iterate strings in a repository
type Cursor struct {
	repo *Repository
	ptr  *C.struct_strings_cursor
}

// ID returns the ID that the cursor currently points to
func (cursor *Cursor) ID() uint32 {
	return uint32(C.strings_cursor_id(cursor.ptr))
}

// String returns the string that the cursor currently points to
func (cursor *Cursor) String() string {
	str := C.strings_cursor_string(cursor.ptr)
	if str == nil {
		return ""
	}
	return C.GoString(str)
}

// Next advances the cursor. It returns true if there is another
// string, and false otherwise
func (cursor *Cursor) Next() bool {
	return bool(C.strings_cursor_next(cursor.ptr))
}

// Frequency is used to track string frequencies
type Frequency struct {
	ptr *C.struct_strings_frequency
}

// NewFrequency creates a new string frequency tracker
func NewFrequency() *Frequency {
	ptr := C.strings_frequency_new()
	if ptr == nil {
		outOfMemory()
	}
	freq := &Frequency{ptr}
	runtime.SetFinalizer(freq, (*Frequency).free)
	return freq
}

func (freq *Frequency) free() {
	C.strings_frequency_free(freq.ptr)
}

// Add adds a string ID. This should be called after interning a string and
// getting back the ID
func (freq *Frequency) Add(id uint32) {
	if ok := C.strings_frequency_add(freq.ptr, C.uint32_t(id)); !ok {
		outOfMemory()
	}
}

// AddAll adds all string IDs, to ensure that each string is present in the
// optimized repository
func (freq *Frequency) AddAll(repo *Repository) {
	if ok := C.strings_frequency_add_all(freq.ptr, repo.ptr); !ok {
		outOfMemory()
	}
}
<|endoftext|>


<commit_before>// Package ioconn allows any combination of an io.Reader, io.Writer and io.Closer to become a net.Conn
package ioconn

import (
	"errors"
	"io"
	"net"
	"time"
)

// CloserFunc is a func that implements the io.Closer interface allowing a
// closure or other function to be io.Closer
type CloserFunc func() error

// Close simply calls the CloserFunc func
func (c CloserFunc) Close() error {
	return c()
}

// FileAddr is a net.Addr that represents a file. Should be a full path
type FileAddr string

// Network always returns "file"
func (f FileAddr) Network() string {
	return "file"
}

// String returns file://path
func (f FileAddr) String() string {
	return "file://" + string(f)
}

// Addr is a simple implementation of the net.Addr interface
type Addr struct {
	Net, Str string
}

// Network returns the Net string
func (a Addr) Network() string {
	return a.Net
}

// String returns the Str string
func (a Addr) String() string {
	return a.Str
}

// Conn implements a net.Conn
type Conn struct {
	io.Reader
	io.Writer
	io.Closer
	Local, Remote               net.Addr
	ReadDeadline, WriteDeadline time.Time
}

// Read implements the io.Reader interface
func (c *Conn) Read(p []byte) (int, error) {
	if !c.ReadDeadline.IsZero() && time.Now().After(c.ReadDeadline) {
		return 0, ErrTimeout
	}
	return c.Reader.Read(p)
}

// Write implements the io.Writer interface
func (c *Conn) Write(p []byte) (int, error) {
	if !c.ReadDeadline.IsZero() && time.Now().After(c.WriteDeadline) {
		return 0, ErrTimeout
	}
	return c.Writer.Write(p)
}

// LocalAddr returns the Local Address
func (c *Conn) LocalAddr() net.Addr {
	return c.Local
}

// RemoteAddr returns the Remote Address
func (c *Conn) RemoteAddr() net.Addr {
	return c.Remote
}

// SetDeadline implements the Conn SetDeadline method
func (c *Conn) SetDeadline(t time.Time) error {
	err := c.SetReadDeadline(t)
	err2 := c.SetWriteDeadline(t)
	if err != nil {
		return err
	}
	return err2
}

// SetReadDeadline implements the Conn SetReadDeadline method
func (c *Conn) SetReadDeadline(t time.Time) error {
	c.ReadDeadline = t
	if rd, ok := c.Writer.(interface {
		SetReadDeadline(time.Time) error
	}); ok {
		return rd.SetReadDeadline(t)
	}
	return nil
}

// SetWriteDeadline implements the Conn SetWriteDeadline method
func (c *Conn) SetWriteDeadline(t time.Time) error {
	c.WriteDeadline = t
	if wd, ok := c.Writer.(interface {
		SetWriteDeadline(time.Time) error
	}); ok {
		return wd.SetWriteDeadline(t)
	}
	return nil
}

// Errors
var (
	ErrTimeout = errors.New("timeout occurred")
)
<commit_msg>updated to vanity urls<commit_after>// Package ioconn allows any combination of an io.Reader, io.Writer and io.Closer to become a net.Conn
package ioconn // import "vimagination.zapto.org/ioconn"

import (
	"errors"
	"io"
	"net"
	"time"
)

// CloserFunc is a func that implements the io.Closer interface allowing a
// closure or other function to be io.Closer
type CloserFunc func() error

// Close simply calls the CloserFunc func
func (c CloserFunc) Close() error {
	return c()
}

// FileAddr is a net.Addr that represents a file. Should be a full path
type FileAddr string

// Network always returns "file"
func (f FileAddr) Network() string {
	return "file"
}

// String returns file://path
func (f FileAddr) String() string {
	return "file://" + string(f)
}

// Addr is a simple implementation of the net.Addr interface
type Addr struct {
	Net, Str string
}

// Network returns the Net string
func (a Addr) Network() string {
	return a.Net
}

// String returns the Str string
func (a Addr) String() string {
	return a.Str
}

// Conn implements a net.Conn
type Conn struct {
	io.Reader
	io.Writer
	io.Closer
	Local, Remote               net.Addr
	ReadDeadline, WriteDeadline time.Time
}

// Read implements the io.Reader interface
func (c *Conn) Read(p []byte) (int, error) {
	if !c.ReadDeadline.IsZero() && time.Now().After(c.ReadDeadline) {
		return 0, ErrTimeout
	}
	return c.Reader.Read(p)
}

// Write implements the io.Writer interface
func (c *Conn) Write(p []byte) (int, error) {
	if !c.ReadDeadline.IsZero() && time.Now().After(c.WriteDeadline) {
		return 0, ErrTimeout
	}
	return c.Writer.Write(p)
}

// LocalAddr returns the Local Address
func (c *Conn) LocalAddr() net.Addr {
	return c.Local
}

// RemoteAddr returns the Remote Address
func (c *Conn) RemoteAddr() net.Addr {
	return c.Remote
}

// SetDeadline implements the Conn SetDeadline method
func (c *Conn) SetDeadline(t time.Time) error {
	err := c.SetReadDeadline(t)
	err2 := c.SetWriteDeadline(t)
	if err != nil {
		return err
	}
	return err2
}

// SetReadDeadline implements the Conn SetReadDeadline method
func (c *Conn) SetReadDeadline(t time.Time) error {
	c.ReadDeadline = t
	if rd, ok := c.Writer.(interface {
		SetReadDeadline(time.Time) error
	}); ok {
		return rd.SetReadDeadline(t)
	}
	return nil
}

// SetWriteDeadline implements the Conn SetWriteDeadline method
func (c *Conn) SetWriteDeadline(t time.Time) error {
	c.WriteDeadline = t
	if wd, ok := c.Writer.(interface {
		SetWriteDeadline(time.Time) error
	}); ok {
		return wd.SetWriteDeadline(t)
	}
	return nil
}

// Errors
var (
	ErrTimeout = errors.New("timeout occurred")
)
<|endoftext|>


<commit_before>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload the provided template.
// Reloading templates on each request is useful to see changes without
// recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// Path to template that is used as root template when
// Page.Serve[Empty|NotFound|Unauthorized|WithError] is called.
var RootTemplatePath = "./templates/index.html"

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    = MustNewTemplate("", nil)
	TemplateNotFound = MustNewTemplate("./templates/404-not-found.html", nil)
)

// Template that is used as content template when Page.Error is called.
var TemplateError = MustNewTemplateWithRoot("./templates/error.html", "./templates/500-internal-server-error.html", nil)

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	if ReloadTemplates {
		if err := tpl.Reload(); err != nil {
			return nil, err
		}
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

func (p *Page) Redirect(urlStr string, code int) {
	http.Redirect(p.responseWriter, p.request, urlStr, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: TemplateError is nil.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: p.Template is nil."))
		return
	}

	if err := p.Template.template.ExecuteTemplate(buffer, path.Base(p.Template.rootTemplatePath), p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<commit_msg>Page.ServeNotFound sets appropriate page title.<commit_after>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload the provided template.
// Reloading templates on each request is useful to see changes without
// recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// Path to template that is used as root template when
// Page.Serve[Empty|NotFound|Unauthorized|WithError] is called.
var RootTemplatePath = "./templates/index.html"

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    = MustNewTemplate("", nil)
	TemplateNotFound = MustNewTemplate("./templates/404-not-found.html", nil)
)

// Template that is used as content template when Page.Error is called.
var TemplateError = MustNewTemplateWithRoot("./templates/error.html", "./templates/500-internal-server-error.html", nil)

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	if ReloadTemplates {
		if err := tpl.Reload(); err != nil {
			return nil, err
		}
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

func (p *Page) Redirect(urlStr string, code int) {
	http.Redirect(p.responseWriter, p.request, urlStr, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: TemplateError is nil.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: p.Template is nil."))
		return
	}

	if err := p.Template.template.ExecuteTemplate(buffer, path.Base(p.Template.rootTemplatePath), p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_page_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"time"

	jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/kubernetes/pkg/api"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/pkg/transport"

	// install all APIs
	_ "github.com/openshift/origin/pkg/api/install"
	_ "github.com/openshift/origin/pkg/quota/apis/quota/install"
	_ "k8s.io/kubernetes/pkg/api/install"
)

func main() {
	var endpoint, keyFile, certFile, caFile string
	flag.StringVar(&endpoint, "endpoint", "https://127.0.0.1:4001", "Etcd endpoint.")
	flag.StringVar(&keyFile, "key", "", "TLS client key.")
	flag.StringVar(&certFile, "cert", "", "TLS client certificate.")
	flag.StringVar(&caFile, "cacert", "", "Server TLS CA certificate.")
	flag.Parse()

	if flag.NArg() == 0 {
		fmt.Fprint(os.Stderr, "ERROR: you need to specify action: dump or ls [<key>] or get <key>\n")
		os.Exit(1)
	}
	if flag.Arg(0) == "get" && flag.NArg() == 1 {
		fmt.Fprint(os.Stderr, "ERROR: you need to specify <key> for get operation\n")
		os.Exit(1)
	}
	if flag.Arg(0) == "dump" && flag.NArg() != 1 {
		fmt.Fprint(os.Stderr, "ERROR: you cannot specify positional arguments with dump\n")
		os.Exit(1)
	}
	action := flag.Arg(0)
	key := ""
	if flag.NArg() > 1 {
		key = flag.Arg(1)
	}

	var tlsConfig *tls.Config
	if len(certFile) != 0 || len(keyFile) != 0 || len(caFile) != 0 {
		tlsInfo := transport.TLSInfo{
			CertFile: certFile,
			KeyFile:  keyFile,
			CAFile:   caFile,
		}
		var err error
		tlsConfig, err = tlsInfo.ClientConfig()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: unable to create client config: %v\n", err)
			os.Exit(1)
		}
	}

	config := clientv3.Config{
		Endpoints:   []string{endpoint},
		TLS:         tlsConfig,
		DialTimeout: 5 * time.Second,
	}
	client, err := clientv3.New(config)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: unable to connect to etcd: %v\n", err)
		os.Exit(1)
	}
	defer client.Close()

	switch action {
	case "ls":
		err = listKeys(client, key)
	case "get":
		err = getKey(client, key)
	case "dump":
		err = dump(client)
	default:
		fmt.Fprintf(os.Stderr, "ERROR: invalid action: %s\n", action)
		os.Exit(1)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s-ing %s: %v\n", action, key, err)
		os.Exit(1)
	}
}

func listKeys(client *clientv3.Client, key string) error {
	var resp *clientv3.GetResponse
	var err error
	if len(key) == 0 {
		resp, err = clientv3.NewKV(client).Get(context.Background(), "/", clientv3.WithFromKey(), clientv3.WithKeysOnly())
	} else {
		resp, err = clientv3.NewKV(client).Get(context.Background(), key, clientv3.WithPrefix(), clientv3.WithKeysOnly())
	}
	if err != nil {
		return err
	}

	for _, kv := range resp.Kvs {
		fmt.Println(string(kv.Key))
	}

	return nil
}

func getKey(client *clientv3.Client, key string) error {
	resp, err := clientv3.NewKV(client).Get(context.Background(), key)
	if err != nil {
		return err
	}

	decoder := api.Codecs.UniversalDeserializer()
	encoder := jsonserializer.NewSerializer(jsonserializer.DefaultMetaFactory, api.Scheme, api.Scheme, true)

	for _, kv := range resp.Kvs {
		obj, gvk, err := decoder.Decode(kv.Value, nil, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: unable to decode %s: %v\n", kv.Key, err)
			continue
		}
		fmt.Println(gvk)
		err = encoder.Encode(obj, os.Stdout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: unable to decode %s: %v\n", kv.Key, err)
			continue
		}
	}

	return nil
}

func dump(client *clientv3.Client) error {
	response, err := clientv3.NewKV(client).Get(context.Background(), "/", clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend))
	if err != nil {
		return err
	}

	kvData := []etcd3kv{}
	decoder := api.Codecs.UniversalDeserializer()
	encoder := jsonserializer.NewSerializer(jsonserializer.DefaultMetaFactory, api.Scheme, api.Scheme, false)
	objJSON := &bytes.Buffer{}

	for _, kv := range response.Kvs {
		obj, _, err := decoder.Decode(kv.Value, nil, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: error decoding value %s: %v\n", string(kv.Value), err)
			continue
		}
		objJSON.Reset()
		if err := encoder.Encode(obj, objJSON); err != nil {
			fmt.Fprintf(os.Stderr, "WARN: error encoding object %#v as JSON: %v", obj, err)
			continue
		}
		kvData = append(
			kvData,
			etcd3kv{
				Key:            string(kv.Key),
				Value:          string(objJSON.Bytes()),
				CreateRevision: kv.CreateRevision,
				ModRevision:    kv.ModRevision,
				Version:        kv.Version,
				Lease:          kv.Lease,
			},
		)
	}

	jsonData, err := json.MarshalIndent(kvData, "", "  ")
	if err != nil {
		return err
	}

	fmt.Println(string(jsonData))

	return nil
}

type etcd3kv struct {
	Key            string `json:"key,omitempty"`
	Value          string `json:"value,omitempty"`
	CreateRevision int64  `json:"create_revision,omitempty"`
	ModRevision    int64  `json:"mod_revision,omitempty"`
	Version        int64  `json:"version,omitempty"`
	Lease          int64  `json:"lease,omitempty"`
}
<commit_msg>Register APIService for apiregistration.k8s.io/v1beta1<commit_after>package main

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"time"

	jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/kubernetes/pkg/api"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/pkg/transport"

	// install all APIs
	_ "github.com/openshift/origin/pkg/api/install"
	_ "github.com/openshift/origin/pkg/quota/apis/quota/install"
	apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration/install"
	_ "k8s.io/kubernetes/pkg/api/install"
)

func init() {
	apiregistration.Install(api.GroupFactoryRegistry, api.Registry, api.Scheme)
}

func main() {
	var endpoint, keyFile, certFile, caFile string
	flag.StringVar(&endpoint, "endpoint", "https://127.0.0.1:4001", "Etcd endpoint.")
	flag.StringVar(&keyFile, "key", "", "TLS client key.")
	flag.StringVar(&certFile, "cert", "", "TLS client certificate.")
	flag.StringVar(&caFile, "cacert", "", "Server TLS CA certificate.")
	flag.Parse()

	if flag.NArg() == 0 {
		fmt.Fprint(os.Stderr, "ERROR: you need to specify action: dump or ls [<key>] or get <key>\n")
		os.Exit(1)
	}
	if flag.Arg(0) == "get" && flag.NArg() == 1 {
		fmt.Fprint(os.Stderr, "ERROR: you need to specify <key> for get operation\n")
		os.Exit(1)
	}
	if flag.Arg(0) == "dump" && flag.NArg() != 1 {
		fmt.Fprint(os.Stderr, "ERROR: you cannot specify positional arguments with dump\n")
		os.Exit(1)
	}
	action := flag.Arg(0)
	key := ""
	if flag.NArg() > 1 {
		key = flag.Arg(1)
	}

	var tlsConfig *tls.Config
	if len(certFile) != 0 || len(keyFile) != 0 || len(caFile) != 0 {
		tlsInfo := transport.TLSInfo{
			CertFile: certFile,
			KeyFile:  keyFile,
			CAFile:   caFile,
		}
		var err error
		tlsConfig, err = tlsInfo.ClientConfig()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: unable to create client config: %v\n", err)
			os.Exit(1)
		}
	}

	config := clientv3.Config{
		Endpoints:   []string{endpoint},
		TLS:         tlsConfig,
		DialTimeout: 5 * time.Second,
	}
	client, err := clientv3.New(config)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: unable to connect to etcd: %v\n", err)
		os.Exit(1)
	}
	defer client.Close()

	switch action {
	case "ls":
		err = listKeys(client, key)
	case "get":
		err = getKey(client, key)
	case "dump":
		err = dump(client)
	default:
		fmt.Fprintf(os.Stderr, "ERROR: invalid action: %s\n", action)
		os.Exit(1)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s-ing %s: %v\n", action, key, err)
		os.Exit(1)
	}
}

func listKeys(client *clientv3.Client, key string) error {
	var resp *clientv3.GetResponse
	var err error
	if len(key) == 0 {
		resp, err = clientv3.NewKV(client).Get(context.Background(), "/", clientv3.WithFromKey(), clientv3.WithKeysOnly())
	} else {
		resp, err = clientv3.NewKV(client).Get(context.Background(), key, clientv3.WithPrefix(), clientv3.WithKeysOnly())
	}
	if err != nil {
		return err
	}

	for _, kv := range resp.Kvs {
		fmt.Println(string(kv.Key))
	}

	return nil
}

func getKey(client *clientv3.Client, key string) error {
	resp, err := clientv3.NewKV(client).Get(context.Background(), key)
	if err != nil {
		return err
	}

	decoder := api.Codecs.UniversalDeserializer()
	encoder := jsonserializer.NewSerializer(jsonserializer.DefaultMetaFactory, api.Scheme, api.Scheme, true)

	for _, kv := range resp.Kvs {
		obj, gvk, err := decoder.Decode(kv.Value, nil, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: unable to decode %s: %v\n", kv.Key, err)
			continue
		}
		fmt.Println(gvk)
		err = encoder.Encode(obj, os.Stdout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: unable to decode %s: %v\n", kv.Key, err)
			continue
		}
	}

	return nil
}

func dump(client *clientv3.Client) error {
	response, err := clientv3.NewKV(client).Get(context.Background(), "/", clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortDescend))
	if err != nil {
		return err
	}

	kvData := []etcd3kv{}
	decoder := api.Codecs.UniversalDeserializer()
	encoder := jsonserializer.NewSerializer(jsonserializer.DefaultMetaFactory, api.Scheme, api.Scheme, false)
	objJSON := &bytes.Buffer{}

	for _, kv := range response.Kvs {
		obj, _, err := decoder.Decode(kv.Value, nil, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "WARN: error decoding value %q: %v\n", string(kv.Value), err)
			continue
		}
		objJSON.Reset()
		if err := encoder.Encode(obj, objJSON); err != nil {
			fmt.Fprintf(os.Stderr, "WARN: error encoding object %#v as JSON: %v", obj, err)
			continue
		}
		kvData = append(
			kvData,
			etcd3kv{
				Key:            string(kv.Key),
				Value:          string(objJSON.Bytes()),
				CreateRevision: kv.CreateRevision,
				ModRevision:    kv.ModRevision,
				Version:        kv.Version,
				Lease:          kv.Lease,
			},
		)
	}

	jsonData, err := json.MarshalIndent(kvData, "", "  ")
	if err != nil {
		return err
	}

	fmt.Println(string(jsonData))

	return nil
}

type etcd3kv struct {
	Key            string `json:"key,omitempty"`
	Value          string `json:"value,omitempty"`
	CreateRevision int64  `json:"create_revision,omitempty"`
	ModRevision    int64  `json:"mod_revision,omitempty"`
	Version        int64  `json:"version,omitempty"`
	Lease          int64  `json:"lease,omitempty"`
}
<|endoftext|>


<commit_before>package pane

import (
	"github.com/chrisseto/sux/pansi"
	"github.com/nsf/termbox-go"
	"log"
)

func (p *Pane) handleEscapeCode(c *pansi.AnsiEscapeCode) {
	switch c.Type {
	case pansi.SetGraphicMode:
		p.SetGraphicMode(c.Values)
	case pansi.CursorPosition:
		if len(c.Values) == 0 {
			p.cx, p.cy = 0, 0
		} else {
			p.cx, p.cy = c.Values[1]-1, c.Values[0]-1
		}
	case pansi.CursorUp:
		p.cy--
	case pansi.CursorDown:
		p.cy++
	case pansi.CursorBackward:
		p.cx--
	case pansi.CursorForward:
		p.cx++
	case pansi.VPA:
		if len(c.Values) == 0 {
			p.cy = 0
		} else {
			p.cy = c.Values[0] - 1
		}
	case pansi.EraseLine:
		row := p.screen.Row(p.cy)
		for i := p.cx; i < len(*row); i++ {
			(*row)[i] = termbox.Cell{' ', p.fg, p.bg}
		}
	case pansi.EraseDisplay:
		p.Clear()
	default:
		log.Printf("Doing nothing with %+v\n", *c)
	}
}

func (p *Pane) SetGraphicMode(vals []int) {
	if len(vals) == 0 {
		p.fg, p.bg = 8, 1
		return
	}
	for i := 0; i < len(vals); i++ {
		switch vals[i] {
		case 0:
			p.fg, p.bg = 8, 1
		case 1:
			p.fg |= termbox.AttrBold
		case 7:
			p.fg, p.bg = p.bg, p.fg
		case 38:
			i++
			switch vals[i] {
			case 5:
				i++
				p.fg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 39:
			p.fg = termbox.ColorWhite
		case 48:
			i++
			switch vals[i] {
			case 5:
				i++
				p.bg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 49:
			p.bg = termbox.ColorBlack
		}
	}
}
<commit_msg>Handle DeleteLine and ReverseIndex escape codes<commit_after>package pane

import (
	"github.com/chrisseto/sux/pansi"
	"github.com/nsf/termbox-go"
	"log"
)

func (p *Pane) handleEscapeCode(c *pansi.AnsiEscapeCode) {
	switch c.Type {
	case pansi.SetGraphicMode:
		p.SetGraphicMode(c.Values)
	case pansi.CursorPosition:
		if len(c.Values) == 0 {
			p.cx, p.cy = 0, 0
		} else {
			p.cx, p.cy = c.Values[1]-1, c.Values[0]-1
		}
	case pansi.CursorUp:
		p.cy--
	case pansi.CursorDown:
		p.cy++
	case pansi.CursorBackward:
		p.cx--
	case pansi.CursorForward:
		p.cx++
	case pansi.VPA:
		if len(c.Values) == 0 {
			p.cy = 0
		} else {
			p.cy = c.Values[0] - 1
		}
	case pansi.EraseLine:
		row := p.screen.Row(p.cy)
		for i := p.cx; i < len(*row); i++ {
			(*row)[i] = termbox.Cell{' ', p.fg, p.bg}
		}
	case pansi.EraseDisplay:
		p.Clear()
	case pansi.DeleteLine:
		var val int
		if len(c.Values) == 0 {
			val = 1
		} else {
			val = c.Values[0]
		}
		p.screen.DeleteRows(p.cy, val)
		p.screen.AppendRows(val)
	case pansi.ReverseIndex:
		if p.cy > 0 {
			p.cy--
		} else {
			p.screen.Scroll(-1)
		}
	default:
		log.Printf("Doing nothing with %+v\n", *c)
	}
}

func (p *Pane) SetGraphicMode(vals []int) {
	if len(vals) == 0 {
		p.fg, p.bg = 8, 1
		return
	}
	for i := 0; i < len(vals); i++ {
		switch vals[i] {
		case 0:
			p.fg, p.bg = 8, 1
		case 1:
			p.fg |= termbox.AttrBold
		case 7:
			p.fg, p.bg = p.bg, p.fg
		case 38:
			i++
			switch vals[i] {
			case 5:
				i++
				p.fg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 39:
			p.fg = termbox.ColorWhite
		case 48:
			i++
			switch vals[i] {
			case 5:
				i++
				p.bg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 49:
			p.bg = termbox.ColorBlack
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package windows

import (
	"fmt"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

const (
	linuxOS   = "linux"
	windowsOS = "windows"
)

var (
	windowsBusyBoximage = imageutils.GetE2EImage(imageutils.Agnhost)
	linuxBusyBoxImage   = imageutils.GetE2EImage(imageutils.Nginx)
)

var _ = SIGDescribe("Hybrid cluster network", func() {
	f := framework.NewDefaultFramework("hybrid-network")

	ginkgo.BeforeEach(func() {
		e2eskipper.SkipUnlessNodeOSDistroIs("windows")
	})

	ginkgo.Context("for all supported CNIs", func() {

		ginkgo.It("should have stable networking for Linux and Windows pods", func() {

			linuxPod := createTestPod(f, linuxBusyBoxImage, linuxOS)
			ginkgo.By("creating a linux pod and waiting for it to be running")
			linuxPod = f.PodClient().CreateSync(linuxPod)

			windowsPod := createTestPod(f, windowsBusyBoximage, windowsOS)

			windowsPod.Spec.Containers[0].Args = []string{"test-webserver"}
			ginkgo.By("creating a windows pod and waiting for it to be running")
			windowsPod = f.PodClient().CreateSync(windowsPod)

			ginkgo.By("verifying pod external connectivity to the internet")

			ginkgo.By("checking connectivity to 8.8.8.8 53 (google.com) from Linux")
			assertConsistentConnectivity(f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck("8.8.8.8", 53))

			ginkgo.By("checking connectivity to www.google.com from Windows")
			assertConsistentConnectivity(f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck("www.google.com"))

			ginkgo.By("verifying pod internal connectivity to the cluster dataplane")

			ginkgo.By("checking connectivity from Linux to Windows")
			assertConsistentConnectivity(f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck(windowsPod.Status.PodIP, 80))

			ginkgo.By("checking connectivity from Windows to Linux")
			assertConsistentConnectivity(f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck(linuxPod.Status.PodIP))

		})

	})
})

var (
	duration       = "10s"
	pollInterval   = "1s"
	timeoutSeconds = 10
)

func assertConsistentConnectivity(f *framework.Framework, podName string, os string, cmd []string) {
	connChecker := func() error {
		ginkgo.By(fmt.Sprintf("checking connectivity of %s-container in %s", os, podName))
		// TODO, we should be retrying this similar to what is done in DialFromNode, in the test/e2e/networking/networking.go tests
		stdout, stderr, err := f.ExecCommandInContainerWithFullOutput(podName, os+"-container", cmd...)
		if err != nil {
			framework.Logf("Encountered error while running command: %v.\nStdout: %s\nStderr: %s\nErr: %v", cmd, stdout, stderr, err)
		}
		return err
	}
	gomega.Eventually(connChecker, duration, pollInterval).ShouldNot(gomega.HaveOccurred())
	gomega.Consistently(connChecker, duration, pollInterval).ShouldNot(gomega.HaveOccurred())
}

func linuxCheck(address string, port int) []string {
	nc := fmt.Sprintf("nc -vz %s %v -w %v", address, port, timeoutSeconds)
	cmd := []string{"/bin/sh", "-c", nc}
	return cmd
}

func windowsCheck(address string) []string {
	curl := fmt.Sprintf("curl.exe %s --connect-timeout %v --fail", address, timeoutSeconds)
	cmd := []string{"cmd", "/c", curl}
	return cmd
}

func createTestPod(f *framework.Framework, image string, os string) *v1.Pod {
	containerName := fmt.Sprintf("%s-container", os)
	podName := "pod-" + string(uuid.NewUUID())
	pod := &v1.Pod{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Pod",
			APIVersion: "v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: podName,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  containerName,
					Image: image,
					Ports: []v1.ContainerPort{{ContainerPort: 80}},
				},
			},
			NodeSelector: map[string]string{
				"kubernetes.io/os": os,
			},
		},
	}
	if os == linuxOS {
		pod.Spec.Tolerations = []v1.Toleration{
			{
				Operator: v1.TolerationOpExists,
				Effect:   v1.TaintEffectNoSchedule,
			},
		}
	}
	return pod
}
<commit_msg>made independent test cases ginkgo.It for checking connectivity<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package windows

import (
	"fmt"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"

	imageutils "k8s.io/kubernetes/test/utils/image"

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

const (
	linuxOS   = "linux"
	windowsOS = "windows"
)

var (
	windowsBusyBoximage = imageutils.GetE2EImage(imageutils.Agnhost)
	linuxBusyBoxImage   = imageutils.GetE2EImage(imageutils.Nginx)
)

var _ = SIGDescribe("Hybrid cluster network", func() {
	f := framework.NewDefaultFramework("hybrid-network")

	ginkgo.BeforeEach(func() {
		e2eskipper.SkipUnlessNodeOSDistroIs("windows")
	})

	ginkgo.Context("for all supported CNIs", func() {

		ginkgo.It("should have stable networking for Linux and Windows pods", func() {

			linuxPod := createTestPod(f, linuxBusyBoxImage, linuxOS)
			ginkgo.By("creating a linux pod and waiting for it to be running")
			linuxPod = f.PodClient().CreateSync(linuxPod)

			windowsPod := createTestPod(f, windowsBusyBoximage, windowsOS)

			windowsPod.Spec.Containers[0].Args = []string{"test-webserver"}
			ginkgo.By("creating a windows pod and waiting for it to be running")
			windowsPod = f.PodClient().CreateSync(windowsPod)

			ginkgo.By("verifying pod internal connectivity to the cluster dataplane")

			ginkgo.By("checking connectivity from Linux to Windows")
			assertConsistentConnectivity(f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck(windowsPod.Status.PodIP, 80))

			ginkgo.By("checking connectivity from Windows to Linux")
			assertConsistentConnectivity(f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck(linuxPod.Status.PodIP))

		})

		ginkgo.It("should provide Internet connection for Linux containers using DNS [Feature:Networking-DNS]", func() {
			linuxPod := createTestPod(f, linuxBusyBoxImage, linuxOS)
			ginkgo.By("creating a linux pod and waiting for it to be running")
			linuxPod = f.PodClient().CreateSync(linuxPod)

			ginkgo.By("verifying pod external connectivity to the internet")

			ginkgo.By("checking connectivity to 8.8.8.8 53 (google.com) from Linux")
			assertConsistentConnectivity(f, linuxPod.ObjectMeta.Name, linuxOS, linuxCheck("8.8.8.8", 53))
		})

		ginkgo.It("should provide Internet connection for Windows containers using DNS [Feature:Networking-DNS]", func() {
			windowsPod := createTestPod(f, windowsBusyBoximage, windowsOS)
			ginkgo.By("creating a windows pod and waiting for it to be running")
			windowsPod = f.PodClient().CreateSync(windowsPod)

			ginkgo.By("verifying pod external connectivity to the internet")

			ginkgo.By("checking connectivity to 8.8.8.8 53 (google.com) from Windows")
			assertConsistentConnectivity(f, windowsPod.ObjectMeta.Name, windowsOS, windowsCheck("www.google.com"))
		})

	})
})

var (
	duration       = "10s"
	pollInterval   = "1s"
	timeoutSeconds = 10
)

func assertConsistentConnectivity(f *framework.Framework, podName string, os string, cmd []string) {
	connChecker := func() error {
		ginkgo.By(fmt.Sprintf("checking connectivity of %s-container in %s", os, podName))
		// TODO, we should be retrying this similar to what is done in DialFromNode, in the test/e2e/networking/networking.go tests
		stdout, stderr, err := f.ExecCommandInContainerWithFullOutput(podName, os+"-container", cmd...)
		if err != nil {
			framework.Logf("Encountered error while running command: %v.\nStdout: %s\nStderr: %s\nErr: %v", cmd, stdout, stderr, err)
		}
		return err
	}
	gomega.Eventually(connChecker, duration, pollInterval).ShouldNot(gomega.HaveOccurred())
	gomega.Consistently(connChecker, duration, pollInterval).ShouldNot(gomega.HaveOccurred())
}

func linuxCheck(address string, port int) []string {
	nc := fmt.Sprintf("nc -vz %s %v -w %v", address, port, timeoutSeconds)
	cmd := []string{"/bin/sh", "-c", nc}
	return cmd
}

func windowsCheck(address string) []string {
	curl := fmt.Sprintf("curl.exe %s --connect-timeout %v --fail", address, timeoutSeconds)
	cmd := []string{"cmd", "/c", curl}
	return cmd
}

func createTestPod(f *framework.Framework, image string, os string) *v1.Pod {
	containerName := fmt.Sprintf("%s-container", os)
	podName := "pod-" + string(uuid.NewUUID())
	pod := &v1.Pod{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Pod",
			APIVersion: "v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: podName,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  containerName,
					Image: image,
					Ports: []v1.ContainerPort{{ContainerPort: 80}},
				},
			},
			NodeSelector: map[string]string{
				"kubernetes.io/os": os,
			},
		},
	}
	if os == linuxOS {
		pod.Spec.Tolerations = []v1.Toleration{
			{
				Operator: v1.TolerationOpExists,
				Effect:   v1.TaintEffectNoSchedule,
			},
		}
	}
	return pod
}
<|endoftext|>


<commit_before>package operators

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"
)

var _ = g.Describe("[Feature:Platform] Managed cluster should", func() {
	defer g.GinkgoRecover()

	g.It("have no crashlooping pods in core namespaces over two minutes", func() {
		c, err := e2e.LoadClientset()
		o.Expect(err).NotTo(o.HaveOccurred())

		var lastPodsWithProblems []*corev1.Pod
		var pending map[string]*corev1.Pod
		wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
			allPods, err := c.CoreV1().Pods("").List(metav1.ListOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())

			var pods []*corev1.Pod
			for i := range allPods.Items {
				pod := &allPods.Items[i]
				if !strings.HasPrefix(pod.Namespace, "openshift-") && !strings.HasPrefix(pod.Namespace, "kube-") {
					continue
				}
				pods = append(pods, pod)
			}

			if pending == nil {
				pending = make(map[string]*corev1.Pod)
				for _, pod := range pods {
					if pod.Status.Phase == corev1.PodPending {
						hasInitContainerRunning := false
						for _, initContainerStatus := range pod.Status.InitContainerStatuses {
							if initContainerStatus.State.Running != nil {
								hasInitContainerRunning = true
								break
							}
						}
						if !hasInitContainerRunning {
							pending[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = pod
						}
					}
				}
			} else {
				for _, pod := range pods {
					if pod.Status.Phase != corev1.PodPending {
						delete(pending, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
					}
				}
			}

			var podsWithProblems []*corev1.Pod
			var names []string
			for _, pod := range pods {
				if pod.Status.Phase == corev1.PodSucceeded {
					continue
				}
				switch {
				case hasCreateContainerError(pod):
				case hasImagePullError(pod):
				case isCrashLooping(pod):
				case hasExcessiveRestarts(pod):
				case hasFailingContainer(pod):
				default:
					continue
				}
				names = append(names, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
				podsWithProblems = append(podsWithProblems, pod)
			}
			if len(names) > 0 {
				e2e.Logf("Some pods in error: %s", strings.Join(names, ", "))
			}
			lastPodsWithProblems = podsWithProblems
			return false, nil
		})
		var msg []string
		ns := make(map[string]struct{})
		for _, pod := range lastPodsWithProblems {
			delete(pending, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
			if _, ok := ns[pod.Namespace]; !ok {
				e2e.DumpEventsInNamespace(func(opts metav1.ListOptions, ns string) (*corev1.EventList, error) {
					return c.CoreV1().Events(ns).List(opts)
				}, pod.Namespace)
				ns[pod.Namespace] = struct{}{}
			}
			status, _ := json.MarshalIndent(pod.Status, "", "  ")
			e2e.Logf("Pod status %s/%s:\n%s", pod.Namespace, pod.Name, string(status))
			msg = append(msg, fmt.Sprintf("Pod %s/%s is not healthy: %v", pod.Namespace, pod.Name, pod.Status.Message))
		}

		for _, pod := range pending {
			if strings.HasPrefix(pod.Name, "must-gather-") {
				e2e.Logf("Pod status %s/%s ignored for being pending", pod.Namespace, pod.Name)
				continue
			}
			if _, ok := ns[pod.Namespace]; !ok {
				e2e.DumpEventsInNamespace(func(opts metav1.ListOptions, ns string) (*corev1.EventList, error) {
					return c.CoreV1().Events(ns).List(opts)
				}, pod.Namespace)
				ns[pod.Namespace] = struct{}{}
			}
			status, _ := json.MarshalIndent(pod.Status, "", "  ")
			e2e.Logf("Pod status %s/%s:\n%s", pod.Namespace, pod.Name, string(status))
			if len(pod.Status.Message) == 0 {
				pod.Status.Message = "unknown error"
			}
			msg = append(msg, fmt.Sprintf("Pod %s/%s was pending entire time: %v", pod.Namespace, pod.Name, pod.Status.Message))
		}

		o.Expect(msg).To(o.BeEmpty())
	})
})

func hasCreateContainerError(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if status.State.Waiting.Reason == "CreateContainerError" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s can't be created", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasImagePullError(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if reason := status.State.Waiting.Reason; reason == "ErrImagePull" || reason == "ImagePullBackOff" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s can't pull image", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasFailingContainer(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Terminated != nil && status.State.Terminated.ExitCode != 0 {
			pod.Status.Message = status.State.Terminated.Message
			if len(pod.Status.Message) == 0 {
				pod.Status.Message = fmt.Sprintf("container %s exited with non-zero exit code", status.Name)
			}
			return true
		}
	}
	return pod.Status.Phase == corev1.PodFailed
}

func isCrashLooping(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if reason := status.State.Waiting.Reason; reason == "CrashLoopBackOff" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s is crashlooping", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasExcessiveRestarts(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.RestartCount > 5 {
			pod.Status.Message = fmt.Sprintf("container %s has restarted more than 5 times", status.Name)
			return true
		}
	}
	return false
}
<commit_msg>Bug 1761346: e2e: populate pending pods map everytime with most recent data<commit_after>package operators

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"
)

var _ = g.Describe("[Feature:Platform] Managed cluster should", func() {
	defer g.GinkgoRecover()

	g.It("have no crashlooping pods in core namespaces over two minutes", func() {
		c, err := e2e.LoadClientset()
		o.Expect(err).NotTo(o.HaveOccurred())

		var lastPodsWithProblems []*corev1.Pod
		var lastPending map[string]*corev1.Pod
		wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
			allPods, err := c.CoreV1().Pods("").List(metav1.ListOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())

			var pods []*corev1.Pod
			for i := range allPods.Items {
				pod := &allPods.Items[i]
				if !strings.HasPrefix(pod.Namespace, "openshift-") && !strings.HasPrefix(pod.Namespace, "kube-") {
					continue
				}
				pods = append(pods, pod)
			}

			pending := make(map[string]*corev1.Pod)
			for _, pod := range pods {
				if pod.Status.Phase == corev1.PodPending {
					hasInitContainerRunning := false
					for _, initContainerStatus := range pod.Status.InitContainerStatuses {
						if initContainerStatus.State.Running != nil {
							hasInitContainerRunning = true
							break
						}
					}
					if !hasInitContainerRunning {
						pending[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = pod
					}
				}
			}
			lastPending = pending

			var podsWithProblems []*corev1.Pod
			var names []string
			for _, pod := range pods {
				if pod.Status.Phase == corev1.PodSucceeded {
					continue
				}
				switch {
				case hasCreateContainerError(pod):
				case hasImagePullError(pod):
				case isCrashLooping(pod):
				case hasExcessiveRestarts(pod):
				case hasFailingContainer(pod):
				default:
					continue
				}
				names = append(names, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
				podsWithProblems = append(podsWithProblems, pod)
			}
			if len(names) > 0 {
				e2e.Logf("Some pods in error: %s", strings.Join(names, ", "))
			}
			lastPodsWithProblems = podsWithProblems
			return false, nil
		})
		var msg []string
		ns := make(map[string]struct{})
		for _, pod := range lastPodsWithProblems {
			delete(lastPending, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
			if _, ok := ns[pod.Namespace]; !ok {
				e2e.DumpEventsInNamespace(func(opts metav1.ListOptions, ns string) (*corev1.EventList, error) {
					return c.CoreV1().Events(ns).List(opts)
				}, pod.Namespace)
				ns[pod.Namespace] = struct{}{}
			}
			status, _ := json.MarshalIndent(pod.Status, "", "  ")
			e2e.Logf("Pod status %s/%s:\n%s", pod.Namespace, pod.Name, string(status))
			msg = append(msg, fmt.Sprintf("Pod %s/%s is not healthy: %v", pod.Namespace, pod.Name, pod.Status.Message))
		}

		for _, pod := range lastPending {
			if strings.HasPrefix(pod.Name, "must-gather-") {
				e2e.Logf("Pod status %s/%s ignored for being pending", pod.Namespace, pod.Name)
				continue
			}
			if _, ok := ns[pod.Namespace]; !ok {
				e2e.DumpEventsInNamespace(func(opts metav1.ListOptions, ns string) (*corev1.EventList, error) {
					return c.CoreV1().Events(ns).List(opts)
				}, pod.Namespace)
				ns[pod.Namespace] = struct{}{}
			}
			status, _ := json.MarshalIndent(pod.Status, "", "  ")
			e2e.Logf("Pod status %s/%s:\n%s", pod.Namespace, pod.Name, string(status))
			if len(pod.Status.Message) == 0 {
				pod.Status.Message = "unknown error"
			}
			msg = append(msg, fmt.Sprintf("Pod %s/%s was pending entire time: %v", pod.Namespace, pod.Name, pod.Status.Message))
		}

		o.Expect(msg).To(o.BeEmpty())
	})
})

func hasCreateContainerError(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if status.State.Waiting.Reason == "CreateContainerError" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s can't be created", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasImagePullError(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if reason := status.State.Waiting.Reason; reason == "ErrImagePull" || reason == "ImagePullBackOff" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s can't pull image", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasFailingContainer(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Terminated != nil && status.State.Terminated.ExitCode != 0 {
			pod.Status.Message = status.State.Terminated.Message
			if len(pod.Status.Message) == 0 {
				pod.Status.Message = fmt.Sprintf("container %s exited with non-zero exit code", status.Name)
			}
			return true
		}
	}
	return pod.Status.Phase == corev1.PodFailed
}

func isCrashLooping(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.State.Waiting != nil {
			if reason := status.State.Waiting.Reason; reason == "CrashLoopBackOff" {
				pod.Status.Message = status.State.Waiting.Message
				if len(pod.Status.Message) == 0 {
					pod.Status.Message = fmt.Sprintf("container %s is crashlooping", status.Name)
				}
				return true
			}
		}
	}
	return false
}

func hasExcessiveRestarts(pod *corev1.Pod) bool {
	for _, status := range append(append([]corev1.ContainerStatus{}, pod.Status.InitContainerStatuses...), pod.Status.ContainerStatuses...) {
		if status.RestartCount > 5 {
			pod.Status.Message = fmt.Sprintf("container %s has restarted more than 5 times", status.Name)
			return true
		}
	}
	return false
}
<|endoftext|>