<commit_before>/*
 * Minio Cloud Storage, (C) 2015, 2016 Minio, 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 main

import (
	"fmt"
	"os"

	"github.com/Sirupsen/logrus"
)

type fileLogger struct {
	Enable   bool   `json:"enable"`
	Filename string `json:"fileName"`
	Level    string `json:"level"`
}

type localFile struct {
	*os.File
}

func enableFileLogger() {
	flogger := serverConfig.GetFileLogger()
	if !flogger.Enable || flogger.Filename != "" {
		return
	}

	file, err := os.OpenFile(flogger.Filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
	fatalIf(err, "Unable to open log file.", nil)

	// Add a local file hook.
	log.Hooks.Add(&localFile{file})

	lvl, err := logrus.ParseLevel(flogger.Level)
	fatalIf(err, "Unknown log level detected, please fix your console logger configuration.", nil)

	// Set default JSON formatter.
	log.Formatter = new(logrus.JSONFormatter)
	log.Level = lvl // Minimum log level.
}

// Fire fires the file logger hook and logs to the file.
func (l *localFile) Fire(entry *logrus.Entry) error {
	line, err := entry.String()
	if err != nil {
		return fmt.Errorf("Unable to read entry, %v", err)
	}
	l.File.Write([]byte(line + "\n"))
	l.File.Sync()
	return nil
}

// Levels -
func (l *localFile) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.PanicLevel,
		logrus.FatalLevel,
		logrus.ErrorLevel,
		logrus.WarnLevel,
		logrus.InfoLevel,
		logrus.DebugLevel,
	}
}
<commit_msg>log: Fix file logging, enable it properly. (#1424)<commit_after>/*
 * Minio Cloud Storage, (C) 2015, 2016 Minio, 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 main

import (
	"fmt"
	"os"

	"github.com/Sirupsen/logrus"
)

type fileLogger struct {
	Enable   bool   `json:"enable"`
	Filename string `json:"fileName"`
	Level    string `json:"level"`
}

type localFile struct {
	*os.File
}

func enableFileLogger() {
	flogger := serverConfig.GetFileLogger()
	if !flogger.Enable || flogger.Filename == "" {
		return
	}

	file, err := os.OpenFile(flogger.Filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
	fatalIf(err, "Unable to open log file.", nil)

	// Add a local file hook.
	log.Hooks.Add(&localFile{file})

	lvl, err := logrus.ParseLevel(flogger.Level)
	fatalIf(err, "Unknown log level detected, please fix your console logger configuration.", nil)

	// Set default JSON formatter.
	log.Formatter = new(logrus.JSONFormatter)
	log.Level = lvl // Minimum log level.
}

// Fire fires the file logger hook and logs to the file.
func (l *localFile) Fire(entry *logrus.Entry) error {
	line, err := entry.String()
	if err != nil {
		return fmt.Errorf("Unable to read entry, %v", err)
	}
	l.File.Write([]byte(line + "\n"))
	l.File.Sync()
	return nil
}

// Levels -
func (l *localFile) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.PanicLevel,
		logrus.FatalLevel,
		logrus.ErrorLevel,
		logrus.WarnLevel,
		logrus.InfoLevel,
		logrus.DebugLevel,
	}
}
<|endoftext|>


<commit_before>package robots

import (
	"fmt"

	"github.com/trinchan/slackbot/robots"
	"math/rand"
)

type bot struct{}

func init() {
	p := &bot{}
	robots.RegisterRobot("raffl", p)
}

func (pb bot) Run(p *robots.Payload) (slashCommandImmediateReturn string) {
	go pb.DeferredAction(p)
	return "checking..."
}

func (pb bot) DeferredAction(p *robots.Payload) {

	reasons := make([]string, 0)
	reasons = append(reasons,
		"Raffle Item 1",
		"Raffle Item 2",
		"Raffle Item 3",
		"Raffle Item 4")

	pick := rand.Intn(100)

	message := ""
	if pick > 0 && pick < len(reasons) {
		message = fmt.Sprint("Your a winner! Here is your prize: %s", reasons[pick])
	} else {
		message = "Sorry, better luck next time!"
	}

	response := &robots.IncomingWebhook{
		Domain:      p.TeamDomain,
		Channel:     p.ChannelID,
		Username:    "raffl",
		Text:        fmt.Sprintf("Hi @%s!\n %s\n %s", p.UserName, "Let's see if you've won a prize.", message),
		IconEmoji:   ":gift:",
		UnfurlLinks: true,
		Parse:       robots.ParseStyleFull,
	}
	response.Send()
}

func (pb bot) Description() (description string) {
	return "Raffl bot!\n\tUsage: /raffl\n\tExpected Response: @user: Raffl this!"
}
<commit_msg>Change immediate response<commit_after>package robots

import (
	"fmt"

	"github.com/trinchan/slackbot/robots"
	"math/rand"
)

type bot struct{}

func init() {
	p := &bot{}
	robots.RegisterRobot("raffl", p)
}

func (pb bot) Run(p *robots.Payload) (slashCommandImmediateReturn string) {
	go pb.DeferredAction(p)
	return "checking..."
}

func (pb bot) DeferredAction(p *robots.Payload) {

	reasons := make([]string, 0)
	reasons = append(reasons,
		"Raffle Item 1",
		"Raffle Item 2",
		"Raffle Item 3",
		"Raffle Item 4")

	pick := rand.Intn(8)

	message := ""
	if pick > 0 && pick < len(reasons) {
		message = fmt.Sprint("Your a winner! Here is your prize: %s", reasons[pick])
	} else {
		message = "Sorry, better luck next time!"
	}

	response := &robots.IncomingWebhook{
		Domain:      p.TeamDomain,
		Channel:     p.ChannelID,
		Username:    "raffl",
		Text:        fmt.Sprintf("Hi @%s!\n %s\n %s", p.UserName, "Let's see if you've won a prize.", message),
		IconEmoji:   ":gift:",
		UnfurlLinks: true,
		Parse:       robots.ParseStyleFull,
	}
	response.Send()
}

func (pb bot) Description() (description string) {
	return "Raffl bot!\n\tUsage: /raffl\n\tExpected Response: @user: Raffl this!"
}
<|endoftext|>


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

package pkcs11

// These tests depend on SoftHSM and the library being in
// in /usr/lib/softhsm/libsofthsm.so

import (
	"fmt"
	"math/big"
	"os"
	"testing"
)

/*
This test supports the following environment variables:

* SOFTHSM_LIB: complete path to libsofthsm.so
* SOFTHSM_TOKENLABEL
* SOFTHSM_PRIVKEYLABEL
* SOFTHSM_PIN
*/

func setenv(t *testing.T) *Ctx {
	lib := "/usr/lib/softhsm/libsofthsm.so"
	if x := os.Getenv("SOFTHSM_LIB"); x != "" {
		lib = x
	}
	t.Logf("loading %s", lib)
	p := New(lib)
	if p == nil {
		t.Fatal("Failed to init lib")
	}
	return p
}

func TestSetenv(t *testing.T) {
	wd, _ := os.Getwd()
	os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")

	lib := "/usr/lib/softhsm/libsofthsm.so"
	if x := os.Getenv("SOFTHSM_LIB"); x != "" {
		lib = x
	}
	p := New(lib)
	if p == nil {
		t.Fatal("Failed to init pkcs11")
	}
	p.Destroy()
	return
}

func getSession(p *Ctx, t *testing.T) SessionHandle {
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e)
	}
	slots, e := p.GetSlotList(true)
	if e != nil {
		t.Fatalf("slots %s\n", e)
	}
	session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
	if e != nil {
		t.Fatalf("session %s\n", e)
	}
	if e := p.Login(session, CKU_USER, pin); e != nil {
		t.Fatalf("user pin %s\n", e)
	}
	return session
}

func TestInitialize(t *testing.T) {
	p := setenv(t)
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e)
	}
	p.Finalize()
	p.Destroy()
}

func finishSession(p *Ctx, session SessionHandle) {
	p.Logout(session)
	p.CloseSession(session)
	p.Finalize()
	p.Destroy()
}

func TestGetInfo(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	info, err := p.GetInfo()
	if err != nil {
		t.Fatalf("non zero error %s\n", err)
	}
	if info.ManufacturerID != "SoftHSM" {
		t.Fatal("ID should be SoftHSM")
	}
	t.Logf("%+v\n", info)
}

func TestFindObject(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	// There are 2 keys in the db with this tag
	template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("failed to init: %s\n", e)
	}
	obj, b, e := p.FindObjects(session, 2)
	if e != nil {
		t.Fatalf("failed to find: %s %v\n", e, b)
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("failed to finalize: %s\n", e)
	}
	if len(obj) != 2 {
		t.Fatal("should have found two objects")
	}
}

func TestGetAttributeValue(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	// There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
	template := []*Attribute{
		NewAttribute(CKA_PUBLIC_EXPONENT, nil),
		NewAttribute(CKA_MODULUS_BITS, nil),
		NewAttribute(CKA_MODULUS, nil),
		NewAttribute(CKA_LABEL, nil),
	}
	// ObjectHandle two is the public key
	attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
	if err != nil {
		t.Fatalf("err %s\n", err)
	}
	for i, a := range attr {
		t.Logf("attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
		if a.Type == CKA_MODULUS {
			mod := big.NewInt(0)
			mod.SetBytes(a.Value)
			t.Logf("modulus %s\n", mod.String())
		}
	}
}

func TestDigest(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
	if e != nil {
		t.Fatalf("DigestInit: %s\n", e)
	}

	hash, e := p.Digest(session, []byte("this is a string"))
	if e != nil {
		t.Fatalf("digest: %s\n", e)
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func TestDigestUpdate(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
		t.Fatalf("DigestInit: %s\n", e)
	}
	if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e)
	}
	if e := p.DigestUpdate(session, []byte("a string")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e)
	}
	hash, e := p.DigestFinal(session)
	if e != nil {
		t.Fatalf("DigestFinal: %s\n", e)
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func testDestroyObject(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)

	p.Logout(session) // log out the normal user
	if e := p.Login(session, CKU_SO, "1234"); e != nil {
		t.Fatalf("security officer pin %s\n", e)
	}

	template := []*Attribute{
		NewAttribute(CKA_LABEL, "MyFirstKey")}

	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("failed to init: %s\n", e)
	}
	obj, _, e := p.FindObjects(session, 1)
	if e != nil || len(obj) == 0 {
		t.Fatalf("failed to find objects\n")
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("failed to finalize: %s\n", e)
	}

	if e := p.DestroyObject(session, obj[0]); e != nil {
		t.Fatal("DestroyObject failed: %s\n", e)
	}
}

// ExampleSign shows how to sign some data with a private key.
// Note: error correction is not implemented in this example.
func ExampleSign() {
	p := setenv(nil)
	p.Initialize()
	defer p.Destroy()
	defer p.Finalize()
	slots, _ := p.GetSlotList(true)
	session, _ := p.OpenSession(slots[0], CKF_SERIAL_SESSION|CKF_RW_SESSION)
	defer p.CloseSession(session)
	p.Login(session, CKU_USER, "1234")
	defer p.Logout(session)
	publicKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
		NewAttribute(CKA_TOKEN, true),
		NewAttribute(CKA_ENCRYPT, true),
		NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
		NewAttribute(CKA_MODULUS_BITS, 1024),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	privateKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PRIVATE_KEY),
		NewAttribute(CKA_TOKEN, true),
		NewAttribute(CKA_PRIVATE, true),
		NewAttribute(CKA_SIGN, true),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	pub, priv, _ := p.GenerateKeyPair(session,
		[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, priv)
	// Sign something with the private key.
	data := []byte("Lets sign this data")

	sig, _ := p.Sign(session, data)
	fmt.Printf("%v validate with %v\n", sig, pub)
}
<commit_msg>Added RSA key generation and signature test<commit_after>// Copyright 2013 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pkcs11

// These tests depend on SoftHSM and the library being in
// in /usr/lib/softhsm/libsofthsm.so

import (
	"fmt"
	"log"
	"math/big"
	"os"
	"testing"
)

/*
This test supports the following environment variables:

* SOFTHSM_LIB: complete path to libsofthsm.so
* SOFTHSM_TOKENLABEL
* SOFTHSM_PRIVKEYLABEL
* SOFTHSM_PIN
*/

func setenv(t *testing.T) *Ctx {
	lib := "/usr/lib/softhsm/libsofthsm.so"
	if x := os.Getenv("SOFTHSM_LIB"); x != "" {
		lib = x
	}
	t.Logf("loading %s", lib)
	p := New(lib)
	if p == nil {
		t.Fatal("Failed to init lib")
	}
	return p
}

func TestSetenv(t *testing.T) {
	wd, _ := os.Getwd()
	os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")

	lib := "/usr/lib/softhsm/libsofthsm.so"
	if x := os.Getenv("SOFTHSM_LIB"); x != "" {
		lib = x
	}
	p := New(lib)
	if p == nil {
		t.Fatal("Failed to init pkcs11")
	}
	p.Destroy()
	return
}

func getSession(p *Ctx, t *testing.T) SessionHandle {
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e)
	}
	slots, e := p.GetSlotList(true)
	if e != nil {
		t.Fatalf("slots %s\n", e)
	}
	session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
	if e != nil {
		t.Fatalf("session %s\n", e)
	}
	if e := p.Login(session, CKU_USER, pin); e != nil {
		t.Fatalf("user pin %s\n", e)
	}
	return session
}

func TestInitialize(t *testing.T) {
	p := setenv(t)
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e)
	}
	p.Finalize()
	p.Destroy()
}

func finishSession(p *Ctx, session SessionHandle) {
	p.Logout(session)
	p.CloseSession(session)
	p.Finalize()
	p.Destroy()
}

func TestGetInfo(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	info, err := p.GetInfo()
	if err != nil {
		t.Fatalf("non zero error %s\n", err)
	}
	if info.ManufacturerID != "SoftHSM" {
		t.Fatal("ID should be SoftHSM")
	}
	t.Logf("%+v\n", info)
}

func TestFindObject(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	// There are 2 keys in the db with this tag
	template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("failed to init: %s\n", e)
	}
	obj, b, e := p.FindObjects(session, 2)
	if e != nil {
		t.Fatalf("failed to find: %s %v\n", e, b)
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("failed to finalize: %s\n", e)
	}
	if len(obj) != 2 {
		t.Fatal("should have found two objects")
	}
}

func TestGetAttributeValue(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	// There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
	template := []*Attribute{
		NewAttribute(CKA_PUBLIC_EXPONENT, nil),
		NewAttribute(CKA_MODULUS_BITS, nil),
		NewAttribute(CKA_MODULUS, nil),
		NewAttribute(CKA_LABEL, nil),
	}
	// ObjectHandle two is the public key
	attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
	if err != nil {
		t.Fatalf("err %s\n", err)
	}
	for i, a := range attr {
		t.Logf("attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
		if a.Type == CKA_MODULUS {
			mod := big.NewInt(0)
			mod.SetBytes(a.Value)
			t.Logf("modulus %s\n", mod.String())
		}
	}
}

func TestDigest(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
	if e != nil {
		t.Fatalf("DigestInit: %s\n", e)
	}

	hash, e := p.Digest(session, []byte("this is a string"))
	if e != nil {
		t.Fatalf("digest: %s\n", e)
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func TestDigestUpdate(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
		t.Fatalf("DigestInit: %s\n", e)
	}
	if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e)
	}
	if e := p.DigestUpdate(session, []byte("a string")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e)
	}
	hash, e := p.DigestFinal(session)
	if e != nil {
		t.Fatalf("DigestFinal: %s\n", e)
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func generateRSAKeyPair(t *testing.T, p *Ctx, session SessionHandle) (ObjectHandle, ObjectHandle) {
	publicKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
		NewAttribute(CKA_TOKEN, false),
		NewAttribute(CKA_VERIFY, true),
		NewAttribute(CKA_PUBLIC_EXPONENT, []byte{1, 0, 1}),
		NewAttribute(CKA_MODULUS_BITS, 2048),
		NewAttribute(CKA_LABEL, "TestPbk"),
	}
	privateKeyTemplate := []*Attribute{
		NewAttribute(CKA_TOKEN, false),
		NewAttribute(CKA_SIGN, true),
		NewAttribute(CKA_LABEL, "TestPvk"),
		NewAttribute(CKA_SENSITIVE, true),
		NewAttribute(CKA_EXTRACTABLE, true),
	}
	pbk, pvk, e := p.GenerateKeyPair(session,
		[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	if e != nil {
		t.Fatalf("failed to generate keypair: %s\n", e)
	}

	return pbk, pvk
}

func TestGenerateKeyPair(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	generateRSAKeyPair(t, p, session)
}

func TestSign(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)
	_, pvk := generateRSAKeyPair(t, p, session)

	p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, pvk)
	_, e := p.Sign(session, []byte("Sign me!"))
	if e != nil {
		t.Fatalf("failed to sign: %s\n", e)
	}
}

func testDestroyObject(t *testing.T) {
	p := setenv(t)
	session := getSession(p, t)
	defer finishSession(p, session)

	p.Logout(session) // log out the normal user
	if e := p.Login(session, CKU_SO, "1234"); e != nil {
		t.Fatalf("security officer pin %s\n", e)
	}

	template := []*Attribute{
		NewAttribute(CKA_LABEL, "MyFirstKey")}

	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("failed to init: %s\n", e)
	}
	obj, _, e := p.FindObjects(session, 1)
	if e != nil || len(obj) == 0 {
		t.Fatalf("failed to find objects\n")
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("failed to finalize: %s\n", e)
	}

	if e := p.DestroyObject(session, obj[0]); e != nil {
		t.Fatal("DestroyObject failed: %s\n", e)
	}
}

// ExampleSign shows how to sign some data with a private key.
// Note: error correction is not implemented in this example.
func ExampleSign() {
	lib := "/usr/lib/softhsm/libsofthsm.so"
	if x := os.Getenv("SOFTHSM_LIB"); x != "" {
		lib = x
	}
	p := New(lib)
	if p == nil {
		log.Fatal("Failed to init lib")
	}

	p.Initialize()
	defer p.Destroy()
	defer p.Finalize()
	slots, _ := p.GetSlotList(true)
	session, _ := p.OpenSession(slots[0], CKF_SERIAL_SESSION|CKF_RW_SESSION)
	defer p.CloseSession(session)
	p.Login(session, CKU_USER, "1234")
	defer p.Logout(session)
	publicKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
		NewAttribute(CKA_TOKEN, false),
		NewAttribute(CKA_ENCRYPT, true),
		NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
		NewAttribute(CKA_MODULUS_BITS, 1024),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	privateKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PRIVATE_KEY),
		NewAttribute(CKA_TOKEN, false),
		NewAttribute(CKA_PRIVATE, true),
		NewAttribute(CKA_SIGN, true),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	_, priv, err := p.GenerateKeyPair(session,
		[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	if err != nil {
		log.Fatal(err)
	}
	p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, priv)
	// Sign something with the private key.
	data := []byte("Lets sign this data")

	_, err = p.Sign(session, data)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("It works!")
	// Output: It works!
}
<|endoftext|>


<commit_before>package cli

import (
	"io/ioutil"
	"log"
	"os"
)

// ExitOnError logs a fatal and exits if the passed error is non-nil.
func ExitOnError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// ExitOnErrorf logs a fatal if the passed error is non-nil. The format string
// and args are passed directly to log.Fatalf, so callers must account for
// including the error's string representation if they desire.
func ExitOnErrorf(err error, msg string, args ...interface{}) {
	if err != nil {
		log.Fatalf(msg, args...)
	}
}

func GetInput(path string) ([]byte, error) {
	if path == "" {
		return ioutil.ReadAll(os.Stdin)
	}

	return ioutil.ReadFile(path)
}
<commit_msg>cli io refactors<commit_after>package cli

import (
	"io"
	"log"
	"os"
)

// ExitOnError logs a fatal and exits if the passed error is non-nil.
func ExitOnError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// ExitOnErrorf logs a fatal if the passed error is non-nil. The format string
// and args are passed directly to log.Fatalf, so callers must account for
// including the error's string representation if they desire.
func ExitOnErrorf(err error, msg string, args ...interface{}) {
	if err != nil {
		log.Fatalf(msg, args...)
	}
}

// GetInput returns the contents of the file at path, or os.Stdin if path is the
// empty string.
func GetInput(path string) ([]byte, error) {
	f, err := Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	return io.ReadAll(f)
}

// Open returns a ReadCloser handle to the file at path, or os.Stdin if path is
// the empty string.
func Open(path string) (io.ReadCloser, error) {
	if path == "" {
		return os.Stdin, nil
	}

	return os.Open(path)
}
<|endoftext|>


<commit_before>package flows

import (
	"encoding/json"

	"github.com/skygeario/skygear-server/pkg/auth/dependency/challenge"
	"github.com/skygeario/skygear-server/pkg/auth/dependency/identity/anonymous"
	"github.com/skygeario/skygear-server/pkg/auth/dependency/interaction"
	"github.com/skygeario/skygear-server/pkg/auth/model"
	"github.com/skygeario/skygear-server/pkg/core/authn"
)

type AnonymousIdentityProvider interface {
	ParseRequest(requestJWT string) (*anonymous.Identity, *anonymous.Request, error)
}

type ChallengeProvider interface {
	Consume(token string) (*challenge.Purpose, error)
}

type AnonymousFlow struct {
	Interactions InteractionProvider
	Anonymous    AnonymousIdentityProvider
	Challenges   ChallengeProvider
}

func (f *AnonymousFlow) Authenticate(requestJWT string, clientID string) (*authn.Attrs, error) {
	identity, request, err := f.Anonymous.ParseRequest(requestJWT)
	if err != nil || request.Action != anonymous.RequestActionAuth {
		return nil, interaction.ErrInvalidCredentials
	}

	var keyID string
	if identity != nil {
		// Verify challenge to use existing identity
		purpose, err := f.Challenges.Consume(request.Challenge)
		if err != nil || *purpose != challenge.PurposeAnonymousRequest {
			return nil, interaction.ErrInvalidCredentials
		}

		keyID = identity.KeyID
	} else {
		// Sign up if identity does not exist
		jwk, err := json.Marshal(request.Key)
		if err != nil {
			return nil, interaction.ErrInvalidCredentials
		}

		i, err := f.Interactions.NewInteractionSignup(&interaction.IntentSignup{
			Identity: interaction.IdentitySpec{
				Type: authn.IdentityTypeAnonymous,
				Claims: map[string]interface{}{
					interaction.IdentityClaimAnonymousKeyID: request.Key.KeyID(),
					interaction.IdentityClaimAnonymousKey:   string(jwk),
				},
			},
			OnUserDuplicate: model.OnUserDuplicateAbort,
		}, clientID)
		if err != nil {
			return nil, err
		}
		s, err := f.Interactions.GetInteractionState(i)
		if err != nil {
			return nil, err
		}
		if s.CurrentStep().Step != interaction.StepCommit {
			panic("interaction_flow_anonymous: unexpected interaction state")
		}
		_, err = f.Interactions.Commit(i)
		if err != nil {
			return nil, err
		}

		keyID = request.Key.KeyID()
	}

	// Login after ensuring user & identity exists
	i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeAnonymous,
			Claims: map[string]interface{}{
				interaction.IdentityClaimAnonymousKeyID: keyID,
			},
		},
	}, clientID)
	if err != nil {
		return nil, err
	}
	s, err := f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	}
	if s.CurrentStep().Step != interaction.StepCommit {
		panic("interaction_flow_anonymous: unexpected interaction state")
	}
	attrs, err := f.Interactions.Commit(i)
	if err != nil {
		return nil, err
	}

	return attrs, nil
}
<commit_msg>Verify challenge token always<commit_after>package flows

import (
	"encoding/json"

	"github.com/skygeario/skygear-server/pkg/auth/dependency/challenge"
	"github.com/skygeario/skygear-server/pkg/auth/dependency/identity/anonymous"
	"github.com/skygeario/skygear-server/pkg/auth/dependency/interaction"
	"github.com/skygeario/skygear-server/pkg/auth/model"
	"github.com/skygeario/skygear-server/pkg/core/authn"
)

type AnonymousIdentityProvider interface {
	ParseRequest(requestJWT string) (*anonymous.Identity, *anonymous.Request, error)
}

type ChallengeProvider interface {
	Consume(token string) (*challenge.Purpose, error)
}

type AnonymousFlow struct {
	Interactions InteractionProvider
	Anonymous    AnonymousIdentityProvider
	Challenges   ChallengeProvider
}

func (f *AnonymousFlow) Authenticate(requestJWT string, clientID string) (*authn.Attrs, error) {
	identity, request, err := f.Anonymous.ParseRequest(requestJWT)
	if err != nil || request.Action != anonymous.RequestActionAuth {
		return nil, interaction.ErrInvalidCredentials
	}

	// Verify challenge token
	purpose, err := f.Challenges.Consume(request.Challenge)
	if err != nil || *purpose != challenge.PurposeAnonymousRequest {
		return nil, interaction.ErrInvalidCredentials
	}

	var keyID string
	if identity != nil {
		keyID = identity.KeyID
	} else {
		// Sign up if identity does not exist
		jwk, err := json.Marshal(request.Key)
		if err != nil {
			return nil, interaction.ErrInvalidCredentials
		}

		i, err := f.Interactions.NewInteractionSignup(&interaction.IntentSignup{
			Identity: interaction.IdentitySpec{
				Type: authn.IdentityTypeAnonymous,
				Claims: map[string]interface{}{
					interaction.IdentityClaimAnonymousKeyID: request.Key.KeyID(),
					interaction.IdentityClaimAnonymousKey:   string(jwk),
				},
			},
			OnUserDuplicate: model.OnUserDuplicateAbort,
		}, clientID)
		if err != nil {
			return nil, err
		}
		s, err := f.Interactions.GetInteractionState(i)
		if err != nil {
			return nil, err
		}
		if s.CurrentStep().Step != interaction.StepCommit {
			panic("interaction_flow_anonymous: unexpected interaction state")
		}
		_, err = f.Interactions.Commit(i)
		if err != nil {
			return nil, err
		}

		keyID = request.Key.KeyID()
	}

	// Login after ensuring user & identity exists
	i, err := f.Interactions.NewInteractionLogin(&interaction.IntentLogin{
		Identity: interaction.IdentitySpec{
			Type: authn.IdentityTypeAnonymous,
			Claims: map[string]interface{}{
				interaction.IdentityClaimAnonymousKeyID: keyID,
			},
		},
	}, clientID)
	if err != nil {
		return nil, err
	}
	s, err := f.Interactions.GetInteractionState(i)
	if err != nil {
		return nil, err
	}
	if s.CurrentStep().Step != interaction.StepCommit {
		panic("interaction_flow_anonymous: unexpected interaction state")
	}
	attrs, err := f.Interactions.Commit(i)
	if err != nil {
		return nil, err
	}

	return attrs, nil
}
<|endoftext|>


<commit_before>package resource

import (
	"errors"

	"github.com/stellar/horizon/db2/history"
	"github.com/stellar/horizon/httpx"
	"github.com/stellar/horizon/render/hal"
	"golang.org/x/net/context"
)

// Populate fills out the details
func (res *Trade) Populate(
	ctx context.Context,
	row history.Effect,
	ledger history.Ledger,
) (err error) {
	if row.Type != history.EffectTrade {
		err = errors.New("invalid effect; not a trade")
		return
	}
	row.UnmarshalDetails(res)
	res.ID = row.PagingToken()
	res.PT = row.PagingToken()
	res.Buyer = row.Account
	res.LedgerCloseTime = ledger.ClosedAt

	lb := hal.LinkBuilder{httpx.BaseURL(ctx)}
	res.Links.Self = lb.Link("/accounts", res.Seller)
	res.Links.Seller = lb.Link("/accounts", res.Seller)
	res.Links.Buyer = lb.Link("/accounts", res.Buyer)
	return
}

// PagingToken implementation for hal.Pageable
func (res Trade) PagingToken() string {
	return res.PT
}
<commit_msg>resource: prevent mismatched trade population<commit_after>package resource

import (
	"errors"

	"github.com/stellar/horizon/db2/history"
	"github.com/stellar/horizon/httpx"
	"github.com/stellar/horizon/render/hal"
	"golang.org/x/net/context"
)

// Populate fills out the details
func (res *Trade) Populate(
	ctx context.Context,
	row history.Effect,
	ledger history.Ledger,
) (err error) {
	if row.Type != history.EffectTrade {
		err = errors.New("invalid effect; not a trade")
		return
	}

	if row.LedgerSequence() != ledger.Sequence {
		err = errors.New("invalid ledger; different sequence than trade")
		return
	}

	row.UnmarshalDetails(res)
	res.ID = row.PagingToken()
	res.PT = row.PagingToken()
	res.Buyer = row.Account
	res.LedgerCloseTime = ledger.ClosedAt

	lb := hal.LinkBuilder{httpx.BaseURL(ctx)}
	res.Links.Self = lb.Link("/accounts", res.Seller)
	res.Links.Seller = lb.Link("/accounts", res.Seller)
	res.Links.Buyer = lb.Link("/accounts", res.Buyer)
	return
}

// PagingToken implementation for hal.Pageable
func (res Trade) PagingToken() string {
	return res.PT
}
<|endoftext|>


<commit_before>package config

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

	"github.com/codegangsta/cli"
)

// Config contains all the configuration needed to run the worker.
type Config struct {
	AmqpURI        string
	PoolSize       int
	BuildAPIURI    string
	ProviderName   string
	ProviderConfig *ProviderConfig
	QueueName      string
	LibratoEmail   string
	LibratoToken   string
	LibratoSource  string
	SentryDSN      string
	Hostname       string
	HardTimeout    time.Duration
	LogTimeout     time.Duration

	BuildAPIInsecureSkipVerify bool
	SkipShutdownOnLogTimeout   bool

	// build script generator options
	BuildCacheFetchTimeout      time.Duration
	BuildCachePushTimeout       time.Duration
	BuildAptCache               string
	BuildNpmCache               string
	BuildParanoid               bool
	BuildFixResolvConf          bool
	BuildFixEtcHosts            bool
	BuildCacheType              string
	BuildCacheS3Scheme          string
	BuildCacheS3Region          string
	BuildCacheS3Bucket          string
	BuildCacheS3AccessKeyID     string
	BuildCacheS3SecretAccessKey string
}

// FromCLIContext creates a Config using a cli.Context by pulling configuration
// from the flags in the context.
func FromCLIContext(c *cli.Context) *Config {
	cfg := &Config{
		AmqpURI:       c.String("amqp-uri"),
		PoolSize:      c.Int("pool-size"),
		BuildAPIURI:   c.String("build-api-uri"),
		ProviderName:  c.String("provider-name"),
		QueueName:     c.String("queue-name"),
		LibratoEmail:  c.String("librato-email"),
		LibratoToken:  c.String("librato-token"),
		LibratoSource: c.String("librato-source"),
		SentryDSN:     c.String("sentry-dsn"),
		Hostname:      c.String("hostname"),
		HardTimeout:   c.Duration("hard-timeout"),
		LogTimeout:    c.Duration("log-timeout"),

		BuildAPIInsecureSkipVerify: c.Bool("build-api-insecure-skip-verify"),
		SkipShutdownOnLogTimeout:   c.Bool("skip-shutdown-on-log-timeout"),

		BuildCacheFetchTimeout:      c.Duration("build-cache-fetch-timeout"),
		BuildCachePushTimeout:       c.Duration("build-cache-push-timeout"),
		BuildAptCache:               c.String("build-apt-cache"),
		BuildNpmCache:               c.String("build-npm-cache"),
		BuildParanoid:               c.Bool("build-paranoid"),
		BuildFixResolvConf:          c.Bool("build-fix-resolv-conf"),
		BuildFixEtcHosts:            c.Bool("build-fix-etc-hosts"),
		BuildCacheType:              c.String("build-cache-type"),
		BuildCacheS3Scheme:          c.String("build-cache-s3-scheme"),
		BuildCacheS3Region:          c.String("build-cache-s3-region"),
		BuildCacheS3Bucket:          c.String("build-cache-s3-bucket"),
		BuildCacheS3AccessKeyID:     c.String("build-cache-s3-access-key-id"),
		BuildCacheS3SecretAccessKey: c.String("build-cache-s3-secret-access-key"),
	}

	cfg.ProviderConfig = ProviderConfigFromEnviron(cfg.ProviderName)

	return cfg
}

// WriteEnvConfig writes the given configuration to out. The format of the
// output is a list of environment variables settings suitable to be sourced
// by a Bourne-like shell.
func WriteEnvConfig(cfg *Config, out io.Writer) {
	cfgMap := map[string]interface{}{
		"amqp-uri":       cfg.AmqpURI,
		"pool-size":      cfg.PoolSize,
		"build-api-uri":  cfg.BuildAPIURI,
		"provider-name":  cfg.ProviderName,
		"queue-name":     cfg.QueueName,
		"librato-email":  cfg.LibratoEmail,
		"librato-token":  cfg.LibratoToken,
		"librato-source": cfg.LibratoSource,
		"sentry-dsn":     cfg.SentryDSN,
		"hostname":       cfg.Hostname,
		"hard-timout":    cfg.HardTimeout,

		"build-api-insecure-skip-verify": cfg.BuildAPIInsecureSkipVerify,
		"skip-shutdown-on-log-timeout":   cfg.SkipShutdownOnLogTimeout,

		"build-cache-fetch-timeout":        cfg.BuildCacheFetchTimeout,
		"build-cache-push-timeout":         cfg.BuildCachePushTimeout,
		"build-opt-cache":                  cfg.BuildAptCache,
		"build-npm-cache":                  cfg.BuildNpmCache,
		"build-paranoid":                   cfg.BuildParanoid,
		"build-fix-resolv-conf":            cfg.BuildFixResolvConf,
		"build-fix-etc-hosts":              cfg.BuildFixEtcHosts,
		"build-cache-type":                 cfg.BuildCacheType,
		"build-cache-s3-scheme":            cfg.BuildCacheS3Scheme,
		"build-cache-s3-region":            cfg.BuildCacheS3Region,
		"build-cache-s3-bucket":            cfg.BuildCacheS3Bucket,
		"build-cache-s3-access-key-id":     cfg.BuildCacheS3AccessKeyID,
		"build-cache-s3-secret-access-key": cfg.BuildCacheS3SecretAccessKey,
	}

	sortedCfgMapKeys := []string{}

	for key := range cfgMap {
		sortedCfgMapKeys = append(sortedCfgMapKeys, key)
	}

	sort.Strings(sortedCfgMapKeys)

	fmt.Fprintf(out, "# travis-worker env config generated %s\n", time.Now().UTC())
	for _, key := range sortedCfgMapKeys {
		envKey := fmt.Sprintf("TRAVIS_WORKER_%s", strings.ToUpper(strings.Replace(key, "-", "_", -1)))
		fmt.Fprintf(out, "export %s=%q\n", envKey, fmt.Sprintf("%v", cfgMap[key]))
	}
	fmt.Fprintf(out, "\n# travis-worker provider config:\n")
	cfg.ProviderConfig.Map(func(key, value string) {
		envKey := strings.ToUpper(fmt.Sprintf("TRAVIS_WORKER_%s_%s", cfg.ProviderName, strings.Replace(key, "-", "_", -1)))
		fmt.Fprintf(out, "export %s=%q\n", envKey, value)
	})
	fmt.Fprintf(out, "# end travis-worker env config\n")
}
<commit_msg>Fixed typo in build-apt-cache option.<commit_after>package config

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

	"github.com/codegangsta/cli"
)

// Config contains all the configuration needed to run the worker.
type Config struct {
	AmqpURI        string
	PoolSize       int
	BuildAPIURI    string
	ProviderName   string
	ProviderConfig *ProviderConfig
	QueueName      string
	LibratoEmail   string
	LibratoToken   string
	LibratoSource  string
	SentryDSN      string
	Hostname       string
	HardTimeout    time.Duration
	LogTimeout     time.Duration

	BuildAPIInsecureSkipVerify bool
	SkipShutdownOnLogTimeout   bool

	// build script generator options
	BuildCacheFetchTimeout      time.Duration
	BuildCachePushTimeout       time.Duration
	BuildAptCache               string
	BuildNpmCache               string
	BuildParanoid               bool
	BuildFixResolvConf          bool
	BuildFixEtcHosts            bool
	BuildCacheType              string
	BuildCacheS3Scheme          string
	BuildCacheS3Region          string
	BuildCacheS3Bucket          string
	BuildCacheS3AccessKeyID     string
	BuildCacheS3SecretAccessKey string
}

// FromCLIContext creates a Config using a cli.Context by pulling configuration
// from the flags in the context.
func FromCLIContext(c *cli.Context) *Config {
	cfg := &Config{
		AmqpURI:       c.String("amqp-uri"),
		PoolSize:      c.Int("pool-size"),
		BuildAPIURI:   c.String("build-api-uri"),
		ProviderName:  c.String("provider-name"),
		QueueName:     c.String("queue-name"),
		LibratoEmail:  c.String("librato-email"),
		LibratoToken:  c.String("librato-token"),
		LibratoSource: c.String("librato-source"),
		SentryDSN:     c.String("sentry-dsn"),
		Hostname:      c.String("hostname"),
		HardTimeout:   c.Duration("hard-timeout"),
		LogTimeout:    c.Duration("log-timeout"),

		BuildAPIInsecureSkipVerify: c.Bool("build-api-insecure-skip-verify"),
		SkipShutdownOnLogTimeout:   c.Bool("skip-shutdown-on-log-timeout"),

		BuildCacheFetchTimeout:      c.Duration("build-cache-fetch-timeout"),
		BuildCachePushTimeout:       c.Duration("build-cache-push-timeout"),
		BuildAptCache:               c.String("build-apt-cache"),
		BuildNpmCache:               c.String("build-npm-cache"),
		BuildParanoid:               c.Bool("build-paranoid"),
		BuildFixResolvConf:          c.Bool("build-fix-resolv-conf"),
		BuildFixEtcHosts:            c.Bool("build-fix-etc-hosts"),
		BuildCacheType:              c.String("build-cache-type"),
		BuildCacheS3Scheme:          c.String("build-cache-s3-scheme"),
		BuildCacheS3Region:          c.String("build-cache-s3-region"),
		BuildCacheS3Bucket:          c.String("build-cache-s3-bucket"),
		BuildCacheS3AccessKeyID:     c.String("build-cache-s3-access-key-id"),
		BuildCacheS3SecretAccessKey: c.String("build-cache-s3-secret-access-key"),
	}

	cfg.ProviderConfig = ProviderConfigFromEnviron(cfg.ProviderName)

	return cfg
}

// WriteEnvConfig writes the given configuration to out. The format of the
// output is a list of environment variables settings suitable to be sourced
// by a Bourne-like shell.
func WriteEnvConfig(cfg *Config, out io.Writer) {
	cfgMap := map[string]interface{}{
		"amqp-uri":       cfg.AmqpURI,
		"pool-size":      cfg.PoolSize,
		"build-api-uri":  cfg.BuildAPIURI,
		"provider-name":  cfg.ProviderName,
		"queue-name":     cfg.QueueName,
		"librato-email":  cfg.LibratoEmail,
		"librato-token":  cfg.LibratoToken,
		"librato-source": cfg.LibratoSource,
		"sentry-dsn":     cfg.SentryDSN,
		"hostname":       cfg.Hostname,
		"hard-timout":    cfg.HardTimeout,

		"build-api-insecure-skip-verify": cfg.BuildAPIInsecureSkipVerify,
		"skip-shutdown-on-log-timeout":   cfg.SkipShutdownOnLogTimeout,

		"build-cache-fetch-timeout":        cfg.BuildCacheFetchTimeout,
		"build-cache-push-timeout":         cfg.BuildCachePushTimeout,
		"build-apt-cache":                  cfg.BuildAptCache,
		"build-npm-cache":                  cfg.BuildNpmCache,
		"build-paranoid":                   cfg.BuildParanoid,
		"build-fix-resolv-conf":            cfg.BuildFixResolvConf,
		"build-fix-etc-hosts":              cfg.BuildFixEtcHosts,
		"build-cache-type":                 cfg.BuildCacheType,
		"build-cache-s3-scheme":            cfg.BuildCacheS3Scheme,
		"build-cache-s3-region":            cfg.BuildCacheS3Region,
		"build-cache-s3-bucket":            cfg.BuildCacheS3Bucket,
		"build-cache-s3-access-key-id":     cfg.BuildCacheS3AccessKeyID,
		"build-cache-s3-secret-access-key": cfg.BuildCacheS3SecretAccessKey,
	}

	sortedCfgMapKeys := []string{}

	for key := range cfgMap {
		sortedCfgMapKeys = append(sortedCfgMapKeys, key)
	}

	sort.Strings(sortedCfgMapKeys)

	fmt.Fprintf(out, "# travis-worker env config generated %s\n", time.Now().UTC())
	for _, key := range sortedCfgMapKeys {
		envKey := fmt.Sprintf("TRAVIS_WORKER_%s", strings.ToUpper(strings.Replace(key, "-", "_", -1)))
		fmt.Fprintf(out, "export %s=%q\n", envKey, fmt.Sprintf("%v", cfgMap[key]))
	}
	fmt.Fprintf(out, "\n# travis-worker provider config:\n")
	cfg.ProviderConfig.Map(func(key, value string) {
		envKey := strings.ToUpper(fmt.Sprintf("TRAVIS_WORKER_%s_%s", cfg.ProviderName, strings.Replace(key, "-", "_", -1)))
		fmt.Fprintf(out, "export %s=%q\n", envKey, value)
	})
	fmt.Fprintf(out, "# end travis-worker env config\n")
}
<|endoftext|>


<commit_before>package tls

import (
	"context"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/rancher/dynamiclistener"
	"github.com/rancher/dynamiclistener/cert"
	"github.com/rancher/dynamiclistener/server"
	"github.com/rancher/dynamiclistener/storage/kubernetes"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/rancher/pkg/namespace"
	"github.com/rancher/rancher/pkg/settings"
	"github.com/rancher/wrangler/pkg/generated/controllers/core"
	corev1controllers "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/sirupsen/logrus"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/rest"
)

const (
	rancherCertFile    = "/etc/rancher/ssl/cert.pem"
	rancherKeyFile     = "/etc/rancher/ssl/key.pem"
	rancherCACertsFile = "/etc/rancher/ssl/cacerts.pem"
)

type internalAPI struct{}

var (
	InternalAPI = internalAPI{}
)

func ListenAndServe(ctx context.Context, restConfig *rest.Config, handler http.Handler, bindHost string, httpsPort, httpPort int, acmeDomains []string, noCACerts bool) error {
	restConfig = rest.CopyConfig(restConfig)
	restConfig.Timeout = 10 * time.Minute
	opts := &server.ListenOpts{}
	var err error

	core, err := core.NewFactoryFromConfig(restConfig)
	if err != nil {
		return err
	}

	if httpsPort != 0 {
		opts, err = SetupListener(core.Core().V1().Secret(), acmeDomains, noCACerts)
		if err != nil {
			return errors.Wrap(err, "failed to setup TLS listener")
		}
	}

	opts.BindHost = bindHost

	migrateConfig(ctx, restConfig, opts)

	backoff := wait.Backoff{
		Duration: 100 * time.Millisecond,
		Factor:   2,
		Steps:    3,
	}

	// Try listen and serve over if there is an already exist error which comes from
	// creating the ca. Rancher will hit this error during HA startup as all servers
	// will race to create the ca secret.
	err = wait.ExponentialBackoff(backoff, func() (bool, error) {
		if err := server.ListenAndServe(ctx, httpsPort, httpPort, handler, opts); err != nil {
			if apierrors.IsAlreadyExists(err) {
				return false, nil
			}
			return false, err
		}
		return true, nil
	})
	if err != nil {
		return errors.Wrap(err, "failed to ListenAndServe")
	}

	internalPort := 0
	if httpsPort != 0 {
		internalPort = httpsPort + 1
	}

	serverOptions := &server.ListenOpts{
		Storage:       opts.Storage,
		Secrets:       opts.Secrets,
		CAName:        "tls-rancher-internal-ca",
		CANamespace:   namespace.System,
		CertNamespace: namespace.System,
		CertName:      "tls-rancher-internal",
	}

	internalAPICtx := context.WithValue(ctx, InternalAPI, true)
	err = wait.ExponentialBackoff(backoff, func() (bool, error) {
		if err := server.ListenAndServe(internalAPICtx, internalPort, 0, handler, serverOptions); err != nil {
			if apierrors.IsAlreadyExists(err) {
				return false, nil
			}
			return false, err
		}
		return true, nil
	})
	if err != nil {
		return errors.Wrap(err, "failed to ListenAndServe for fleet")
	}

	if err := core.Start(ctx, 5); err != nil {
		return err
	}

	<-ctx.Done()
	return ctx.Err()

}

func migrateConfig(ctx context.Context, restConfig *rest.Config, opts *server.ListenOpts) {
	c, err := dynamic.NewForConfig(restConfig)
	if err != nil {
		return
	}

	config, err := c.Resource(schema.GroupVersionResource{
		Group:    "management.cattle.io",
		Version:  "v3",
		Resource: "listenconfigs",
	}).Get(ctx, "cli-config", metav1.GetOptions{})
	if err != nil {
		return
	}

	known := convert.ToStringSlice(config.Object["knownIps"])
	for k := range convert.ToMapInterface(config.Object["generatedCerts"]) {
		if strings.HasPrefix(k, "local/") {
			continue
		}
		known = append(known, k)
	}

	for _, k := range known {
		k = strings.SplitN(k, ":", 2)[0]
		found := false
		for _, san := range opts.TLSListenerConfig.SANs {
			if san == k {
				found = true
				break
			}
		}
		if !found {
			opts.TLSListenerConfig.SANs = append(opts.TLSListenerConfig.SANs, k)
		}
	}
}

func SetupListener(secrets corev1controllers.SecretController, acmeDomains []string, noCACerts bool) (*server.ListenOpts, error) {
	caForAgent, noCACerts, opts, err := readConfig(secrets, acmeDomains, noCACerts)
	if err != nil {
		return nil, err
	}

	if noCACerts {
		caForAgent = ""
	} else if caForAgent == "" {
		caCert, caKey, err := kubernetes.LoadOrGenCA(secrets, opts.CANamespace, opts.CAName)
		if err != nil {
			return nil, err
		}
		caForAgent = string(cert.EncodeCertPEM(caCert))
		opts.CA = caCert
		opts.CAKey = caKey
	}

	caForAgent = strings.TrimSpace(caForAgent)
	if settings.CACerts.Get() != caForAgent {
		if err := settings.CACerts.Set(caForAgent); err != nil {
			return nil, err
		}
	}

	return opts, nil
}

func readConfig(secrets corev1controllers.SecretController, acmeDomains []string, noCACerts bool) (string, bool, *server.ListenOpts, error) {
	var (
		ca  string
		err error
	)

	tlsConfig, err := BaseTLSConfig()
	if err != nil {
		return "", noCACerts, nil, err
	}

	expiration, err := strconv.Atoi(settings.RotateCertsIfExpiringInDays.Get())
	if err != nil {
		return "", noCACerts, nil, errors.Wrapf(err, "parsing %s", settings.RotateCertsIfExpiringInDays.Get())
	}

	sans := []string{"localhost", "127.0.0.1", "rancher.cattle-system"}
	ip, err := net.ChooseHostInterface()
	if err == nil {
		sans = append(sans, ip.String())
	}

	opts := &server.ListenOpts{
		Secrets:       secrets,
		CAName:        "tls-rancher",
		CANamespace:   "cattle-system",
		CertNamespace: "cattle-system",
		AcmeDomains:   acmeDomains,
		TLSListenerConfig: dynamiclistener.Config{
			TLSConfig:             tlsConfig,
			ExpirationDaysCheck:   expiration,
			SANs:                  sans,
			FilterCN:              filterCN,
			CloseConnOnCertChange: true,
		},
	}

	// ACME / Let's Encrypt
	// If --acme-domain is set, configure and return
	if len(acmeDomains) > 0 {
		return "", true, opts, nil
	}

	// Mounted certificates
	// If certificate file/key are set
	certFileExists := fileExists(rancherCertFile)
	keyFileExists := fileExists(rancherKeyFile)

	// If certificate file exists but not certificate key, or other way around, error out
	if (certFileExists && !keyFileExists) || (!certFileExists && keyFileExists) {
		return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set both certificate file and certificate key file (one is missing)")
	}

	caFileExists := fileExists(rancherCACertsFile)

	// If certificate file and certificate key file exists, load files into listenConfig
	if certFileExists && keyFileExists {
		cert, err := tls.LoadX509KeyPair(rancherCertFile, rancherKeyFile)
		if err != nil {
			return "", noCACerts, nil, err
		}
		opts.TLSListenerConfig.TLSConfig.Certificates = []tls.Certificate{cert}

		// Selfsigned needs cacerts, recognized CA needs --no-cacerts but can't be used together
		if (caFileExists && noCACerts) || (!caFileExists && !noCACerts) {
			return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set cacerts when using self signed certificates or use --no-cacerts when using certificates from a recognized Certificate Authority, do not use both at the same time")
		}
		// Load cacerts if exists
		if caFileExists {
			ca, err = readPEM(rancherCACertsFile)
			if err != nil {
				return "", noCACerts, nil, err
			}
		}
		return ca, noCACerts, opts, nil
	}

	// External termination
	// We need to check if cacerts is passed or if --no-cacerts is used (when not providing certificate file and key)
	// If cacerts is passed
	if caFileExists {
		// We can't have --no-cacerts
		if noCACerts {
			return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set cacerts when using self signed certificates or use --no-cacerts when using certificates from a recognized Certificate Authority, do not use both at the same time")
		}
		ca, err = readPEM(rancherCACertsFile)
		if err != nil {
			return "", noCACerts, nil, err
		}
	}

	// No certificates mounted or only --no-cacerts used
	return ca, noCACerts, opts, nil
}

func filterCN(cns ...string) []string {
	serverURL := settings.ServerURL.Get()
	if serverURL == "" {
		return cns
	}
	u, err := url.Parse(serverURL)
	if err != nil {
		logrus.Errorf("invalid server-url, can not parse %s: %v", serverURL, err)
		return cns
	}
	host := u.Hostname()
	for _, cn := range cns {
		if cn == host {
			return []string{host}
		}
	}
	return nil
}

func fileExists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func readPEM(path string) (string, error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	return string(content), nil
}
<commit_msg>Add rancher cluster IP to generated internal certs<commit_after>package tls

import (
	"context"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
	"github.com/rancher/dynamiclistener"
	"github.com/rancher/dynamiclistener/cert"
	"github.com/rancher/dynamiclistener/server"
	"github.com/rancher/dynamiclistener/storage/kubernetes"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/rancher/pkg/namespace"
	"github.com/rancher/rancher/pkg/settings"
	"github.com/rancher/wrangler/pkg/generated/controllers/core"
	corev1controllers "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/sirupsen/logrus"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/rest"
)

const (
	rancherCertFile    = "/etc/rancher/ssl/cert.pem"
	rancherKeyFile     = "/etc/rancher/ssl/key.pem"
	rancherCACertsFile = "/etc/rancher/ssl/cacerts.pem"
)

type internalAPI struct{}

var (
	InternalAPI = internalAPI{}
)

func ListenAndServe(ctx context.Context, restConfig *rest.Config, handler http.Handler, bindHost string, httpsPort, httpPort int, acmeDomains []string, noCACerts bool) error {
	restConfig = rest.CopyConfig(restConfig)
	restConfig.Timeout = 10 * time.Minute
	opts := &server.ListenOpts{}
	var err error

	core, err := core.NewFactoryFromConfig(restConfig)
	if err != nil {
		return err
	}

	if httpsPort != 0 {
		opts, err = SetupListener(core.Core().V1().Secret(), acmeDomains, noCACerts)
		if err != nil {
			return errors.Wrap(err, "failed to setup TLS listener")
		}
	}

	opts.BindHost = bindHost

	migrateConfig(ctx, restConfig, opts)

	backoff := wait.Backoff{
		Duration: 100 * time.Millisecond,
		Factor:   2,
		Steps:    3,
	}

	// Try listen and serve over if there is an already exist error which comes from
	// creating the ca. Rancher will hit this error during HA startup as all servers
	// will race to create the ca secret.
	err = wait.ExponentialBackoff(backoff, func() (bool, error) {
		if err := server.ListenAndServe(ctx, httpsPort, httpPort, handler, opts); err != nil {
			if apierrors.IsAlreadyExists(err) {
				return false, nil
			}
			return false, err
		}
		return true, nil
	})
	if err != nil {
		return errors.Wrap(err, "failed to ListenAndServe")
	}

	internalPort := 0
	if httpsPort != 0 {
		internalPort = httpsPort + 1
	}

	serverOptions := &server.ListenOpts{
		Storage:       opts.Storage,
		Secrets:       opts.Secrets,
		CAName:        "tls-rancher-internal-ca",
		CANamespace:   namespace.System,
		CertNamespace: namespace.System,
		CertName:      "tls-rancher-internal",
	}
	clusterIP, err := getClusterIP(core.Core().V1().Service())
	if err != nil {
		return err
	}
	if clusterIP != "" {
		serverOptions.TLSListenerConfig = dynamiclistener.Config{
			SANs: []string{clusterIP},
		}
	}

	internalAPICtx := context.WithValue(ctx, InternalAPI, true)
	err = wait.ExponentialBackoff(backoff, func() (bool, error) {
		if err := server.ListenAndServe(internalAPICtx, internalPort, 0, handler, serverOptions); err != nil {
			if apierrors.IsAlreadyExists(err) {
				return false, nil
			}
			return false, err
		}
		return true, nil
	})
	if err != nil {
		return errors.Wrap(err, "failed to ListenAndServe for fleet")
	}

	if err := core.Start(ctx, 5); err != nil {
		return err
	}

	<-ctx.Done()
	return ctx.Err()

}

func migrateConfig(ctx context.Context, restConfig *rest.Config, opts *server.ListenOpts) {
	c, err := dynamic.NewForConfig(restConfig)
	if err != nil {
		return
	}

	config, err := c.Resource(schema.GroupVersionResource{
		Group:    "management.cattle.io",
		Version:  "v3",
		Resource: "listenconfigs",
	}).Get(ctx, "cli-config", metav1.GetOptions{})
	if err != nil {
		return
	}

	known := convert.ToStringSlice(config.Object["knownIps"])
	for k := range convert.ToMapInterface(config.Object["generatedCerts"]) {
		if strings.HasPrefix(k, "local/") {
			continue
		}
		known = append(known, k)
	}

	for _, k := range known {
		k = strings.SplitN(k, ":", 2)[0]
		found := false
		for _, san := range opts.TLSListenerConfig.SANs {
			if san == k {
				found = true
				break
			}
		}
		if !found {
			opts.TLSListenerConfig.SANs = append(opts.TLSListenerConfig.SANs, k)
		}
	}
}

func SetupListener(secrets corev1controllers.SecretController, acmeDomains []string, noCACerts bool) (*server.ListenOpts, error) {
	caForAgent, noCACerts, opts, err := readConfig(secrets, acmeDomains, noCACerts)
	if err != nil {
		return nil, err
	}

	if noCACerts {
		caForAgent = ""
	} else if caForAgent == "" {
		caCert, caKey, err := kubernetes.LoadOrGenCA(secrets, opts.CANamespace, opts.CAName)
		if err != nil {
			return nil, err
		}
		caForAgent = string(cert.EncodeCertPEM(caCert))
		opts.CA = caCert
		opts.CAKey = caKey
	}

	caForAgent = strings.TrimSpace(caForAgent)
	if settings.CACerts.Get() != caForAgent {
		if err := settings.CACerts.Set(caForAgent); err != nil {
			return nil, err
		}
	}

	return opts, nil
}

func readConfig(secrets corev1controllers.SecretController, acmeDomains []string, noCACerts bool) (string, bool, *server.ListenOpts, error) {
	var (
		ca  string
		err error
	)

	tlsConfig, err := BaseTLSConfig()
	if err != nil {
		return "", noCACerts, nil, err
	}

	expiration, err := strconv.Atoi(settings.RotateCertsIfExpiringInDays.Get())
	if err != nil {
		return "", noCACerts, nil, errors.Wrapf(err, "parsing %s", settings.RotateCertsIfExpiringInDays.Get())
	}

	sans := []string{"localhost", "127.0.0.1", "rancher.cattle-system"}
	ip, err := net.ChooseHostInterface()
	if err == nil {
		sans = append(sans, ip.String())
	}

	opts := &server.ListenOpts{
		Secrets:       secrets,
		CAName:        "tls-rancher",
		CANamespace:   "cattle-system",
		CertNamespace: "cattle-system",
		AcmeDomains:   acmeDomains,
		TLSListenerConfig: dynamiclistener.Config{
			TLSConfig:             tlsConfig,
			ExpirationDaysCheck:   expiration,
			SANs:                  sans,
			FilterCN:              filterCN,
			CloseConnOnCertChange: true,
		},
	}

	// ACME / Let's Encrypt
	// If --acme-domain is set, configure and return
	if len(acmeDomains) > 0 {
		return "", true, opts, nil
	}

	// Mounted certificates
	// If certificate file/key are set
	certFileExists := fileExists(rancherCertFile)
	keyFileExists := fileExists(rancherKeyFile)

	// If certificate file exists but not certificate key, or other way around, error out
	if (certFileExists && !keyFileExists) || (!certFileExists && keyFileExists) {
		return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set both certificate file and certificate key file (one is missing)")
	}

	caFileExists := fileExists(rancherCACertsFile)

	// If certificate file and certificate key file exists, load files into listenConfig
	if certFileExists && keyFileExists {
		cert, err := tls.LoadX509KeyPair(rancherCertFile, rancherKeyFile)
		if err != nil {
			return "", noCACerts, nil, err
		}
		opts.TLSListenerConfig.TLSConfig.Certificates = []tls.Certificate{cert}

		// Selfsigned needs cacerts, recognized CA needs --no-cacerts but can't be used together
		if (caFileExists && noCACerts) || (!caFileExists && !noCACerts) {
			return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set cacerts when using self signed certificates or use --no-cacerts when using certificates from a recognized Certificate Authority, do not use both at the same time")
		}
		// Load cacerts if exists
		if caFileExists {
			ca, err = readPEM(rancherCACertsFile)
			if err != nil {
				return "", noCACerts, nil, err
			}
		}
		return ca, noCACerts, opts, nil
	}

	// External termination
	// We need to check if cacerts is passed or if --no-cacerts is used (when not providing certificate file and key)
	// If cacerts is passed
	if caFileExists {
		// We can't have --no-cacerts
		if noCACerts {
			return "", noCACerts, nil, fmt.Errorf("invalid SSL configuration found, please set cacerts when using self signed certificates or use --no-cacerts when using certificates from a recognized Certificate Authority, do not use both at the same time")
		}
		ca, err = readPEM(rancherCACertsFile)
		if err != nil {
			return "", noCACerts, nil, err
		}
	}

	// No certificates mounted or only --no-cacerts used
	return ca, noCACerts, opts, nil
}

func getClusterIP(services corev1controllers.ServiceController) (string, error) {
	service, err := services.Get(namespace.System, "rancher", metav1.GetOptions{})
	if err != nil {
		if apierrors.IsNotFound(err) {
			return "", nil
		}
		return "", err
	}
	if service.Spec.ClusterIP == "" {
		return "", fmt.Errorf("waiting on service %s/rancher to be assigned a ClusterIP", namespace.System)
	}
	return service.Spec.ClusterIP, nil
}

func filterCN(cns ...string) []string {
	serverURL := settings.ServerURL.Get()
	if serverURL == "" {
		return cns
	}
	u, err := url.Parse(serverURL)
	if err != nil {
		logrus.Errorf("invalid server-url, can not parse %s: %v", serverURL, err)
		return cns
	}
	host := u.Hostname()
	for _, cn := range cns {
		if cn == host {
			return []string{host}
		}
	}
	return nil
}

func fileExists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func readPEM(path string) (string, error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	return string(content), nil
}
<|endoftext|>


<commit_before>package main

/// had to have a `util` file.
/// Because pragmatism.
/// Because irony.

import (
	"fmt"
	"github.com/briandowns/spinner"
	humanize "github.com/dustin/go-humanize"
	"github.com/olekukonko/tablewriter"
	"github.com/parnurzeal/gorequest"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"time"
)

func AugmentRequest(c *gorequest.SuperAgent, cfg *Config) *gorequest.SuperAgent {
	return c.
		AddCookie(cfg.GetAuthCookie()).
		Set("Content-type", "application/json").
		Set("User-Agent", UserAgentString(globalBuildVersion)).
		Timeout(15 * time.Second).
		SetCurlCommand(globalEnableCurl).
		SetDebug(globalEnableDebug)
}

func RenderTableToStdout(headers []string, data [][]string) {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader(headers)
	table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false})
	table.SetHeaderLine(false)
	table.SetRowLine(false)
	table.SetColWidth(100)
	table.SetColumnSeparator("")
	table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.AppendBulk(data) // Add Bulk Data
	table.Render()
}

func hostFromUri(str string) (error, string) {
	u, e := url.Parse(str)
	if e != nil {
		return e, ""
	}
	return e, u.Host
}

/*
 * return a java-style System.currentTimeMillis to match
 * the values being returned from the server.
 */
func currentTimeMillis() int64 {
	return time.Now().UnixNano() / int64(time.Millisecond)
}

func javaEpochToTime(long int64) time.Time {
	return time.Unix(0, long*int64(time.Millisecond))
}

func javaEpochToHumanizedTime(long int64) string {
	return humanize.Time(javaEpochToTime(long))
}

func JavaEpochToDateStr(long int64) string {
	t := javaEpochToTime(long)
	return t.Format(time.RFC3339)
}

func ProgressIndicator() *spinner.Spinner {
	s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
	s.Color("green")
	return s
}

func PrintTerminalErrors(errs []error) {
	for i, j := 0, len(errs)-1; i < j; i, j = i+1, j-1 {
		errs[i], errs[j] = errs[j], errs[i]
	}

	for _, e := range errs {
		fmt.Println(e)
	}
}

func isValidGUID(in string) bool {
	match, _ := regexp.MatchString(`^[a-z0-9]{12,12}$`, in)
	return match
}

func isValidCommaDelimitedList(str string) bool {
	match, _ := regexp.MatchString(`^([a-z0-9\\-]+,?)+$`, str)
	return match
}

func CurrentVersion() string {
	if len(globalBuildVersion) == 0 {
		return "dev"
	} else {
		return "v" + globalBuildVersion
	}
}

func UserAgentString(globalBuildVersion string) string {
	var name = "NelsonCLI"
	var version = getVersionForMode(globalBuildVersion)
	return name + "/" + version + " (" + runtime.GOOS + ")"
}

func getVersionForMode(globalBuildVersion string) string {
	if len(globalBuildVersion) == 0 {
		return "dev"
	} else {
		return "0.5." + globalBuildVersion
	}
}
<commit_msg>add automatic retries <commit_after>package main

/// had to have a `util` file.
/// Because pragmatism.
/// Because irony.

import (
	"fmt"
	"github.com/briandowns/spinner"
	humanize "github.com/dustin/go-humanize"
	"github.com/olekukonko/tablewriter"
	"github.com/parnurzeal/gorequest"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"time"
)

func AugmentRequest(c *gorequest.SuperAgent, cfg *Config) *gorequest.SuperAgent {
	return c.
		AddCookie(cfg.GetAuthCookie()).
		Set("Content-type", "application/json").
		Set("User-Agent", UserAgentString(globalBuildVersion)).
		Timeout(5*time.Second).
		Retry(3, 1*time.Second, http.StatusBadGateway, http.StatusInternalServerError).
		SetCurlCommand(globalEnableCurl).
		SetDebug(globalEnableDebug)
}

func RenderTableToStdout(headers []string, data [][]string) {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader(headers)
	table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false})
	table.SetHeaderLine(false)
	table.SetRowLine(false)
	table.SetColWidth(100)
	table.SetColumnSeparator("")
	table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.AppendBulk(data) // Add Bulk Data
	table.Render()
}

func hostFromUri(str string) (error, string) {
	u, e := url.Parse(str)
	if e != nil {
		return e, ""
	}
	return e, u.Host
}

/*
 * return a java-style System.currentTimeMillis to match
 * the values being returned from the server.
 */
func currentTimeMillis() int64 {
	return time.Now().UnixNano() / int64(time.Millisecond)
}

func javaEpochToTime(long int64) time.Time {
	return time.Unix(0, long*int64(time.Millisecond))
}

func javaEpochToHumanizedTime(long int64) string {
	return humanize.Time(javaEpochToTime(long))
}

func JavaEpochToDateStr(long int64) string {
	t := javaEpochToTime(long)
	return t.Format(time.RFC3339)
}

func ProgressIndicator() *spinner.Spinner {
	s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
	s.Color("green")
	return s
}

func PrintTerminalErrors(errs []error) {
	for i, j := 0, len(errs)-1; i < j; i, j = i+1, j-1 {
		errs[i], errs[j] = errs[j], errs[i]
	}

	for _, e := range errs {
		fmt.Println(e)
	}
}

func isValidGUID(in string) bool {
	match, _ := regexp.MatchString(`^[a-z0-9]{12,12}$`, in)
	return match
}

func isValidCommaDelimitedList(str string) bool {
	match, _ := regexp.MatchString(`^([a-z0-9\\-]+,?)+$`, str)
	return match
}

func CurrentVersion() string {
	if len(globalBuildVersion) == 0 {
		return "dev"
	} else {
		return "v" + globalBuildVersion
	}
}

func UserAgentString(globalBuildVersion string) string {
	var name = "NelsonCLI"
	var version = getVersionForMode(globalBuildVersion)
	return name + "/" + version + " (" + runtime.GOOS + ")"
}

func getVersionForMode(globalBuildVersion string) string {
	if len(globalBuildVersion) == 0 {
		return "dev"
	} else {
		return "0.5." + globalBuildVersion
	}
}
<|endoftext|>


<commit_before>package ui

import (
	"fmt"
	c "github.com/tiagorlampert/CHAOS/pkg/color"
)

func ShowMenuHeader(version string) {
	fmt.Println("")
	fmt.Println(c.Yellow, "                                                 CHAOS v"+version)
	fmt.Println(c.Cyan, "                                             by tiagorlampert")
	fmt.Println("")
	fmt.Println(c.White, " Please use `tab` to autocomplete commands,")
	fmt.Println(c.White, " or type `exit` to quit this program.")
	fmt.Println("")
}
<commit_msg>update version on menu<commit_after>package ui

import (
	"fmt"
	c "github.com/tiagorlampert/CHAOS/pkg/color"
)

func ShowMenuHeader(version string) {
	fmt.Println("")
	fmt.Println(c.Yellow, "                                                 CHAOS "+version)
	fmt.Println(c.Cyan, "                                             by tiagorlampert")
	fmt.Println("")
	fmt.Println(c.White, " Please use `tab` to autocomplete commands,")
	fmt.Println(c.White, " or type `exit` to quit this program.")
	fmt.Println("")
}
<|endoftext|>


<commit_before>package util

import (
	"bufio"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"
)

// PromptForInt read command line input
func PromptForInt(in io.Reader, out io.Writer, prompt string, defaultValue int) (int, error) {
	fmt.Print(out, "=> %s [%d]: ", prompt, defaultValue)
	s := bufio.NewScanner(in)
	// Scan the first token
	s.Scan()
	if s.Err() != nil {
		return defaultValue, fmt.Errorf("error reading number: %v", s.Err())
	}
	ans := s.Text()
	if ans == "" {
		return defaultValue, nil
	}
	// Convert input into integer
	i, err := strconv.Atoi(ans)
	if err != nil {
		return defaultValue, fmt.Errorf("%q is not a number", ans)
	}
	return i, nil
}

// CreateDir check if directory exists and create it
func CreateDir(dir string, perm os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.Mkdir(dir, perm)
		if err != nil {
			return fmt.Errorf("error creating destination dir: %v", err)
		}
	}

	return nil
}

// Base64String read file and return base64 string
func Base64String(path string) (string, error) {
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}
	fileEncoded := base64.StdEncoding.EncodeToString(file)

	return fileEncoded, nil
}
<commit_msg>No Ticket - Fix print function when prompting for user input<commit_after>package util

import (
	"bufio"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"
)

// PromptForInt read command line input
func PromptForInt(in io.Reader, out io.Writer, prompt string, defaultValue int) (int, error) {
	fmt.Fprintf(out, "=> %s [%d]: ", prompt, defaultValue)
	s := bufio.NewScanner(in)
	// Scan the first token
	s.Scan()
	if s.Err() != nil {
		return defaultValue, fmt.Errorf("error reading number: %v", s.Err())
	}
	ans := s.Text()
	if ans == "" {
		return defaultValue, nil
	}
	// Convert input into integer
	i, err := strconv.Atoi(ans)
	if err != nil {
		return defaultValue, fmt.Errorf("%q is not a number", ans)
	}
	return i, nil
}

// CreateDir check if directory exists and create it
func CreateDir(dir string, perm os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.Mkdir(dir, perm)
		if err != nil {
			return fmt.Errorf("error creating destination dir: %v", err)
		}
	}

	return nil
}

// Base64String read file and return base64 string
func Base64String(path string) (string, error) {
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}
	fileEncoded := base64.StdEncoding.EncodeToString(file)

	return fileEncoded, nil
}
<|endoftext|>


<commit_before>/*
Copyright The Helm 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 action

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"

	"helm.sh/helm/pkg/chartutil"
	"helm.sh/helm/pkg/lint"
	"helm.sh/helm/pkg/lint/support"
)

var errLintNoChart = errors.New("no chart found for linting (missing Chart.yaml)")

// Lint is the action for checking that the semantics of a chart are well-formed.
//
// It provides the implementation of 'helm lint'.
type Lint struct {
	Strict    bool
	Namespace string
}

type LintResult struct {
	TotalChartsLinted int
	Messages          []support.Message
	Errors            []error
}

// NewLint creates a new Lint object with the given configuration.
func NewLint() *Lint {
	return &Lint{}
}

// Run executes 'helm Lint' against the given chart.
func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
	lowestTolerance := support.ErrorSev
	if l.Strict {
		lowestTolerance = support.WarningSev
	}

	result := &LintResult{}
	for _, path := range paths {
		linter, err := lintChart(path, vals, l.Namespace, l.Strict)
		if err != nil {
			if err == errLintNoChart {
				result.Errors = append(result.Errors, err)
			}
			if linter.HighestSeverity >= lowestTolerance {
				result.Errors = append(result.Errors, err)
			}
		} else {
			result.Messages = append(result.Messages, linter.Messages...)
			result.TotalChartsLinted++
			for _, msg := range linter.Messages {
				if msg.Severity == support.ErrorSev {
					result.Errors = append(result.Errors, msg.Err)
				}
			}
		}
	}
	return result
}

func lintChart(path string, vals map[string]interface{}, namespace string, strict bool) (support.Linter, error) {
	var chartPath string
	linter := support.Linter{}

	if strings.HasSuffix(path, ".tgz") {
		tempDir, err := ioutil.TempDir("", "helm-lint")
		if err != nil {
			return linter, err
		}
		defer os.RemoveAll(tempDir)

		file, err := os.Open(path)
		if err != nil {
			return linter, err
		}
		defer file.Close()

		if err = chartutil.Expand(tempDir, file); err != nil {
			return linter, err
		}

		lastHyphenIndex := strings.LastIndex(filepath.Base(path), "-")
		if lastHyphenIndex <= 0 {
			return linter, errors.Errorf("unable to parse chart archive %q, missing '-'", filepath.Base(path))
		}
		base := filepath.Base(path)[:lastHyphenIndex]
		chartPath = filepath.Join(tempDir, base)
	} else {
		chartPath = path
	}

	// Guard: Error out of this is not a chart.
	if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err != nil {
		return linter, errLintNoChart
	}

	return lint.All(chartPath, vals, namespace, strict), nil
}
<commit_msg>fix(action): typo<commit_after>/*
Copyright The Helm 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 action

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"

	"helm.sh/helm/pkg/chartutil"
	"helm.sh/helm/pkg/lint"
	"helm.sh/helm/pkg/lint/support"
)

var errLintNoChart = errors.New("no chart found for linting (missing Chart.yaml)")

// Lint is the action for checking that the semantics of a chart are well-formed.
//
// It provides the implementation of 'helm lint'.
type Lint struct {
	Strict    bool
	Namespace string
}

type LintResult struct {
	TotalChartsLinted int
	Messages          []support.Message
	Errors            []error
}

// NewLint creates a new Lint object with the given configuration.
func NewLint() *Lint {
	return &Lint{}
}

// Run executes 'helm Lint' against the given chart.
func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
	lowestTolerance := support.ErrorSev
	if l.Strict {
		lowestTolerance = support.WarningSev
	}

	result := &LintResult{}
	for _, path := range paths {
		linter, err := lintChart(path, vals, l.Namespace, l.Strict)
		if err != nil {
			if err == errLintNoChart {
				result.Errors = append(result.Errors, err)
			}
			if linter.HighestSeverity >= lowestTolerance {
				result.Errors = append(result.Errors, err)
			}
		} else {
			result.Messages = append(result.Messages, linter.Messages...)
			result.TotalChartsLinted++
			for _, msg := range linter.Messages {
				if msg.Severity == support.ErrorSev {
					result.Errors = append(result.Errors, msg.Err)
				}
			}
		}
	}
	return result
}

func lintChart(path string, vals map[string]interface{}, namespace string, strict bool) (support.Linter, error) {
	var chartPath string
	linter := support.Linter{}

	if strings.HasSuffix(path, ".tgz") {
		tempDir, err := ioutil.TempDir("", "helm-lint")
		if err != nil {
			return linter, err
		}
		defer os.RemoveAll(tempDir)

		file, err := os.Open(path)
		if err != nil {
			return linter, err
		}
		defer file.Close()

		if err = chartutil.Expand(tempDir, file); err != nil {
			return linter, err
		}

		lastHyphenIndex := strings.LastIndex(filepath.Base(path), "-")
		if lastHyphenIndex <= 0 {
			return linter, errors.Errorf("unable to parse chart archive %q, missing '-'", filepath.Base(path))
		}
		base := filepath.Base(path)[:lastHyphenIndex]
		chartPath = filepath.Join(tempDir, base)
	} else {
		chartPath = path
	}

	// Guard: Error out if this is not a chart.
	if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err != nil {
		return linter, errLintNoChart
	}

	return lint.All(chartPath, vals, namespace, strict), nil
}
<|endoftext|>


<commit_before>package healthcheck

import (
	"testing"

	"github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml"
	"k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"

	pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

func pointer[T any](s T) *T {
	return &s
}

type mockGPUDevice struct{}

func (gp *mockGPUDevice) parseMigDeviceUUID(UUID string) (string, uint, uint, error) {
	return UUID, 3173334309191009974, 1015241, nil
}

func TestCatchError(t *testing.T) {
	gp := mockGPUDevice{}
	device1 := v1beta1.Device{
		ID: "device1",
	}
	udevice1 := v1beta1.Device{
		ID:     "device1",
		Health: pluginapi.Unhealthy,
	}
	device2 := v1beta1.Device{
		ID: "device2",
	}
	udevice2 := v1beta1.Device{
		ID:     "device2",
		Health: pluginapi.Unhealthy,
	}
	tests := []struct {
		name             string
		event            nvml.Event
		hc               GPUHealthChecker
		wantErrorDevices []v1beta1.Device
	}{
		{
			name: "non-critical error",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             0,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "xid error not included ",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(88),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "catching xid 72",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{udevice1},
		},
		{
			name: "not catching xid 72",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
				},
				healthCriticalXid: map[uint64]bool{},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "catching all devices error",
			event: nvml.Event{
				UUID:              nil,
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(48),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{udevice1, udevice2},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tt.hc.health = make(chan v1beta1.Device, len(tt.hc.devices))
			tt.hc.catchError(tt.event, &gp)
			for _, d := range tt.wantErrorDevices {
				if len(tt.hc.health) == 0 {
					t.Errorf("Fewer error devices was caught than expected.")
				} else if gotErrorDevice := <-tt.hc.health; gotErrorDevice != d {
					t.Errorf("Error device was not caught. Got %v. Want %v",
						gotErrorDevice, d)
				}
			}
			if len(tt.hc.health) != 0 {
				t.Errorf("More error devices was caught than expected.")
			}
		})
	}
}
<commit_msg>adding unknown device test case<commit_after>package healthcheck

import (
	"testing"

	"github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml"
	"k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"

	pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

func pointer[T any](s T) *T {
	return &s
}

type mockGPUDevice struct{}

func (gp *mockGPUDevice) parseMigDeviceUUID(UUID string) (string, uint, uint, error) {
	return UUID, 3173334309191009974, 1015241, nil
}

func TestCatchError(t *testing.T) {
	gp := mockGPUDevice{}
	device1 := v1beta1.Device{
		ID: "device1",
	}
	udevice1 := v1beta1.Device{
		ID:     "device1",
		Health: pluginapi.Unhealthy,
	}
	device2 := v1beta1.Device{
		ID: "device2",
	}
	udevice2 := v1beta1.Device{
		ID:     "device2",
		Health: pluginapi.Unhealthy,
	}
	tests := []struct {
		name             string
		event            nvml.Event
		hc               GPUHealthChecker
		wantErrorDevices []v1beta1.Device
	}{
		{
			name: "non-critical error",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             0,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "xid error not included ",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(88),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
			        },
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "catching xid 72",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{udevice1},
		},
		{
                        name: "unknown device",
                        event: nvml.Event{
                                UUID:              pointer("GPU-f053fce6-90ae-037069703604"),
                                GpuInstanceId:     pointer(uint(3173334309191009974)),
                                ComputeInstanceId: pointer(uint(1015241)),
                                Etype:             nvml.XidCriticalError,
                                Edata:             uint64(72),
                        },
                        hc: GPUHealthChecker{
                                devices: map[string]v1beta1.Device{
                                        "device1": device1,
                                        "device2": device2,
                                },
                                nvmlDevices: map[string]*nvml.Device{
                                        "device1": {
                                                UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
                                        },
                                        "device2": {
                                                UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
                                        },
                                },
				healthCriticalXid: map[uint64]bool{
                                        72: true,
                                        48: true,
                                },
                        },
                        wantErrorDevices: []v1beta1.Device{},
                },
		{
			name: "not catching xid 72",
			event: nvml.Event{
				UUID:              pointer("GPU-f053fce6-851c-1235-90ae-037069703604"),
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(72),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
				},
				healthCriticalXid: map[uint64]bool{},
			},
			wantErrorDevices: []v1beta1.Device{},
		},
		{
			name: "catching all devices error",
			event: nvml.Event{
				UUID:              nil,
				GpuInstanceId:     pointer(uint(3173334309191009974)),
				ComputeInstanceId: pointer(uint(1015241)),
				Etype:             nvml.XidCriticalError,
				Edata:             uint64(48),
			},
			hc: GPUHealthChecker{
				devices: map[string]v1beta1.Device{
					"device1": device1,
					"device2": device2,
				},
				nvmlDevices: map[string]*nvml.Device{
					"device1": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703604",
					},
					"device2": {
						UUID: "GPU-f053fce6-851c-1235-90ae-037069703633",
					},
				},
				healthCriticalXid: map[uint64]bool{
					72: true,
					48: true,
				},
			},
			wantErrorDevices: []v1beta1.Device{udevice1, udevice2},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tt.hc.health = make(chan v1beta1.Device, len(tt.hc.devices))
			tt.hc.catchError(tt.event, &gp)
			for _, d := range tt.wantErrorDevices {
				if len(tt.hc.health) == 0 {
					t.Errorf("Fewer error devices was caught than expected.")
				} else if gotErrorDevice := <-tt.hc.health; gotErrorDevice != d {
					t.Errorf("Error device was not caught. Got %v. Want %v",
						gotErrorDevice, d)
				}
			}
			if len(tt.hc.health) != 0 {
				t.Errorf("More error devices was caught than expected.")
			}
		})
	}
}
<|endoftext|>