package irc

import (
	"bufio"
	"fmt"
	"os"
	"sync"
)

const (
	motdHeader = "- %s Message of the day - "
	motdFooter = "- End of /MOTD command"
)

var (
	motdOnce sync.Once
	motd     []string
)

// sendMOTD will send the message of the day to a relay.
func sendMOTD(state state, sink sink) {
	motdOnce.Do(func() { loadMOTD(state) })

	sendNumericTrailing(state, sink, replyMOTDStart,
		fmt.Sprintf(motdHeader, state.getConfig().Name))

	for _, line := range motd {
		sendNumericTrailing(state, sink, replyMOTD, "- "+line)
	}

	sendNumericTrailing(state, sink, replyEndOfMOTD, motdFooter)
}

func loadMOTD(state state) {
	motdFile := state.getConfig().MOTD
	if motdFile == "" || motd != nil {
		return
	}

	file, err := os.Open(motdFile)
	if err != nil {
		logf(warn, "Could not open MOTD: %v", err)
	}

	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	motd = make([]string, 0)
	for scanner.Scan() {
		motd = append(motd, scanner.Text())
	}

	file.Close()
}

package irc

import (
	"bufio"
	"fmt"
	"os"
	"sync"
)

const (
	motdHeader = "- %s Message of the day - "
	motdFooter = "- End of /MOTD command"
)

var (
	motdOnce sync.Once
	motd     []string
)

// sendMOTD will send the message of the day to a relay.
func sendMOTD(state state, sink sink) {
	motdOnce.Do(func() { loadMOTD(state) })

	sendNumericTrailing(state, sink, replyMOTDStart,
		fmt.Sprintf(motdHeader, state.getConfig().Name))

	for _, line := range motd {
		sendNumericTrailing(state, sink, replyMOTD, "- "+line)
	}

	sendNumericTrailing(state, sink, replyEndOfMOTD, motdFooter)
}

func loadMOTD(state state) {
	motdFile := state.getConfig().MOTD
	if motdFile == "" || motd != nil {
		return
	}

	file, err := os.Open(motdFile)
	if err != nil {
		logf(warn, "Could not open MOTD: %v", err)
		return
	}

	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	motd = make([]string, 0)
	for scanner.Scan() {
		motd = append(motd, scanner.Text())
	}

	file.Close()
}

Fix crash if no MOTD exists.


package auth

import (
	"net/http"
)

const CookieName = "ATC-Authorization"

type CookieSetHandler struct {
	Handler http.Handler
}

func (handler CookieSetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie(CookieName)
	if err == nil && r.Header.Get("Authorization") == "" {
		r.Header.Set("Authorization", cookie.Value)
	}

	handler.Handler.ServeHTTP(w, r)
}

Add X- headers for security


package main

import (
	"net"
	"os"
	"path/filepath"
	"testing"

	"github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/vault"
	"github.com/stretchr/testify/assert"
)

func setupVault(t *testing.T) (net.Listener, error) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)

	os.Setenv("VAULT_ADDR", addr)
	os.Setenv("VAULT_TOKEN", token)

	return ln, nil
}

func TestMainE(t *testing.T) {
	ln, err := setupVault(t)
	defer ln.Close()
	assert.Nil(t, err)

	assert.Nil(t, mainE())

	cwd, err := os.Getwd()
	assert.Nil(t, err)

	stat, err := os.Stat(filepath.Join(cwd, "passwd.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0644, stat.Mode())

	stat, err = os.Stat(filepath.Join(cwd, "shadow.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0000, stat.Mode())

	stat, err = os.Stat(filepath.Join(cwd, "group.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0644, stat.Mode())
}

package main

import (
	"net"
	"os"
	"path/filepath"
	"testing"

	"github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/vault"
	"github.com/stretchr/testify/assert"
)

func setupVault(t *testing.T) (net.Listener, error) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)

	os.Setenv("VAULT_ADDR", addr)
	os.Setenv("VAULT_TOKEN", token)

	return ln, nil
}

func TestMainE(t *testing.T) {
	ln, err := setupVault(t)
	assert.Nil(t, err)
	defer ln.Close()

	assert.Nil(t, mainE())

	cwd, err := os.Getwd()
	assert.Nil(t, err)

	stat, err := os.Stat(filepath.Join(cwd, "passwd.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0644, stat.Mode())

	stat, err = os.Stat(filepath.Join(cwd, "shadow.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0000, stat.Mode())

	stat, err = os.Stat(filepath.Join(cwd, "group.cache"))
	assert.Nil(t, err)
	assert.EqualValues(t, 0644, stat.Mode())
}

Check errors before deferring in tests


// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build windows

package sqlite3

/*
#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
#cgo windows,386 CFLAGS: -D_localtime32=localtime
#cgo LDFLAGS: -lmingwex -lmingw32
*/
import "C"

// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build windows

package sqlite3

/*
#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T
#cgo LDFLAGS: -lmingwex -lmingw32
*/
import "C"

Fix compile for old mingw32


package hdfsbackend

import "code.uber.internal/infra/kraken/lib/backend/hdfsbackend/webhdfs"

// Config defines configuration for all HDFS clients.
type Config struct {
	NameNodes     []string `yaml:"namenodes"`
	UserName      string   `yaml:"username"`
	RootDirectory string   `yaml:"root_directory"`

	// ListConcurrency is the number of threads used for listing.
	ListConcurrency int `yaml:"list_concurrency"`

	// NamePath identifies which namepath.Pather to use.
	NamePath string `yaml:"name_path"`

	// UploadDirectory is scratch space, relative to RootDirectory, used for
	// uploading files before moving them to content-addressable storage. Avoids
	// partial uploads corrupting the content-addressable storage space.
	UploadDirectory string `yaml:"upload_directory"`

	WebHDFS webhdfs.Config `yaml:"webhdfs"`

	// Enables test-only behavior.
	testing bool
}

func (c *Config) applyDefaults() {
	if c.RootDirectory == "" {
		c.RootDirectory = "/infra/dockerRegistry/"
	}
	if c.ListConcurrency == 0 {
		c.ListConcurrency = 4
	}
	if c.UploadDirectory == "" {
		c.UploadDirectory = "_uploads"
	}
}

package hdfsbackend

import "code.uber.internal/infra/kraken/lib/backend/hdfsbackend/webhdfs"

// Config defines configuration for all HDFS clients.
type Config struct {
	NameNodes     []string `yaml:"namenodes"`
	UserName      string   `yaml:"username"`
	RootDirectory string   `yaml:"root_directory"`

	// ListConcurrency is the number of threads used for listing.
	ListConcurrency int `yaml:"list_concurrency"`

	// NamePath identifies which namepath.Pather to use.
	NamePath string `yaml:"name_path"`

	// UploadDirectory is scratch space, relative to RootDirectory, used for
	// uploading files before moving them to content-addressable storage. Avoids
	// partial uploads corrupting the content-addressable storage space.
	UploadDirectory string `yaml:"upload_directory"`

	WebHDFS webhdfs.Config `yaml:"webhdfs"`

	// Enables test-only behavior.
	testing bool
}

func (c *Config) applyDefaults() {
	if c.RootDirectory == "" {
		c.RootDirectory = "/infra/dockerRegistry/"
	}
	if c.ListConcurrency == 0 {
		c.ListConcurrency = 16
	}
	if c.UploadDirectory == "" {
		c.UploadDirectory = "_uploads"
	}
}

Increase list concurrency to 16


package main

import (
	"log"
	"net/http"
	"os"
)

type Config struct {
	port                string
	allowedContentTypes string // uncompiled regex
}

func envOrDefault(key string, default_value string) string {
	env := os.Getenv(key)
	if env != "" {
		return env
	} else {
		return default_value
	}
}

func main() {
	config := Config{
		port:                os.Getenv("PORT"),
		allowedContentTypes: envOrDefault("ALLOWED_CONTENT_TYPE_REGEX", "^image/"),
	}
	proxy := newProxy(config)

	http.HandleFunc("/", proxy.handler)

	log.Println("Listening as front on port " + config.port + "...")
	err := http.ListenAndServe(":"+config.port, nil)
	if err != nil {
		log.Panic(err)
	}
}

package main

import (
	"log"
	"net/http"
	"os"
)

type Config struct {
	port                string
	allowedContentTypes string // uncompiled regex
}

func envOrDefault(key string, default_value string) string {
	env := os.Getenv(key)
	if env != "" {
		return env
	} else {
		return default_value
	}
}

func main() {
	config := Config{
		port:                os.Getenv("PORT"),
		allowedContentTypes: envOrDefault("ALLOWED_CONTENT_TYPE_REGEX", "^image/"),
	}
	proxy := newProxy(config)

	// Simply ok favicon requests
	http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})

	http.HandleFunc("/", proxy.handler)

	log.Println("Listening as front on port " + config.port + "...")
	err := http.ListenAndServe(":"+config.port, nil)
	if err != nil {
		log.Panic(err)
	}
}

Return ok for favicon requests


package twigo

func NewClient(account_sid, auth_token, number string) (*Client, error) {

	c := &Client{AccountSid:account_sid,AuthToken:auth_token,Number:number}
	return c, nil
}

func (c *Client) Text(msg_sms *SMS) (*TwilioResponse, *TwilioError) {

	resp, twil_err := Send(c, msg_sms)
	return resp, twil_err
}

func (c *Client) Call(msg_voice *Voice) (*TwilioResponse, *TwilioError) {

	resp, twil_err := Send(c, msg_voice)
	return resp, twil_err
}

package twigo

func NewClient(account_sid, auth_token, number string) (*Client, error) {

	c := &Client{AccountSid:account_sid,AuthToken:auth_token,Number:number}

	err := Validate(*c)

	if err != nil {
		return nil,err
	}

	return c, nil
}

func (c *Client) Text(msg_sms *SMS) (*TwilioResponse, *TwilioError, error) {

	err := Validate(*msg_sms)

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

	resp, twil_err := Send(c, msg_sms)
	return resp, twil_err, nil
}

func (c *Client) Call(msg_voice *Voice) (*TwilioResponse, *TwilioError, error) {

	err := Validate(*msg_voice)

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

	resp, twil_err := Send(c, msg_voice)
	return resp, twil_err, nil
}

Handle field validation for SMS, Client, and Voice types


// Copyright (c) 2015, Ben Morgan. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package alpm works with parts of Arch Linux packages.
package alpm

import "strings"

// PackageGlob is a glob that should only find packages.
const PackageGlob = "-*.pkg.tar*"

// HasDatabaseFormat returns true if the filename matches a pacman package
// format that we can do anything with.
//
// Currently, only the following formats are supported:
//	.db.tar.gz
//
func HasDatabaseFormat(filename string) bool {
	return strings.HasSuffix(filename, ".db.tar.gz")
}

// HasPackageFormat returns true if the filename matches a pacman package
// format that we can do anything with.
//
// Currently, only the following formats are supported:
//  .pkg.tar
//	.pkg.tar.xz
//	.pkg.tar.gz
//	.pkg.tar.bz2
//
func HasPackageFormat(filename string) bool {
	for _, ext := range []string{".pkg.tar", ".pkg.tar.xz", ".pkg.tar.gz", ".pkg.tar.bz2"} {
		if strings.HasSuffix(filename, ext) {
			return true
		}
	}
	return false
}

// Copyright (c) 2015, Ben Morgan. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package alpm works with parts of Arch Linux packages.
package alpm

import "strings"

// PackageGlob is a glob that should only find packages.
const PackageGlob = "-*.pkg.tar*"

// HasDatabaseFormat returns true if the filename matches a pacman package
// format that we can do anything with.
//
// Currently, only the following formats are supported:
//	.db.tar.gz
//
func HasDatabaseFormat(filename string) bool {
	return strings.HasSuffix(filename, ".db.tar.gz")
}

// HasPackageFormat returns true if the filename matches a pacman package
// format that we can do anything with.
//
// Currently, only the following formats are supported:
//	.pkg.tar
//	.pkg.tar.xz
//	.pkg.tar.gz
//	.pkg.tar.bz2
//	.pkg.tar.zst
//
func HasPackageFormat(filename string) bool {
	for _, ext := range []string{".pkg.tar", ".pkg.tar.xz", ".pkg.tar.gz", ".pkg.tar.bz2", ".pkg.tar.zst"} {
		if strings.HasSuffix(filename, ext) {
			return true
		}
	}
	return false
}

Add support for reading *.tar.zst package files


// +build linux

/*
Copyright 2015 Google Inc. All rights reserved.

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

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

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

package kubelet

import (
	"github.com/docker/libcontainer/selinux"
)

// getRootContext gets the SELinux context of the kubelet rootDir
// or returns an error.
func (kl *Kubelet) getRootDirContext() (string, error) {
	// If SELinux is not enabled, return an empty string
	if !selinux.SelinuxEnabled() {
		return "", nil
	}

	// Get the SELinux context of the rootDir.
	rootContext, err := selinux.Getfilecon(kl.getRootDir())
	if err != nil {
		return "", err
	}

	// There is a libcontainer bug where the null byte is not stripped from
	// the result of reading some selinux xattrs; strip it.
	//
	// TODO: remove when https://github.com/docker/libcontainer/issues/499
	// is fixed
	rootContext = rootContext[:len(rootContext)-1]

	return rootContext, nil
}

// +build linux

/*
Copyright 2015 Google Inc. All rights reserved.

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

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

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

package kubelet

import (
	"github.com/docker/libcontainer/selinux"
)

// getRootContext gets the SELinux context of the kubelet rootDir
// or returns an error.
func (kl *Kubelet) getRootDirContext() (string, error) {
	// If SELinux is not enabled, return an empty string
	if !selinux.SelinuxEnabled() {
		return "", nil
	}

	// Get the SELinux context of the rootDir.
	return selinux.Getfilecon(kl.getRootDir())
}

Remove workaround for libcontainer Getfilecon bug


package models

import (
	"labix.org/v2/mgo/bson"
)

type Group struct {
	Id                 bson.ObjectId            `bson:"_id" json:"-"`
	Body               string                   `bson:"body" json:"body"`
	Title              string                   `bson:"title" json:"title"`
	Slug               string                   `bson:"slug" json:"slug"`
	Privacy            string                   `bson:"privacy" json:"privacy"`
	Visibility         string                   `bson:"visibility" json:"visibility"`
	SocialApiChannelId string                   `bson:"socialApiChannelId" json:"socialApiChannelId"`
	Parent             []map[string]interface{} `bson:"parent" json:"parent"`
	Customize          map[string]interface{}   `bson:"customize" json:"customize"`
	Counts             map[string]interface{}   `bson:"counts" json:"counts"`
	Migration          string                   `bson:"migration,omitempty"`
}

package models

import (
	"labix.org/v2/mgo/bson"
)

type Group struct {
	Id                 bson.ObjectId            `bson:"_id" json:"-"`
	Body               string                   `bson:"body" json:"body"`
	Title              string                   `bson:"title" json:"title"`
	Slug               string                   `bson:"slug" json:"slug"`
	Privacy            string                   `bson:"privacy" json:"privacy"`
	Visibility         string                   `bson:"visibility" json:"visibility"`
	SocialApiChannelId string                   `bson:"socialApiChannelId" json:"socialApiChannelId"`
	Parent             []map[string]interface{} `bson:"parent" json:"parent"`
	Customize          map[string]interface{}   `bson:"customize" json:"customize"`
	Counts             map[string]interface{}   `bson:"counts" json:"counts"`
	Migration          string                   `bson:"migration,omitempty"`
	StackTemplate      []string                 `bson:"stackTemplates",omitempty`
}

Add StackTemplate field to Group mongo model


package build

import (
	"encoding/json"

	"github.com/nanobox-io/nanobox/models"
)

func DevPayload(appModel *models.App) string {
	rtn := map[string]interface{}{}
	rtn["env"] = appModel.Evars
	rtn["boxfile"] = appModel.DeployedBoxfile
	bytes, _ := json.Marshal(rtn)
	return string(bytes)
}

package build

import (
	"encoding/json"

	"github.com/nanobox-io/nanobox/models"
)

func DevPayload(appModel *models.App) string {
	// create an APP_IP evar
	evars := appModel.Evars
	evars["APP_IP"] = appModel.LocalIPs["env"]

	rtn := map[string]interface{}{}
	rtn["env"] = evars
	rtn["boxfile"] = appModel.DeployedBoxfile
	bytes, _ := json.Marshal(rtn)
	return string(bytes)
}

Add an app ip into the run container


package main

import (
	"flag"
	"fmt"
)

const CompareAndSwapUsage = `usage: etcdctl [etcd flags] compareAndSwap <key> <value> [testAndSet flags]
either prevValue or prevIndex needs to be given
special flags: --ttl to set a key with ttl
			   --prevValue to set the previous value
			   --prevIndex to set the previous index`

var (
	compareAndSwapFlag   = flag.NewFlagSet("testAndSet", flag.ExitOnError)
	compareAndSwapTtl    = compareAndSwapFlag.Uint64("ttl", 0, "ttl of the key")
	compareAndSwapPvalue = compareAndSwapFlag.String("prevValue", "", "previous value")
	compareAndSwapPindex = compareAndSwapFlag.Uint64("prevIndex", 0, "previous index")
)

func init() {
	// The minimum number of arguments is 3 because
	// there needs to be either pvalue or pindex
	registerCommand("compareAndSwap", CompareAndSwapUsage, 3, 6, compareAndSwap)
}

func compareAndSwap(args []string) error {
	key := args[0]
	value := args[1]
	compareAndSwapFlag.Parse(args[2:])
	resp, err := client.CompareAndSwap(key, value,
		*compareAndSwapTtl, *compareAndSwapPvalue, *compareAndSwapPindex)
	if debug {
		fmt.Println(<-curlChan)
	}
	if err != nil {
		return err
	}

	output(resp)
	return nil
}

package main

import (
	"flag"
	"fmt"
)

const CompareAndSwapUsage = `usage: etcdctl [etcd flags] compareAndSwap <key> <value> [testAndSet flags]
either prevvalue or previndex needs to be given
special flags: --ttl to set a key with ttl
			   --prevvalue to set the previous value
			   --previndex to set the previous index`

var (
	compareAndSwapFlag   = flag.NewFlagSet("testAndSet", flag.ExitOnError)
	compareAndSwapTtl    = compareAndSwapFlag.Uint64("ttl", 0, "ttl of the key")
	compareAndSwapPvalue = compareAndSwapFlag.String("prevvalue", "", "previous value")
	compareAndSwapPindex = compareAndSwapFlag.Uint64("previndex", 0, "previous index")
)

func init() {
	// The minimum number of arguments is 3 because
	// there needs to be either pvalue or pindex
	registerCommand("compareAndSwap", CompareAndSwapUsage, 3, 6, compareAndSwap)
}

func compareAndSwap(args []string) error {
	key := args[0]
	value := args[1]
	compareAndSwapFlag.Parse(args[2:])
	resp, err := client.CompareAndSwap(key, value,
		*compareAndSwapTtl, *compareAndSwapPvalue, *compareAndSwapPindex)
	if debug {
		fmt.Println(<-curlChan)
	}
	if err != nil {
		return err
	}

	output(resp)
	return nil
}

Change flag names to lower case


package upload

import "github.com/materials-commons/mcstore/pkg/app/flow"

type uploader struct {
	tracker *uploadTracker
}

func newUploader() *uploader {
	return &uploader{
		tracker: newUploadTracker(),
	}
}

func (u *uploader) processRequest(request *flow.Request) error {
	if err := request.Write(); err != nil {
		// write failed for some reason
		return err
	}

	if u.uploadDone(request) {
		u.assembleUpload(request)
	}
	return nil
}

func (u *uploader) uploadDone(request *flow.Request) bool {
	id := request.UploadID()
	count := u.tracker.increment(id)
	return count == request.FlowTotalChunks
}

func (u *uploader) assembleUpload(request *flow.Request) {
	assembler := newAssembler(request, u.tracker)
	assembler.launch()
}

type uploadFinisher struct {
	uploadID string
	tracker  *uploadTracker
}

func newUploadFinisher(uploadID string, tracker *uploadTracker) *uploadFinisher {
	return &uploadFinisher{
		uploadID: uploadID,
		tracker:  tracker,
	}
}

func (f *uploadFinisher) Finish() error {
	f.tracker.clear(f.uploadID)
	return nil
}

package upload

import "github.com/materials-commons/mcstore/pkg/app/flow"

type uploader struct {
	tracker *uploadTracker
	w       RequestWriter
}

func newUploader() *uploader {
	return &uploader{
		tracker: newUploadTracker(),
	}
}

func (u *uploader) processRequest(request *flow.Request) error {
	if err := u.w.Write(request); err != nil {
		// write failed for some reason
		return err
	}

	if u.uploadDone(request) {
		u.assembleUpload(request)
	}
	return nil
}

func (u *uploader) uploadDone(request *flow.Request) bool {
	id := request.UploadID()
	count := u.tracker.increment(id)
	return count == request.FlowTotalChunks
}

func (u *uploader) assembleUpload(request *flow.Request) {
	assembler := newAssembler(request, u.tracker)
	assembler.launch()
}

type uploadFinisher struct {
	uploadID string
	tracker  *uploadTracker
}

func newUploadFinisher(uploadID string, tracker *uploadTracker) *uploadFinisher {
	return &uploadFinisher{
		uploadID: uploadID,
		tracker:  tracker,
	}
}

func (f *uploadFinisher) Finish() error {
	f.tracker.clear(f.uploadID)
	return nil
}

Change to using a request writer interface.


README.mdpackage main

import (
	"github.com/stretchr/testify/assert"
	"testing"
	"github.com/michaelklishin/rabbit-hole"
	"reflect"
)

func TestGraphDefinition(t *testing.T){
	var rabbitmq RabbitMQPlugin

	graphdef := rabbitmq.GraphDefinition()
	if len(graphdef) != 2 {
		t.Error("GetTempfilename: %d should be 2", len(graphdef))
	}
}

func TestParse(t *testing.T){
	var rabbitmq RabbitMQPlugin

	var stub rabbithole.Overview
	stub.QueueTotals.Messages = 1
	stub.QueueTotals.MessagesReady = 2
	stub.QueueTotals.MessagesUnacknowledged = 3
	stub.MessageStats.PublishDetails.Rate = 4

	stat, err := rabbitmq.parseStats(stub)

	assert.Nil(t, err)
	assert.EqualValues(t, reflect.TypeOf(stat["messages"]).String(), "float64")
	assert.EqualValues(t, stat["messages"], 1)
	assert.EqualValues(t, reflect.TypeOf(stat["publish"]).String(), "float64")
	assert.EqualValues(t, stat["publish"], 4)
}

Fix test file first line


package client

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type Map struct {
	Node struct {
		ServerList string `json:"serverList"`
		LuxMap     string `json:"luxMap"`
	} `json:"nodes"`
}

func Connect(clusterURL string) (string, error) {

	resp, err := http.Get(clusterURL)
	if err != nil {
		return "", err
	}

	//Need to handle this in-case cluster manager dies
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	var nodes Map
	json.Unmarshal([]byte(string(body)), &nodes)
	vbmap := nodes.Node.LuxMap

	return vbmap, nil
}

package client

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type Map struct {
	Node struct {
		ServerList string `json:"serverList"`
		LuxMap     string `json:"luxMap"`
	} `json:"nodes"`
}

var nodeMap *Map

func RunClient(cluster string) {

	// update nodeMap every second
}

func GetMap() *Map {
	return nodeMap
}

func Connect(clusterURL string) (string, error) {

	resp, err := http.Get(clusterURL)
	if err != nil {
		return "", err
	}

	//Need to handle this in-case cluster manager dies
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	var nodes Map
	json.Unmarshal([]byte(string(body)), &nodes)
	vbmap := nodes.Node.LuxMap

	return vbmap, nil
}

Add interface defn to clusterClient


// +build !rel
package main

import (
	"fmt"
	"io/ioutil"
)

// Asset reads the file at the abs path given
func Asset(name string) ([]byte, error) {
	dat, err := ioutil.ReadFile(name)

	if err != nil {
		return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
	}

	return dat, nil
}

Add development bindata to override prod bindata


package main

import "fmt"

func main() {
	fmt.Println("BTSOOT - Copyright (C) 2016-2017 Paul Kramme")
}

package main

import "fmt"
import "flag"
import "encoding/json"
import "io/ioutil"

type location struct {
	Source string
	Dest string
	Name string
	More_special_settings bool
}

type config struct {
	Some_generell_settings bool
	Locations []location
}

func main() {
	fmt.Println("BTSOOT - Copyright (C) 2016-2017 Paul Kramme")

	verbose := flag.Bool("verbose", false, "Verbose output for better debugging or just to see whats going on. This can slow BTSOOT down.")
	create_config := flag.Bool("createconfig", false, "Creates a config, aborts any other command")
	add_new := flag.String("add", "", "Add new block")
	add_new_src := flag.String("src", "", "Add new source location, can only be used with -add")
	add_new_dest := flag.String("dest", "", "Add new destination, can only be used with -add")
	rm := flag.String("rm", "", "Remove a block from config")
	flag.Parse()

	if *create_config == true {
		createconfig()
	}

	var conf config
	configfile, err := ioutil.ReadFile("./config.json")
	if err != nil {
		panic(err)
	}
	err = fromjson(string(configfile), &conf)
	if err != nil {
		panic(err)
	}

	if *verbose == true {fmt.Println("Verbose printing activated.")}

	if *add_new != "" {
		var loc location
		loc.Name = *add_new
		if *add_new_src != "" {
			loc.Source = *add_new_src
		}
		if *add_new_dest != "" {
			loc.Dest = *add_new_dest
		}
		conf.Locations = append(conf.Locations, loc)
	}

	if *rm != "" {
		for n, location_iterr := range conf.Locations {
			if location_iterr.Name == *rm {
				// Removing an slice element without preserving order
				conf.Locations[n] = conf.Locations[len(conf.Locations)-1]
				conf.Locations = conf.Locations[:len(conf.Locations)-1]
			}
		}
	}
	// resulting_config, err := tojson(conf)
	resulting_config, err := json.MarshalIndent(conf, "", "    ")
	err = ioutil.WriteFile("./config.json", resulting_config, 0664)
	if err != nil {
		panic(err)
	}
}

func createconfig() {
	fmt.Println("CREATING CONFIG")
}

func fromjson(src string, v interface{}) error {
	return json.Unmarshal([]byte(src), v)
}

func tojson(v interface{}) ([]byte, error) {
	return json.Marshal(v)
}

Add config writer, add and rm


package nntp

import (
	"fmt"
	"io"
)

type Conn struct {
}

func (c *Conn) Write(p []byte) (int, error) {
	return 0, nil
}

func (c *Conn) Read(p []byte) (n int, err error) {
	return
}

func (c *Conn) do(format string, is ...interface{}) io.ReadCloser {
	cmd := fmt.Sprintf(format, is...)
	fmt.Fprintf(c, "%s\r\n", cmd)
	return nil
}

package nntp

import "fmt"

type Conn struct {
}

func (c *Conn) Write(p []byte) (int, error) {
	return 0, nil
}

func (c *Conn) Read(p []byte) (n int, err error) {
	return
}

func (c *Conn) Do(format string, is ...interface{}) *Reader {
	cmd := fmt.Sprintf(format, is...)
	fmt.Fprintf(c, "%s\r\n", cmd)
	return nil
}

Return a reader instead of interface


/*
Copyright 2016 The MITRE Corporation. All rights reserved.

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

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

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

package models

import "gopkg.in/mgo.v2/bson"

const (
	Deduplication = "deduplication"
	Query         = "query"
)

type RecordMatchContext struct {
	ID   bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`
	Meta *Meta         `bson:"meta,omitempty" json:"meta,omitempty"`
	// human-friendly name assoc. w/ this record matching context
	Name string `bson:"name,omitempty" json:"name,omitempty"`
	// descriptive remarks assoc. w/ this interface to the record match system
	Description string `bson:"description,omitempty" json:"description,omitempty"`
}

/*
Copyright 2016 The MITRE Corporation. All rights reserved.

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

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

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

package models

import "gopkg.in/mgo.v2/bson"

const (
	Deduplication = "deduplication"
	Query         = "query"
)

type RecordMatchContext struct {
	ID   bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`
	Meta *Meta         `bson:"meta,omitempty" json:"meta,omitempty"`
	// human-friendly name assoc. w/ this record matching context
	Name string `bson:"name,omitempty" json:"name,omitempty"`
	// descriptive remarks assoc. w/ this interface to the record match system
	Description string `bson:"description,omitempty" json:"description,omitempty"`
	// distinguishes bewteen different context types (e.g., benchmark, challenge)
	Type string `bson:"type,omitempty" json:"type,omitempty"`
}

Add Type field to RecordMatchContext


package main

import (
	"github.com/tscolari/docode/packages/docode"
	"github.com/tscolari/docode/packages/docodeconfig"

	"flag"
)

func main() {
	docodeFilePath := flag.String("config", "./DocodeFile", "ConfigFile to load")
	flag.Parse()

	fileConfig := docodeconfig.NewFromFile(*docodeFilePath)
	runner := docode.New(fileConfig)
	err := runner.Run()
	if err != nil {
		panic("ERROR: " + err.Error())
	}
}

package main

import (
	"github.com/tscolari/docode/packages/docode"
	"github.com/tscolari/docode/packages/docodeconfig"

	"flag"
)

func main() {
	docodeFilePath := flag.String("c", "./DocodeFile", "ConfigFile to load")
	argsConfig := fetchConfigFromArgs()

	flag.Parse()

	fileConfig := docodeconfig.NewFromFile(*docodeFilePath)
	config := docodeconfig.MergeConfigurations(argsConfig, fileConfig)
	runner := docode.New(config)
	err := runner.Run()
	if err != nil {
		panic("ERROR: " + err.Error())
	}
}

func fetchConfigFromArgs() docodeconfig.ArgsConfiguration {
	argsConfig := docodeconfig.ArgsConfiguration{}
	argsConfig.SSHKey = flag.String("k", "", "Ssh key path to use")

	return argsConfig
}

Add `-k` argument to set SSH-KEY on cli


package migrations

import (
	"github.com/GeertJohan/go.rice"
	"github.com/mattes/migrate"
	"github.com/pkg/errors"
	// Enable PostgreSQL driver for migration tool
	_ "github.com/mattes/migrate/database/postgres"
	// Enable File source for migration tool
	_ "github.com/mattes/migrate/source/file"
	// Enable go.rice source for migration tool
	"github.com/diyan/assimilator/migrations/source"
)

func UpgradeDB(databaseURL string) error {
	// TODO Who is responsible to run `create database sentry_ci` statement?
	box, err := rice.FindBox("postgres")
	if err != nil {
		return errors.Wrap(err, "can not find db migrations")
	}
	sourceDriver, err := source.WithInstance(box)
	if err != nil {
		return errors.Wrap(err, "can not init source driver for db migrations")
	}
	m, err := migrate.NewWithSourceInstance("go.rice", sourceDriver, databaseURL)
	if err != nil {
		return errors.Wrap(err, "failed to upgrade database schema")
	}
	if err := m.Up(); err != nil {
		return errors.Wrap(err, "failed to upgrade database schema")
	}
	return nil
}

package migrations

import (
	"github.com/diyan/assimilator/migrations/source"

	"github.com/GeertJohan/go.rice"
	"github.com/mattes/migrate"
	"github.com/pkg/errors"
	// Enable PostgreSQL driver for migration tool
	_ "github.com/mattes/migrate/database/postgres"
)

func UpgradeDB(databaseURL string) error {
	// TODO Who should run `create database sentry_ci` statement?
	box, err := rice.FindBox("postgres")
	if err != nil {
		return errors.Wrap(err, "can not find db migrations")
	}
	sourceDriver, err := source.WithInstance(box)
	if err != nil {
		return errors.Wrap(err, "can not init source driver for db migrations")
	}
	m, err := migrate.NewWithSourceInstance("go.rice", sourceDriver, databaseURL)
	if err != nil {
		return errors.Wrap(err, "failed to upgrade database schema")
	}
	if err := m.Up(); err != nil {
		return errors.Wrap(err, "failed to upgrade database schema")
	}
	return nil
}

Remove obsolete code from migration package


package main

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

func handler(w http.ResponseWriter, r *http.Request) {
  proc := sh("/usr/local/letsencrypt/letsencrypt.sh %s 2>&1", strings.Split(r.Header["Host"][0], ":")[0])
  fmt.Fprintln(w,proc.stdout)
}

func main() {
  http.HandleFunc("/.well-known/letsencrypt", handler)
  http.Handle("/", http.FileServer(http.Dir("/srv")))
  http.ListenAndServe(":8080", nil)
}

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
  proc := sh("/usr/local/letsencrypt/letsencrypt.sh %s 2>&1", strings.Split(r.Header["X-Forwarded-Host"][0], ":")[0])
  fmt.Fprintln(w,proc.stdout)
}

func main() {
  http.HandleFunc("/.well-known/letsencrypt", handler)
  http.Handle("/", http.FileServer(http.Dir("/srv")))
  http.ListenAndServe(":8080", nil)
}

Revert "Simplify config for LetsEncrypt."


package ipns

import (
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	"github.com/ipfs/go-ipfs/core"
	mdag "github.com/ipfs/go-ipfs/merkledag"
	nsys "github.com/ipfs/go-ipfs/namesys"
	ci "github.com/ipfs/go-ipfs/p2p/crypto"
	path "github.com/ipfs/go-ipfs/path"
	ft "github.com/ipfs/go-ipfs/unixfs"
)

// InitializeKeyspace sets the ipns record for the given key to
// point to an empty directory.
func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error {
	emptyDir := &mdag.Node{Data: ft.FolderPBData()}
	nodek, err := n.DAG.Add(emptyDir)
	if err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(n.Context())
	defer cancel()

	err = n.Pinning.Pin(ctx, emptyDir, false)
	if err != nil {
		return err
	}

	err = n.Pinning.Flush()
	if err != nil {
		return err
	}

	pub := nsys.NewRoutingPublisher(n.Routing)
	err = pub.Publish(n.Context(), key, path.FromKey(nodek))
	if err != nil {
		return err
	}

	return nil
}

package ipns

import (
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	"github.com/ipfs/go-ipfs/core"
	mdag "github.com/ipfs/go-ipfs/merkledag"
	nsys "github.com/ipfs/go-ipfs/namesys"
	ci "github.com/ipfs/go-ipfs/p2p/crypto"
	path "github.com/ipfs/go-ipfs/path"
	ft "github.com/ipfs/go-ipfs/unixfs"
)

// InitializeKeyspace sets the ipns record for the given key to
// point to an empty directory.
func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error {
	emptyDir := &mdag.Node{Data: ft.FolderPBData()}
	nodek, err := n.DAG.Add(emptyDir)
	if err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(n.Context())
	defer cancel()

	err = n.Pinning.Pin(ctx, emptyDir, false)
	if err != nil {
		return err
	}

	err = n.Pinning.Flush()
	if err != nil {
		return err
	}

	pub := nsys.NewRoutingPublisher(n.Routing)
	if err := pub.Publish(ctx, key, path.FromKey(nodek)); err != nil {
		return err
	}

	return nil
}

Fix ctx used in pub.Publish


package sqlego

import "testing"

func TestSelectStatement(t *testing.T) {
	node := Select("Users", []string{"id", "name", "email"})
	sql := node.Compile()
	if sql != "SELECT id,name,email FROM Users;" {
		t.Fatal(sql)
	}
}

package sqlego

import (
	s "strings"
	"testing"
)

func TestSelectStatement(t *testing.T) {
	node := Select("Users", []string{"id", "name", "email"})
	sql := node.Compile()
	if sql != "SELECT id,name,email FROM Users;" {
		t.Fatal(sql)
	}
}

func TestUpdateStatement(t *testing.T) {
	node := Update("Users", map[string]string{"id": "2", "name": "Bruce", "email": "bruce@example.com"})
	sql := node.Compile()
	if !s.Contains(sql, "UPDATE Users SET") && !s.Contains(sql, "id=2") && !s.Contains(sql, "name=Bruce") && !s.Contains(sql, "email=bruce@example.com") {
		t.Fatal(sql)
	}
}

Add basic UPDATE statement testing


package main

import "fmt"

func main() {
  fmt.Printf("Hello World\n")
}

package main

import "fmt"

func main() {
  str := "Hello World"
  fmt.Println(str)
}

Update hello world to include a variable


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

package signal

import (
	"syscall"
	"testing"
)

func TestSignal(t *testing.T) {
	// Send this process a SIGHUP.
	syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)

	if sig := (<-Incoming).(UnixSignal); sig != 1 {
		t.Error("signal was %v, want %v", sig, 1)
	}
}

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

package signal

import (
	"syscall"
	"testing"
)

func TestSignal(t *testing.T) {
	// Send this process a SIGHUP.
	syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)

	if sig := (<-Incoming).(UnixSignal); sig != 1 {
		t.Errorf("signal was %v, want %v", sig, 1)
	}
}

Use t.Errorf for formatted error output.


package middlewares

import (
	"github.com/xaviergodart/gydro/errors"
	"github.com/xaviergodart/gydro/models"
	"strconv"
	"net/http"
)

var (
	KeyParam string = "apikey"
)

func KeyAuth(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		keyget := r.URL.Query().Get(KeyParam)
		keyheader := r.Header.Get(KeyParam)
		var consumer *models.Consumer
		switch {
			case keyget == "" && keyheader == "":
				errors.NewHttpError(w, "ErrorApiKeyMandatory")
				return
			case keyget != "":
				consumer = models.FindConsumerByApiKey(keyget)
				if consumer == nil {
					errors.NewHttpError(w, "ErrorApiKeyInvalid")
					return
				}
			case keyheader != "":
				consumer = models.FindConsumerByApiKey(keyheader)
				if consumer == nil {
					errors.NewHttpError(w, "ErrorApiKeyInvalid")
					return
				}
		}
		r.Header.Set("X-Consumer-ID", strconv.Itoa(consumer.GetId()))
		r.Header.Set("X-Consumer-Custom-ID", consumer.CustomId)
		r.Header.Set("X-Consumer-Username", consumer.CustomId)
		next.ServeHTTP(w, r)
	})
}

package middlewares

import (
	"github.com/xaviergodart/gydro/errors"
	"github.com/xaviergodart/gydro/models"
	"strconv"
	"net/http"
)

var (
	KeyParam string = "apikey"
)

func KeyAuth(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		keyget := r.URL.Query().Get(KeyParam)
		keyheader := r.Header.Get(KeyParam)
		var consumer *models.Consumer
		switch {
			case keyget == "" && keyheader == "":
				errors.NewHttpError(w, "ErrorApiKeyMandatory")
				return
			case keyget != "":
				consumer = models.FindConsumerByApiKey(keyget)
				if consumer == nil {
					errors.NewHttpError(w, "ErrorApiKeyInvalid")
					return
				}
			case keyheader != "":
				consumer = models.FindConsumerByApiKey(keyheader)
				if consumer == nil {
					errors.NewHttpError(w, "ErrorApiKeyInvalid")
					return
				}
		}
		r.Header.Set("X-Consumer-ID", strconv.Itoa(consumer.GetId()))
		r.Header.Set("X-Consumer-Custom-ID", consumer.CustomId)
		r.Header.Set("X-Consumer-Username", consumer.Username)
		next.ServeHTTP(w, r)
	})
}

Fix wrong header for KeyAuth middleware


// Copyright 2015 Stanislav Nazarenko
//
// 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 ld

// JsonLdApi is the main interface to JSON-LD API.
// See http://www.w3.org/TR/json-ld-api/ for detailed description of this interface.
type JsonLdApi struct {
}

// NewJsonLdApi creates a new instance of JsonLdApi and initialises it
// with the given JsonLdOptions structure.
func NewJsonLdApi() *JsonLdApi {
	return &JsonLdApi{}
}

// Copyright 2015 Stanislav Nazarenko
//
// 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 ld

// JsonLdApi exposes internal functions used by JsonLdProcessor.
// See http://www.w3.org/TR/json-ld-api/ for detailed description of
// underlying algorithms
//
// Warning: using this interface directly is highly discouraged. Please use JsonLdProcessor instead.
type JsonLdApi struct {
}

// NewJsonLdApi creates a new instance of JsonLdApi.
func NewJsonLdApi() *JsonLdApi {
	return &JsonLdApi{}
}

Fix docstrings for JsonLdApi to avoid confusion


package main

import (
	"fmt"
	"time"
	"sync"
)

var wg sync.WaitGroup

func worker(id int, jobs <-chan int, results chan<- int) {
	for j := range jobs {
		if j == -1 {
			wg.Done()
			return
		}
		fmt.Println("worker", id, "processing job", j)
		time.Sleep(time.Second)
		results <- j * 2
	}
}

func printer(results <-chan int) {

	for r := range results {
		fmt.Println(r)
	}
}

func main() {
	jobs := make(chan int, 100)
	results := make(chan int, 100)
	// This starts up 3 workers, initially blocked
	// because there are no jobs yet.
	for w := 1; w <= 3; w++ {
		wg.Add(1)
		go worker(w, jobs, results)
	}

	go printer(results)
	// Here we send 9 `jobs` and then `close` that
	// channel to indicate that's all the work we have.
	for j := 1; j <= 9; j++ {
		jobs <- j
	}
	for w := 1; w <= 3; w++ {
		jobs <- -1
	}
	wg.Wait()
}

package main

import (
	"fmt"
	"time"
	"sync"
)

var wg sync.WaitGroup

func worker(id int, jobs <-chan int, results chan<- int) {
	for j := range jobs {
		if j == -1 {
			wg.Done()
			break
		}
		fmt.Println("worker", id, "processing job", j)
		time.Sleep(time.Second)
		results <- j * 2
	}
}

func printer(results <-chan int) {

	for r := range results {
		fmt.Println(r)
	}
}

func main() {
	jobs := make(chan int, 100)
	results := make(chan int, 100)
	// This starts up 3 workers, initially blocked
	// because there are no jobs yet.
	for w := 1; w <= 3; w++ {
		wg.Add(1)
		go worker(w, jobs, results)
	}

	go printer(results)
	// Here we send 9 `jobs` and then `close` that
	// channel to indicate that's all the work we have.
	for j := 1; j <= 9; j++ {
		jobs <- j
	}
	for w := 1; w <= 3; w++ {
		jobs <- -1
	}
	wg.Wait()
}

Remove fatal error in workers


package wait

import (
	"fmt"
	"time"

	"github.com/BytemarkHosting/bytemark-client/cmd/bytemark/app"
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
)

func VMPowerOff(c *app.Context, name lib.VirtualMachineName) (err error) {
	vm := brain.VirtualMachine{PowerOn: true}

	for vm.PowerOn {
		if !c.IsTest() {
			time.Sleep(5 * time.Second)
		}
		fmt.Fprint(c.App().Writer, ".")

		vm, err = c.Client().GetVirtualMachine(name)
		if err != nil {
			return
		}
	}
	return
}

package wait

import (
	"fmt"
	"time"

	"github.com/BytemarkHosting/bytemark-client/cmd/bytemark/app"
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
)

// VMPowerOff waits for the named virtual machine to power off before returning
// a nil error. This is done by frequently polling the brain for info about the
// VM. If any calls fail, the error is returned.
func VMPowerOff(c *app.Context, name lib.VirtualMachineName) (err error) {
	vm := brain.VirtualMachine{PowerOn: true}

	for vm.PowerOn {
		if !c.IsTest() {
			time.Sleep(5 * time.Second)
		}
		fmt.Fprint(c.App().Writer, ".")

		vm, err = c.Client().GetVirtualMachine(name)
		if err != nil {
			return
		}
	}
	return
}

Add documentation comment for wait.VMPowerOff


package client

import (
	"fmt"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
)

type CmdPing struct{}

func (v *CmdPing) Run() error {
	_, err := G.API.Post(libkb.APIArg{
		Endpoint: "ping",
		Args: libkb.HTTPArgs{
			"alice":   libkb.S{Val: "hi alice"},
			"bob":     libkb.I{Val: 1000},
			"charlie": libkb.B{Val: true},
		},
	})
	if err != nil {
		return err
	}
	_, err = G.API.Get(libkb.APIArg{Endpoint: "ping"})
	if err != nil {
		return err
	}
	G.Log.Info(fmt.Sprintf("API Server at %s is up", G.Env.GetServerURI()))
	return nil
}

func NewCmdPing(cl *libcmdline.CommandLine) cli.Command {
	return cli.Command{
		Name:  "ping",
		Usage: "ping the keybase API server",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&CmdPing{}, "ping", c)
		},
	}
}

func (v *CmdPing) ParseArgv(*cli.Context) error { return nil }

func (v *CmdPing) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config: true,
		API:    true,
	}
}

package client

import (
	"fmt"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
)

type CmdPing struct{}

func (v *CmdPing) Run() error {
	_, err := G.API.Post(libkb.APIArg{Endpoint: "ping"})
	if err != nil {
		return err
	}
	_, err = G.API.Get(libkb.APIArg{Endpoint: "ping"})
	if err != nil {
		return err
	}
	G.Log.Info(fmt.Sprintf("API Server at %s is up", G.Env.GetServerURI()))
	return nil
}

func NewCmdPing(cl *libcmdline.CommandLine) cli.Command {
	return cli.Command{
		Name:  "ping",
		Usage: "ping the keybase API server",
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&CmdPing{}, "ping", c)
		},
	}
}

func (v *CmdPing) ParseArgv(*cli.Context) error { return nil }

func (v *CmdPing) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config: true,
		API:    true,
	}
}

Remove unused args to ping endpoint


package main

import (
	"flag"
	"github.com/itsankoff/gotcha/server"
	"log"
)

func main() {
	config := server.NewConfig()
	flag.StringVar(&config.ListenHost, "host",
		"0.0.0.0:9000", "host to listen")

	flag.StringVar(&config.FileServerHost, "file_host",
		"http://0.0.0.0:9000", "host to server files")

	flag.StringVar(&config.FileServerPath, "file_path",
		"/", "query path to access files")

	flag.StringVar(&config.FileServerFolder, "file_folder",
		"./", "storage folder")

	flag.StringVar(&config.SSLKeyPath, "key_path",
		"", "path to ssl key")

	flag.StringVar(&config.SSLCertPath, "cert_path",
		"", "path to ssl cert")

	flag.Parse()
	args := flag.Args()
	if len(args) > 0 && args[0] == "--help" {
		flag.PrintDefaults()
		return
	}

	srv := server.New(config)
	wss := server.NewWebSocket(config)
	srv.AddTransport("127.0.0.1:9000", &wss)
	done := make(chan interface{})

	err := srv.Start(done)
	if err != nil {
		log.Fatal("Failed to start server")
	}
}

package main

import (
	"flag"
	"github.com/itsankoff/gotcha/server"
	"log"
)

func main() {
	config := server.NewConfig()
	flag.StringVar(&config.ListenHost, "host",
		"0.0.0.0:9000", "host to listen")

	flag.StringVar(&config.FileServerHost, "file_host",
		"http://0.0.0.0:9000", "host to server files")

	flag.StringVar(&config.FileServerPath, "file_path",
		"/", "query path to access files")

	flag.StringVar(&config.FileServerFolder, "file_folder",
		"./", "storage folder")

	flag.StringVar(&config.SSLKeyPath, "key_path",
		"", "path to ssl key")

	flag.StringVar(&config.SSLCertPath, "cert_path",
		"", "path to ssl cert")

	flag.Parse()

	srv := server.New(config)
	wss := server.NewWebSocket(config)
	srv.AddTransport("127.0.0.1:9000", &wss)
	done := make(chan interface{})

	err := srv.Start(done)
	if err != nil {
		log.Fatal("Failed to start server")
	}
}

Fix cmd arguments parsing for server


package config

import (
	"github.com/lxc/lxd/shared/api"
)

// Config represents the config of a backup that can be stored in a backup.yaml file (or embedded in index.yaml).
type Config struct {
	Container       *api.Instance                `yaml:"container,omitempty"` // Used by VM backups too.
	Snapshots       []*api.InstanceSnapshot      `yaml:"snapshots,omitempty"`
	Pool            *api.StoragePool             `yaml:"pool,omitempty"`
	Volume          *api.StorageVolume           `yaml:"volume,omitempty"`
	VolumeSnapshots []*api.StorageVolumeSnapshot `yaml:"volume_snapshots,omitempty"`
}

package config

import (
	"github.com/lxc/lxd/shared/api"
)

// Config represents the config of a backup that can be stored in a backup.yaml file (or embedded in index.yaml).
type Config struct {
	Container       *api.Instance                `yaml:"container,omitempty"` // Used by VM backups too.
	Snapshots       []*api.InstanceSnapshot      `yaml:"snapshots,omitempty"`
	Pool            *api.StoragePool             `yaml:"pool,omitempty"`
	Profiles        []*api.Profile               `yaml:"profiles,omitempty"`
	Volume          *api.StorageVolume           `yaml:"volume,omitempty"`
	VolumeSnapshots []*api.StorageVolumeSnapshot `yaml:"volume_snapshots,omitempty"`
}

Add Profiles field do Config struct


package geocodio

import "errors"

var (
	// ErrReverseGecodeMissingLatLng error when a lat/lng is not provided
	ErrReverseGecodeMissingLatLng = errors.New("Latitude and longitude must not be empty")
)

package geocodio

import "errors"

var (
	// ErrReverseGecodeMissingLatLng error when a lat/lng is not provided
	ErrReverseGecodeMissingLatLng = errors.New("Latitude and longitude must not be empty")
	ErrMissingApiKey              = errors.New("Missing or empty API key")
)

Add error for invalid API key


package prompt

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
)

// YkmanProvider runs ykman to generate a OATH-TOTP token from the Yubikey device
// To set up ykman, first run `ykman oath add`
func YkmanMfaProvider(mfaSerial string) (string, error) {
	yubikeyOathCredName := os.Getenv("YKMAN_OATH_CREDENTIAL_NAME")
	if yubikeyOathCredName == "" {
		yubikeyOathCredName = mfaSerial
	}

	log.Printf("Fetching MFA code using `ykman oath code --single %s`", yubikeyOathCredName)
	cmd := exec.Command("ykman", "oath", "code", "--single", yubikeyOathCredName)
	cmd.Stderr = os.Stderr

	out, err := cmd.Output()
	if err != nil {
		return "", fmt.Errorf("ykman: %w", err)
	}

	return strings.TrimSpace(string(out)), nil
}

func init() {
	Methods["ykman"] = YkmanMfaProvider
}

package prompt

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
)

// YkmanProvider runs ykman to generate a OATH-TOTP token from the Yubikey device
// To set up ykman, first run `ykman oath add`
func YkmanMfaProvider(mfaSerial string) (string, error) {
	args := []string{}

	yubikeyOathCredName := os.Getenv("YKMAN_OATH_CREDENTIAL_NAME")
	if yubikeyOathCredName == "" {
		yubikeyOathCredName = mfaSerial
	}

	// Get the serial number of the yubikey device to use.
	yubikeyDeviceSerial := os.Getenv("YKMAN_OATH_DEVICE_SERIAL")
	if yubikeyDeviceSerial != "" {
		// If the env var was set, extend args to support passing the serial.
		args = append(args, "--device", yubikeyDeviceSerial)
	}

	// Add the rest of the args as usual.
	args = append(args, "oath", "code", "--single", yubikeyOathCredName)

	log.Printf("Fetching MFA code using `ykman %s`", strings.Join(args, " "))
	cmd := exec.Command("ykman", args...)
	cmd.Stderr = os.Stderr

	out, err := cmd.Output()
	if err != nil {
		return "", fmt.Errorf("ykman: %w", err)
	}

	return strings.TrimSpace(string(out)), nil
}

func init() {
	Methods["ykman"] = YkmanMfaProvider
}

Set YKMAN_OATH_DEVICE_SERIAL to select Yubikey


package operations

import (
	"encoding/json"
	"time"

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

// List contains fields that represent parameters common to most list operations. List
// struct is not an operation in and of itself and cannot be used with client.Do directly.
// Use one of the predefined XXXList operations defined blow instead and supply List
// struct as the first field.
//
// See the Pagination and Lists documentation at https://www.omise.co/api-pagination for
// more information.
type List struct {
	Offset int            `json:"offset,omitempty"`
	Limit  int            `json:"limit,omitempty"`
	From   time.Time      `json:"-"`
	To     time.Time      `json:"-"`
	Order  omise.Ordering `json:"order,omitempty"`

	NullableFrom *time.Time `json:"from,omitempty"`
	NullableTo   *time.Time `json:"to,omitempty"`
}

type optionalFieldList List

// MarshalJSON List type
func (l List) MarshalJSON() ([]byte, error) {
	l.SetOptionalField()
	return json.Marshal(optionalFieldList(l))
}

func (l *List) SetOptionalField() {
	if !l.From.IsZero() {
		l.NullableFrom = &l.From
	}
	if !l.To.IsZero() {
		l.NullableTo = &l.To
	}
}

package operations

import (
	"encoding/json"
	"time"

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

// List contains fields that represent parameters common to most list operations. List
// struct is not an operation in and of itself and cannot be used with client.Do directly.
// Use one of the predefined XXXList operations defined blow instead and supply List
// struct as the first field.
//
// See the Pagination and Lists documentation at https://www.omise.co/api-pagination for
// more information.
type List struct {
	Offset int            `json:"offset,omitempty"`
	Limit  int            `json:"limit,omitempty"`
	From   time.Time      `json:"-"`
	To     time.Time      `json:"-"`
	Order  omise.Ordering `json:"order,omitempty"`
}

// MarshalJSON List type
func (l List) MarshalJSON() ([]byte, error) {
	type Alias List
	params := struct {
		Alias
		PFrom *time.Time `json:"from,omitempty"`
		PTo   *time.Time `json:"to,omitempty"`
	}{
		Alias: Alias(l),
	}
	if !l.From.IsZero() {
		params.PFrom = &l.From
	}
	if !l.To.IsZero() {
		params.PTo = &l.To
	}
	return json.Marshal(params)
}

Move custom struct for marshal json to MarshalJSON method


package forces

import "github.com/hAWKdv/go-gravity/vectors/vectors"

// KineticFriction force
type KineticFriction struct {
	mover     *vectors.Mover
	magnitude float64
}

// CreateKineticFriction creates a kinetic friction force
func CreateKineticFriction(mover *vectors.Mover) *KineticFriction {
	// NOTE(Georgi): Currently hardcoded
	coef := 0.02
	normalForce := 1.0

	return &KineticFriction{mover, coef * normalForce}
}

// GetForce returns the force vector of kinetic friction
func (kf *KineticFriction) GetForce() *vectors.Vector {
	friction := kf.mover.GetVelocity().Copy()
	friction.Multiply(-1)
	friction.Normalize()
	friction.Multiply(kf.magnitude)

	return friction
}

package forces

import "github.com/hAWKdv/go-gravity/vectors/vectors"

const (
	// NormalForce is the default normal force for the environment
	NormalForce = 1.0
	// FCoef is the friction coefficient
	FCoef = 0.02
)

// KineticFriction force
type KineticFriction struct {
	mover     *vectors.Mover
	magnitude float64
}

// CreateKineticFriction creates a kinetic friction force
func CreateKineticFriction(mover *vectors.Mover) *KineticFriction {
	return &KineticFriction{mover, FCoef * NormalForce}
}

// GetForce returns the force vector of kinetic friction
func (kf *KineticFriction) GetForce() *vectors.Vector {
	friction := kf.mover.GetVelocity().Copy()
	friction.Multiply(-1)
	friction.Normalize()
	friction.Multiply(kf.magnitude)

	return friction
}

Put hardcoded values in constants


package turtle

// Emojis maps a name to an Emoji
var Emojis = make(map[string]*Emoji)

func init() {
	for _, e := range emojis {
		Emojis[e.Name] = e
	}
}

// Search emojis by a name
func Search(s string) []*Emoji {
	return search(emojis, s)
}

// Keyword filters the emojis by a keyword
func Keyword(k string) []*Emoji {
	return keyword(emojis, k)
}

// Category filters the emojis by a category
func Category(c string) []*Emoji {
	return category(emojis, c)
}

package turtle

// Version of the turtle library
const Version = "v0.1.0-dev"

// Emojis maps a name to an Emoji
var Emojis = make(map[string]*Emoji)

func init() {
	for _, e := range emojis {
		Emojis[e.Name] = e
	}
}

// Search emojis by a name
func Search(s string) []*Emoji {
	return search(emojis, s)
}

// Keyword filters the emojis by a keyword
func Keyword(k string) []*Emoji {
	return keyword(emojis, k)
}

// Category filters the emojis by a category
func Category(c string) []*Emoji {
	return category(emojis, c)
}

Add version info to library


/**
* Node
*
* A Node data structure is the simplest data structure in CS. The idea is it's
* an object that stores a value and a reference to the next Node. We can do
* the following operations with a Node:
*
* - Create Node
* - Get Value
* - Get Next
* - Set Value
* - Set Next
*
* All operations can be performed in O(1) time. This means all methods do not
* rely on any other variables.
**/
package node

import ()

type Node struct {
	Value int
	Next  *Node
}

func NewNode(v int) *Node {
	return &Node{Value: v}
}

func (n *Node) GetValue() int {
	return n.Value
}

func (n *Node) SetValue(v int) {
	n.Value = v
}

func (n *Node) GetNext() *Node {
	return n.Next
}

func (n *Node) SetNext(m *Node) {
	n.Next = m
}

/**
* Node
*
* A Node data structure is the simplest data structure in CS. The idea is it's
* an object that stores a value and a reference to the next Node. We can do
* the following operations with a Node:
*
* - Create Node
* - Get Value
* - Get Next
* - Set Value
* - Set Next
*
* All operations can be performed in O(1) time. This means all methods do not
* rely on any other variables.
**/
package node

import ()

type Node struct {
	Value interface{}
	Next  *Node
}

func NewNode(v interface{}) *Node {
	return &Node{Value: v}
}

func (n *Node) GetValue() interface{} {
	return n.Value
}

func (n *Node) SetValue(v interface{}) {
	n.Value = v
}

func (n *Node) GetNext() *Node {
	return n.Next
}

func (n *Node) SetNext(m *Node) {
	n.Next = m
}

Make Node work with various data types rather than limit to just int


package docker_test

import (
	"testing"

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

var builderPath string

func TestDockerLifecycleBuilder(t *testing.T) {
	RegisterFailHandler(Fail)

	BeforeSuite(func() {
		var err error

		builderPath, err = gexec.Build("github.com/cloudfoundry-incubator/docker_app_lifecycle/builder")
		Expect(err).NotTo(HaveOccurred())
	})

	AfterSuite(func() {
		gexec.CleanupBuildArtifacts()
	})

	RunSpecs(t, "Docker-App-Lifecycle-Builder Suite")
}

package docker_test

import (
	"testing"

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

var builderPath string

func TestDockerLifecycleBuilder(t *testing.T) {
	RegisterFailHandler(Fail)

	BeforeSuite(func() {
		var err error

		builderPath, err = gexec.Build("code.cloudfoundry.org/dockerapplifecycle/builder")
		Expect(err).NotTo(HaveOccurred())
	})

	AfterSuite(func() {
		gexec.CleanupBuildArtifacts()
	})

	RunSpecs(t, "Docker-App-Lifecycle-Builder Suite")
}

Update and rename docker_app_lifecycle -> dockerapplifecycle


package tuntap

import (
	"os"
	"strings"
	"syscall"
	"unsafe"
)

func createInterface(file *os.File, ifPattern string, kind DevKind) (string, error) {
	var req ifReq
	req.Flags = 0
	copy(req.Name[:15], ifPattern)
	switch kind {
	case DevTun:
		req.Flags |= iffTun
	case DevTap:
		req.Flags |= iffTap
	default:
		panic("Unknown interface type")
	}
	fd := file.Fd()
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))

	//  calling File.Fd() changes file to be blocking, so we change it back so it continues to play well with the go runtime
	syscall.SetNonblock(int(fd), true)

	if err != 0 {
		return "", err
	}
	return strings.TrimRight(string(req.Name[:]), "\x00"), nil
}

package tuntap

import (
	"os"
	"strings"
	"syscall"
	"unsafe"
)

func createInterface(file *os.File, ifPattern string, kind DevKind) (string, error) {
	var req ifReq
	req.Flags = 0
	copy(req.Name[:15], ifPattern)
	switch kind {
	case DevTun:
		req.Flags |= iffTun
	case DevTap:
		req.Flags |= iffTap
	default:
		panic("Unknown interface type")
	}
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
	if err != 0 {
		return "", err
	}
	return strings.TrimRight(string(req.Name[:]), "\x00"), nil
}

Revert "force fd back to non-block mode to make go 1.13 happier"


// Copyright 2014 Chadev. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"math/rand"

	"github.com/danryan/hal"
)

var tableFlipHandler = hal.Hear(listenName+` tableflip`, func(res *hal.Response) error {
	num := rand.Int()
	switch {
	case num%15 == 0:
		return res.Send(`the table flipped you! ノ┬─┬ノ ︵ ( \o°o)\`)
	case num%3 == 0:
		return res.Send("(ノಠ益ಠ)ノ彡┻━┻")
	case num%5 == 0:
		return res.Send("you set the table down ┬─┬ノ( º _ ºノ)")
	default:
		return res.Send(`(╯°□°）╯︵ ┻━┻`)
	}
})

// Copyright 2014 Chadev. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"math/rand"
	"time"

	"github.com/danryan/hal"
)

var tableFlipped bool

var tableFlipHandler = hal.Hear(listenName+` tableflip`, func(res *hal.Response) error {
	rand.Seed(time.Now().UTC().UnixNano())

	e := []string{
		"(ノಠ益ಠ)ノ彡┻━┻",
		`(╯°□°）╯︵ ┻━┻`,
		`the table flipped you! ノ┬─┬ノ ︵ ( \o°o)\`,
		"┻━┻ ︵ヽ(`Д´)ﾉ︵ ┻━┻",
	}

	return res.Send(e[rand.Intn(len(e))])
})

Change how random is done for tableflipping


package main

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

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hi there, I love %s!\n", r.URL.Path[1:])
}

func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hi there, I love %s!\n", r.URL.Path[1:])
}

func main() {
	log.Print("http server started")
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Print message when server is started


package twitch

import (
	"fmt"
	"time"
)

type Follow struct {
	CreatedAt     time.Time `json:"created_at"`
	Id            string    `json:"_id"`
	User          User      `json:"user"`
	Notifications bool      `json:"notifications"`
}

type FollowResponse struct {
	Total   int64    `json:"_total"`
	Follows []Follow `json:"follows"`
}

func (client *TwitchClient) GetChannelFollows(channel string, options *RequestOptions) FollowResponse {
	res := FollowResponse{}
	client.getRequest(fmt.Sprintf("/channels/%s/follows", channel), options, &res)
	return res
}

package twitch

import (
	"fmt"
	"net/url"
	"time"
)

type Follow struct {
	CreatedAt     time.Time `json:"created_at"`
	Id            string    `json:"_id"`
	User          User      `json:"user"`
	Notifications bool      `json:"notifications"`
}

type FollowResponse struct {
	Total   int64    `json:"_total"`
	Follows []Follow `json:"follows"`
}

func (client *TwitchClient) GetChannelFollows(channel string, options *RequestOptions) FollowResponse {
	res := FollowResponse{}
	client.getRequest(fmt.Sprintf("/channels/%s/follows", channel), options, &res)
	return res
}

type helixFollowResponse struct {
	Total   int64         `json:"total"`
	Follows []helixFollow `json:"data"`
}

type helixFollow struct {
	FromID     string    `json:"from_id"`
	FromName   string    `json:"from_name"`
	ToID       string    `json:"to_id"`
	ToName     string    `json:"to_name"`
	FollowedAt time.Time `json:"followed_at"`
}

// GetFollowersForID requests follower information for a user/channel ID.
func (client *TwitchClient) GetFollowersForID(userID string, options *RequestOptions) (helixFollowResponse, error) {
	options.Version = "helix"

	if options.Extra == nil {
		options.Extra = &url.Values{}
	}

	options.Extra.Add("to_id", userID)

	res := helixFollowResponse{}
	err := client.getRequest("/users/follows", options, &res)
	return res, err
}

Add GetFollowersForID request for Helix API


package dropsonde_unmarshaller_test

import (
	"time"

	"github.com/cloudfoundry/dropsonde/emitter/fake"
	"github.com/cloudfoundry/dropsonde/metric_sender"
	"github.com/cloudfoundry/dropsonde/metricbatcher"
	"github.com/cloudfoundry/dropsonde/metrics"

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

	"testing"
)

func TestUnmarshaller(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Dropsonde Unmarshaller Suite")
}

var fakeEventEmitter = fake.NewFakeEventEmitter("doppler")
var metricBatcher *metricbatcher.MetricBatcher

var _ = BeforeSuite(func() {
	sender := metric_sender.NewMetricSender(fakeEventEmitter)
	metricBatcher = metricbatcher.New(sender, 100*time.Millisecond)
	metrics.Initialize(sender, metricBatcher)
})

package dropsonde_unmarshaller_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

func TestUnmarshaller(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Dropsonde Unmarshaller Suite")
}

Remove dead sender/batchers from unmarshaller suite


package disallow

import (
	"net/http"

	"github.com/rancher/apiserver/pkg/types"
	"github.com/rancher/steve/pkg/attributes"
	schema2 "github.com/rancher/steve/pkg/schema"
	steve "github.com/rancher/steve/pkg/server"
)

var (
	allowPut = map[string]bool{
		"features": true,
		"settings": true,
	}
)

func Register(server *steve.Server) {
	server.SchemaFactory.AddTemplate(schema2.Template{
		Customize: func(schema *types.APISchema) {
			gr := attributes.GR(schema)
			if gr.Group == "management.cattle.io" || gr.Group == "project.cattle.io" {
				attributes.AddDisallowMethods(schema,
					http.MethodPost,
					http.MethodPatch,
					http.MethodDelete)
				if !allowPut[gr.Resource] {
					attributes.AddDisallowMethods(schema, http.MethodPut)
				}
			}
		},
	})
}

package disallow

import (
	"net/http"

	"github.com/rancher/apiserver/pkg/types"
	"github.com/rancher/steve/pkg/attributes"
	schema2 "github.com/rancher/steve/pkg/schema"
	steve "github.com/rancher/steve/pkg/server"
)

var (
	allowPost = map[string]bool{
		"settings": true,
	}
	allowPut = map[string]bool{
		"features": true,
		"settings": true,
	}
)

func Register(server *steve.Server) {
	server.SchemaFactory.AddTemplate(schema2.Template{
		Customize: func(schema *types.APISchema) {
			gr := attributes.GR(schema)
			if gr.Group == "management.cattle.io" || gr.Group == "project.cattle.io" {
				attributes.AddDisallowMethods(schema,
					http.MethodPatch,
					http.MethodDelete)
				if !allowPut[gr.Resource] {
					attributes.AddDisallowMethods(schema, http.MethodPut)
				}
				if !allowPut[gr.Resource] {
					attributes.AddDisallowMethods(schema, http.MethodPost)
				}
			}
		},
	})
}

Allow POST on settings too


/*
Copyright 2021 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 kubecross

import "sigs.k8s.io/release-utils/http"

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
//counterfeiter:generate . impl
type impl interface {
	GetURLResponse(url string, trim bool) (string, error)
}

type defaultImpl struct{}

func (*defaultImpl) GetURLResponse(url string, trim bool) (string, error) {
	return http.GetURLResponse(url, trim)
}

/*
Copyright 2021 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 kubecross

import (
	"bytes"

	"sigs.k8s.io/release-utils/http"
)

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
//counterfeiter:generate . impl
type impl interface {
	GetURLResponse(url string, trim bool) (string, error)
}

type defaultImpl struct{}

func (*defaultImpl) GetURLResponse(url string, trim bool) (string, error) {
	content, err := http.NewAgent().Get(url)
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(content)), nil
}

Use http agent for kubecross version retrieval


package db

import (
	"testing"
	"time"

	"github.com/octavore/ketchup/proto/ketchup/models"
)

func TestSort(t *testing.T) {
	now := time.Now()
	nowUnix := now.Unix()
	nowPlus1 := now.Add(time.Minute).Unix()
	nowPlus2 := now.Add(time.Minute * 2).Unix()
	pages := []*models.Page{
		{Timestamps: &models.Timestamp{UpdatedAt: &nowUnix}},
		{Timestamps: &models.Timestamp{UpdatedAt: &nowPlus2}},
		{Timestamps: &models.Timestamp{UpdatedAt: &nowPlus1}},
	}

	SortPagesByUpdatedAt(pages, true)
	expected := []int64{nowUnix, nowPlus1, nowPlus2}
	for i, n := range expected {
		ps := pages[i].GetTimestamps().GetUpdatedAt()
		if ps != n {
			t.Fatalf("expected %v but got %v at %v", n, ps, i)
		}
	}

	SortPagesByUpdatedAt(pages, false)
	expected = []int64{nowPlus2, nowPlus1, nowUnix}
	for i, n := range expected {
		ps := pages[i].GetTimestamps().GetUpdatedAt()
		if ps != n {
			t.Fatalf("expected %v but got %v at %v", n, ps, i)
		}
	}
}

package db

import (
	"testing"
	"time"

	"github.com/octavore/ketchup/proto/ketchup/models"
)

func TestSort(t *testing.T) {
	now := time.Now()
	nowUnix := now.UnixNano() / 1e6
	nowPlus1 := now.Add(time.Minute).UnixNano() / 1e6
	nowPlus2 := now.Add(time.Minute*2).UnixNano() / 1e6
	pages := []*models.Page{
		{Timestamps: &models.Timestamp{UpdatedAt: &nowUnix}},
		{Timestamps: &models.Timestamp{UpdatedAt: &nowPlus2}},
		{Timestamps: &models.Timestamp{UpdatedAt: &nowPlus1}},
	}

	SortPagesByUpdatedAt(pages, true)
	expected := []int64{nowUnix, nowPlus1, nowPlus2}
	for i, n := range expected {
		ps := pages[i].GetTimestamps().GetUpdatedAt()
		if ps != n {
			t.Fatalf("expected %v but got %v at %v", n, ps, i)
		}
	}

	SortPagesByUpdatedAt(pages, false)
	expected = []int64{nowPlus2, nowPlus1, nowUnix}
	for i, n := range expected {
		ps := pages[i].GetTimestamps().GetUpdatedAt()
		if ps != n {
			t.Fatalf("expected %v but got %v at %v", n, ps, i)
		}
	}
}

Change sort test to use time in millis.


package main

import (
	"reflect"
	"testing"
)

var ParseKeysListTests = []struct {
	list string
	keys []string
}{
	// normal
	{`host`, []string{`host`}},
	{`host,status`, []string{`host`, `status`}},
	{`host,status,size`, []string{`host`, `status`, `size`}},
}

func TestParseKeysList(t *testing.T) {
	for _, test := range ParseKeysListTests {
		expect := test.keys
		actual := ParseKeysList(test.list)
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf("ParseKeysList(%q) = %q, want %q",
				test.list, actual, expect)
		}
	}
}

package main

import (
	"reflect"
	"testing"
)

var ParseKeysListTests = []struct {
	list string
	keys []string
}{
	// normal
	{`host`, []string{`host`}},
	{`host,status`, []string{`host`, `status`}},
	{`host,status,size`, []string{`host`, `status`, `size`}},

	// include empty keys
	{``, []string{``}},
	{`,`, []string{``, ``}},
	{`,,`, []string{``, ``, ``}},
	{`,host`, []string{``, `host`}},
	{`,,host`, []string{``, ``, `host`}},
	{`host,`, []string{`host`, ``}},
	{`host,,`, []string{`host`, ``, ``}},
	{`,,host,,status,,`, []string{``, ``, `host`, ``, `status`, ``, ``}},
}

func TestParseKeysList(t *testing.T) {
	for _, test := range ParseKeysListTests {
		expect := test.keys
		actual := ParseKeysList(test.list)
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf("ParseKeysList(%q) = %q, want %q",
				test.list, actual, expect)
		}
	}
}

Add case that list includes empty keys


package main

import (
	"log"
	"os"

	"github.com/joho/godotenv"
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
)

func init() {
	err := godotenv.Load()
	if err != nil {
		log.Fatal("Error loading .env file")
	}
}

func main() {

	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(middleware.CORS())

	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"http://localhost:8100/"},
	}))

	e.POST("/qoutes/", CreateQoute)
	e.GET("/qoutes/", GetAllQoutes)
	e.GET("/qoutes/by/:status", GetQoutesByStatus)
	e.GET("/qoutes/:id", GetQoute)
	e.PUT("/qoutes/:id", UpdateQoute)
	e.PUT("/qoutes/:id/:status", UpdateStatus)
	e.DELETE("/qoutes/:id", DeleteQoute)
	log.Print("Server listing on port", os.Getenv("PORT"))
	e.Run(standard.New(os.Getenv("PORT")))

}

package main

import (
	"log"
	"os"

	"github.com/joho/godotenv"
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
)

func init() {
	err := godotenv.Load()
	if err != nil {
		log.Fatal("Error loading .env file")
	}
}

func main() {

	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(middleware.CORS())

	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*", "http://192.168.43.108:8100/"},
	}))

	e.POST("/qoutes/", CreateQoute)
	e.GET("/qoutes/", GetAllQoutes)
	e.GET("/qoutes/by/:status", GetQoutesByStatus)
	e.GET("/qoutes/:id", GetQoute)
	e.PUT("/qoutes/:id", UpdateQoute)
	e.PUT("/qoutes/:id/:status", UpdateStatus)
	e.DELETE("/qoutes/:id", DeleteQoute)
	log.Print("Server listing on port", os.Getenv("PORT"))
	e.Run(standard.New(os.Getenv("PORT")))

}

Add IP address of requested client


// +build builtin_assets

package main

import (
	"context"
	"net/http"
	"path"
	"strings"
)

func (w *httpWorker) httpHandleAsset(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	var (
		isDefault bool
		ct        string
	)

	// Stop handling assets if frontend is disabled
	if !w.service.config.Frontend.Enabled {
		rw.WriteHeader(http.StatusForbidden)
		return
	}

	// Get file data from built-in assets
	filePath := strings.TrimPrefix(r.URL.Path, w.service.config.RootPath+"/assets/")
	if strings.HasSuffix(filePath, "/") || filepath.Ext(filePath) == "" {
		filePath = httpDefaultPath
	}

	if filePath == httpDefaultPath {
		isDefault = true
	}

	data, err := Asset(filePath)
	if err != nil {
		rw.WriteHeader(http.StatusNotFound)
		return
	}

	// Handle default file path
	if isDefault {
		w.httpServeDefault(rw, string(data))
		return
	}

	// Get asset content type
	switch path.Ext(filePath) {
	case ".css":
		ct = "text/css"

	case ".js":
		ct = "text/javascript"

	default:
		ct = http.DetectContentType(data)
	}

	rw.Header().Set("Content-Type", ct)
	rw.WriteHeader(http.StatusOK)
	rw.Write(data)
}

// +build builtin_assets

package main

import (
	"context"
	"net/http"
	"path"
	"path/filepath"
	"strings"
)

func (w *httpWorker) httpHandleAsset(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	var (
		isDefault bool
		ct        string
	)

	// Stop handling assets if frontend is disabled
	if !w.service.config.Frontend.Enabled {
		rw.WriteHeader(http.StatusForbidden)
		return
	}

	// Get file data from built-in assets
	filePath := strings.TrimPrefix(r.URL.Path, w.service.config.RootPath+"/assets/")
	if strings.HasSuffix(filePath, "/") || filepath.Ext(filePath) == "" {
		filePath = httpDefaultPath
	}

	if filePath == httpDefaultPath {
		isDefault = true
	}

	data, err := Asset(filePath)
	if err != nil {
		rw.WriteHeader(http.StatusNotFound)
		return
	}

	// Handle default file path
	if isDefault {
		w.httpServeDefault(rw, string(data))
		return
	}

	// Get asset content type
	switch path.Ext(filePath) {
	case ".css":
		ct = "text/css"

	case ".js":
		ct = "text/javascript"

	default:
		ct = http.DetectContentType(data)
	}

	rw.Header().Set("Content-Type", ct)
	rw.WriteHeader(http.StatusOK)
	rw.Write(data)
}

Fix missing import in 'builtin_asset' code


package main

import (
	ess "github.com/eris-ltd/erisdb/erisdb/erisdbss"
	"github.com/eris-ltd/erisdb/server"
	"os"
	"github.com/gin-gonic/gin"
)

func main() {
	gin.SetMode(gin.ReleaseMode)

	baseDir := os.Getenv("HOME") + "/.edbservers"
	ss := ess.NewServerServer(baseDir)
	proc := server.NewServeProcess(nil, ss)
	err := proc.Start()
	if err != nil {
		panic(err.Error())
	}
	<- proc.StopEventChannel()
	os.RemoveAll(baseDir)
}

package main

import (
	ess "github.com/eris-ltd/erisdb/erisdb/erisdbss"
	"github.com/eris-ltd/erisdb/server"
	"os"
	"github.com/gin-gonic/gin"
	"path"
)

func main() {
	gin.SetMode(gin.ReleaseMode)

	baseDir := path.Join(os.TempDir(), "/.edbservers")
	ss := ess.NewServerServer(baseDir)
	proc := server.NewServeProcess(nil, ss)
	err := proc.Start()
	if err != nil {
		panic(err.Error())
	}
	<- proc.StopEventChannel()
	os.RemoveAll(baseDir)
}

Change serverserver to use os temp dir as base


package logrus_papertrail

import (
	"net"
	"testing"

	"github.com/Sirupsen/logrus"
)

func TestWritingToUDP(t *testing.T) {
	log := logrus.New()
	port := 16661

	addr := net.UDPAddr{
		Port: port,
		IP:   net.ParseIP("127.0.0.1"),
	}

	c, err := net.ListenUDP("udp", &addr)
	if err != nil {
		t.Fatalf("ListenUDP failed: %v", err)
	}
	defer c.Close()

	hook, err := NewPapertrailHook("localhost", port, "test")
	if err != nil {
		t.Errorf("Unable to connect to local UDP server.")
	}

	log.Hooks.Add(hook)
	log.Info("Today was a good day.")

	var buf = make([]byte, 1500)
	n, _, err := c.ReadFromUDP(buf)

	if err != nil {
		t.Fatalf("Error reading data from local UDP server")
	}

	if n <= 0 {
		t.Errorf("Nothing written to local UDP server.")
	}
}

package logrus_papertrail

import (
	"fmt"
	"testing"

	"github.com/Sirupsen/logrus"
	"github.com/stvp/go-udp-testing"
)

func TestWritingToUDP(t *testing.T) {
	port := 16661
	udp.SetAddr(fmt.Sprintf(":%d", port))

	hook, err := NewPapertrailHook("localhost", port, "test")
	if err != nil {
		t.Errorf("Unable to connect to local UDP server.")
	}

	log := logrus.New()
	log.Hooks.Add(hook)

	udp.ShouldReceive(t, "foo", func() {
		log.Info("foo")
	})
}

Use third-party UDP testing library to tighten up test.


// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2016

// +build go1.12

package instamux

import (
	"net/http"

	"github.com/gorilla/mux"
	instana "github.com/instana/go-sensor"
)

// AddMiddleware instruments the mux.Router instance with Instana
func AddMiddleware(sensor *instana.Sensor, router *mux.Router) {
	router.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			pathTemplate, err := mux.CurrentRoute(r).GetPathTemplate()
			if err != nil {
				sensor.Logger().Debug("can not get path template from the route: ", err.Error())
				pathTemplate = ""
			}

			instana.TracingHandlerFunc(sensor, pathTemplate, func(writer http.ResponseWriter, request *http.Request) {
				next.ServeHTTP(writer, request)
			})(w, r)
		})
	})
}

// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2016

// +build go1.12

package instamux

import (
	"net/http"

	"github.com/gorilla/mux"
	instana "github.com/instana/go-sensor"
)

// AddMiddleware instruments the mux.Router instance with Instana
func AddMiddleware(sensor *instana.Sensor, router *mux.Router) {
	router.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			pathTemplate, err := mux.CurrentRoute(req).GetPathTemplate()
			if err != nil {
				sensor.Logger().Debug("can not get path template from the route: ", err)
				pathTemplate = ""
			}

			instana.TracingHandlerFunc(sensor, pathTemplate, func(w http.ResponseWriter, req *http.Request) {
				next.ServeHTTP(w, req)
			})(w, req)
		})
	})
}

Use consistent naming in gorilla/mux middleware


package main

import "fmt"

// START OMIT
type Pet interface { // HL
	Name() string        // HL
	FavoriteToy() string // HL
}

type Dog struct { // Implicitly a Pet because it fulfills the interface
	name        string
	favoriteToy string
}

func (d Dog) Name() string { // Value receiver
	return d.name
}
func (d *Dog) FavoriteToy() string { //Pointer receiver
	return d.favoriteToy
}

func PetAnimal(p Pet) { // HL
	fmt.Printf("You petted %s!\n", p.Name())
}

func main() {
	d := Dog{"Meeko", "🍖"}
	PetAnimal(d)
}

// END OMIT

package main

import "fmt"

// START OMIT
type Pet interface { // HL
	Name() string        // HL
	FavoriteToy() string // HL
}

type Dog struct { // Implicitly a Pet because it fulfills the interface
	name        string
	favoriteToy string
}

func (d Dog) Name() string { // Value receiver
	return d.name
}
func (d Dog) FavoriteToy() string { //Pointer receiver would start with (d *Dog)
	return d.favoriteToy
}

func PetAnimal(p Pet) { // HL
	fmt.Printf("You petted %s!\n", p.Name())
}

func main() {
	d := Dog{"Meeko", "🍖"}
	PetAnimal(d)
}

// END OMIT

Fix bug in short presentation


package game

import (
	"time"

	"github.com/Bredgren/geo"
)

type playerCameraTarget struct {
	g      *Game
	p      *player
	offset geo.Vec
	pos    geo.Vec
}

func newPlayerCameraTarget(g *Game, p *player, screenHeight int) *playerCameraTarget {
	return &playerCameraTarget{
		g:      g,
		p:      p,
		offset: geo.VecXY(0, -float64(screenHeight)*0.4),
		pos:    p.Pos(),
	}
}

func (ct *playerCameraTarget) update(dt time.Duration) {
	switch ct.g.state {
	case mainMenuState:
		ct.pos.Y = ct.offset.Y
	case playState:
		ct.pos = ct.p.Pos().Plus(ct.offset)
	}
}

func (ct *playerCameraTarget) Pos() geo.Vec {
	return ct.pos
}

package game

import (
	"math"
	"time"

	"github.com/Bredgren/geo"
)

type playerCameraTarget struct {
	g      *Game
	p      *player
	offset geo.Vec
	pos    geo.Vec
}

func newPlayerCameraTarget(g *Game, p *player, screenHeight int) *playerCameraTarget {
	return &playerCameraTarget{
		g:      g,
		p:      p,
		offset: geo.VecXY(0, -float64(screenHeight)*0.4),
		pos:    p.Pos(),
	}
}

func (ct *playerCameraTarget) update(dt time.Duration) {
	switch ct.g.state {
	case mainMenuState:
		ct.pos.Y = ct.offset.Y
	case playState:
		offset := ct.offset
		offset.Y = -math.Max(0, ct.p.Pos().Y-offset.Y)
		ct.pos = ct.p.Pos().Plus(offset)
	}
}

func (ct *playerCameraTarget) Pos() geo.Vec {
	return ct.pos
}

Fix camera offset when in the play state


package elasti_cache

import (
	"github.com/jagregory/cfval/constraints"
	. "github.com/jagregory/cfval/schema"
)

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html
func SubnetGroup() Resource {
	return Resource{
		AwsType: "AWS::ElastiCache::SubnetGroup",
		Properties: map[string]Schema{
			"Description": Schema{
				Type:     ValueString,
				Required: constraints.Always,
			},

			"SubnetIds": Schema{
				Type:     SubnetID,
				Required: constraints.Always,
				Array:    true,
			},
		},
	}
}

package elasti_cache

import (
	"github.com/jagregory/cfval/constraints"
	. "github.com/jagregory/cfval/schema"
)

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-subnetgroup.html
func SubnetGroup() Resource {
	return Resource{
		AwsType: "AWS::ElastiCache::SubnetGroup",

		// Name
		ReturnValue: Schema{
			Type: ValueString,
		},

		Properties: map[string]Schema{
			"Description": Schema{
				Type:     ValueString,
				Required: constraints.Always,
			},

			"SubnetIds": Schema{
				Type:     SubnetID,
				Required: constraints.Always,
				Array:    true,
			},
		},
	}
}

Fix return value of subnet group


package rel

type Windower interface {
	Over(Visitable) *OverNode
	Visitable
}

func windowPredicationOver(node Windower, visitable Visitable) *OverNode {
	return &OverNode{
		Left:  node,
		Right: visitable,
	}
}

package rel

type Windower interface {
	Over(Visitable) *OverNode
	Visitable
}

func windowPredicationOver(left Windower, right Visitable) *OverNode {
	return &OverNode{
		Left:  left,
		Right: right,
	}
}

Fix variable references in window predications


package utils

import (
	"os"
	"os/user"
)

/*GetUserHomeDir returns the home directory of the current user.
 */
func GetUserHomeDir() string {
	usr, err := user.Current()
	// If the current user cannot be reached, get the HOME environment variable
	if err != nil {
		return os.Getenv("$HOME")
	}
	return usr.HomeDir
}

/*GetLocalhost returns the localhost name of the current computer.
 *If there is an error, it returns a default string.
 */
func GetLocalhost() string {
	lhost, err := os.Hostname()
	if err != nil {
		return "DefaultHostname"
	}
	return lhost
}

package utils

import (
	"os"
	"os/user"
	"path/filepath"

	"github.com/k0pernicus/goyave/consts"
)

/*IsGitRepository returns if the path, given as an argument, is a git repository or not.
 *This function returns a boolean value: true if the pathdir pointed to a git repository, else false.
 */
func IsGitRepository(pathdir string) bool {
	if filepath.Base(pathdir) != consts.GitFileName {
		pathdir = filepath.Join(pathdir, consts.GitFileName)
	}
	file, err := os.Open(pathdir)
	if err != nil {
		return false
	}
	_, err = file.Stat()
	return !os.IsNotExist(err)
}

/*GetUserHomeDir returns the home directory of the current user.
 */
func GetUserHomeDir() string {
	usr, err := user.Current()
	// If the current user cannot be reached, get the HOME environment variable
	if err != nil {
		return os.Getenv("$HOME")
	}
	return usr.HomeDir
}

/*GetLocalhost returns the localhost name of the current computer.
 *If there is an error, it returns a default string.
 */
func GetLocalhost() string {
	lhost, err := os.Hostname()
	if err != nil {
		return "DefaultHostname"
	}
	return lhost
}

Add a new function to know if a pathdir represents the path of a git repository


package util

import "testing"

func TestIndent(t *testing.T) {
	i := Indent(4)
	if i != "    " {
		t.Errorf("Expected four(4) whitespaces, got %v", i)
	}
}

package util

import (
	"net/http"
	"testing"
)

func TestIndent(t *testing.T) {
	if i := Indent(4); i != "    " {
		t.Errorf("Expected four(4) whitespaces, got %v", i)
	}
}

func TestResponseError(t *testing.T) {
	r := &http.Response{
		StatusCode: 401,
	}

	m := make(map[string]interface{})
	if re := ResponseError(r, m); re == "" {
		t.Errorf("Expected error mesage, got %v", re)
	}

	r.StatusCode = 200
	if re := ResponseError(r, m); re != "" {
		t.Errorf("Expected empty mesage, got %v", re)
	}

	m["code"] = 100
	m["error"] = "error string"
	m["message"] = "error message"
	if re := ResponseError(r, m); re == "" {
		t.Errorf("Expected error mesage, got %v", re)
	}
}

Add more tests for util.


package fuse

func (ms *MountState) systemWrite(req *request, header []byte) Status {
	if req.flatDataSize() == 0 {
		_, err := ms.mountFile.Write(header)
		return ToStatus(err)
	}

	if req.fdData != nil {
		sz := req.flatDataSize()
		buf := ms.AllocOut(req, uint32(sz))
		req.flatData, req.status = req.fdData.Bytes(buf)
		header = req.serializeHeader(len(req.flatData))
	}

	_, err := Writev(int(ms.mountFile.Fd()), [][]byte{header, req.flatData})
	if req.readResult != nil {
		req.readResult.Done()
	}
	return ToStatus(err)
}

package fuse

import (
	"syscall"
)

func (ms *MountState) systemWrite(req *request, header []byte) Status {
	if req.flatDataSize() == 0 {
		_, err := syscall.Write(ms.mountFd, Write(header))
		return ToStatus(err)
	}

	if req.fdData != nil {
		sz := req.flatDataSize()
		buf := ms.AllocOut(req, uint32(sz))
		req.flatData, req.status = req.fdData.Bytes(buf)
		header = req.serializeHeader(len(req.flatData))
	}

	_, err := Writev(int(ms.mountFd), [][]byte{header, req.flatData})
	if req.readResult != nil {
		req.readResult.Done()
	}
	return ToStatus(err)
}

Use mountFd on darwin too.


package aliyunecs

const autoFdiskScript = `#/bin/bash
#fdisk ,formating and create the file system on /dev/xvdb or /dev/vdb
DISK_ATTACH_POINT="/dev/xvdb"
fdisk_fun()
{
fdisk -S 56 \$DISK_ATTACH_POINT << EOF
n
p
1

wq
EOF

sleep 5
mkfs.ext4 \${DISK_ATTACH_POINT}1
}

#config /etc/fstab and mount device
main()
{
  if [ -b "/dev/vdb" ]; then
    DISK_ATTACH_POINT="/dev/vdb"
  fi

  fdisk_fun
  flag=0
  if [ -d "/var/lib/docker" ];then
    flag=1
    service docker stop
    rm -fr /var/lib/docker
  fi
  mkdir /var/lib/docker
  echo "\${DISK_ATTACH_POINT}1    /var/lib/docker     ext4    defaults        0 0" >>/etc/fstab
  mount -a

  if [ \$flag==1 ]; then
    service docker start
  fi
}

main
df -h

`

package aliyunecs

const autoFdiskScript = `#/bin/bash
#fdisk ,formating and create the file system on /dev/xvdb or /dev/vdb
DISK_ATTACH_POINT="/dev/xvdb"
fdisk_fun()
{
fdisk -S 56 \$DISK_ATTACH_POINT << EOF
n
p
1

wq
EOF

sleep 5
mkfs.ext4 -i 8192 \${DISK_ATTACH_POINT}1
}

#config /etc/fstab and mount device
main()
{
  if [ -b "/dev/vdb" ]; then
    DISK_ATTACH_POINT="/dev/vdb"
  fi

  fdisk_fun
  flag=0
  if [ -d "/var/lib/docker" ];then
    flag=1
    service docker stop
    rm -fr /var/lib/docker
  fi
  mkdir /var/lib/docker
  echo "\${DISK_ATTACH_POINT}1    /var/lib/docker     ext4    defaults        0 0" >>/etc/fstab
  mount -a

  if [ \$flag==1 ]; then
    service docker start
  fi
}

main
df -h

`

Set bytes_per_inode to 8KB for data disk of unionfs


package core

type positionalParameters struct {
	parameters []string
	rest       string
}

func (ps positionalParameters) arity() int {
	n := len(ps.parameters)

	if ps.rest != "" {
		n++
	}

	return n
}

func (ps positionalParameters) bind(args *Arguments) ([]Value, Value) {
	vs := make([]Value, 0, ps.arity())

	for _, s := range ps.parameters {
		v := args.nextPositional()

		if v == nil {
			return nil, argumentError("positional argument, {} is missing", s)
		}

		vs = append(vs, v)
	}

	if ps.rest != "" {
		vs = append(vs, args.restPositionals())
	}

	return vs, nil
}

package core

type positionalParameters struct {
	parameters []string
	rest       string
}

func (ps positionalParameters) arity() int {
	n := len(ps.parameters)

	if ps.rest != "" {
		n++
	}

	return n
}

func (ps positionalParameters) bind(args *Arguments) ([]Value, Value) {
	vs := make([]Value, 0, ps.arity())

	for _, s := range ps.parameters {
		v := args.nextPositional()

		if v == nil {
			return nil, argumentError("positional argument, %s is missing", s)
		}

		vs = append(vs, v)
	}

	if ps.rest != "" {
		vs = append(vs, args.restPositionals())
	}

	return vs, nil
}

Fix format string passed to argumentError


package trash

import (
	"os"
	"path/filepath"
)

// TODO: Use better type than string.
func MoveToTrash(name string) error {
	name = filepath.Clean(name)
	home := os.Getenv("HOME")
	_, file := filepath.Split(name)
	target := filepath.Join(home, ".Trash", file)

	// TODO: If target name exists in Trash, come up with a unique one (perhaps append a timestamp) instead of overwriting.
	// TODO: Support OS X "Put Back". Figure out how it's done and do it.

	return os.Rename(name, target)
}

package trash

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

// TODO: Use better type than string.
func MoveToTrash(name string) error {
	name = filepath.Clean(name)
	home := os.Getenv("HOME")
	dir, file := filepath.Split(name)
	target := filepath.Join(home, ".Trash", file)

	// TODO: If target name exists in Trash, come up with a unique one (perhaps append a timestamp) instead of overwriting.
	// TODO: Support OS X "Put Back". Figure out how it's done and do it.

	err := os.Rename(name, target)
	if err != nil {
		return err
	}

	// If directory became empty, remove it (recursively up).
	for {
		/*// Ensure it's a directory, not file.
		if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
			break
		}*/
		// Ensure it's an empty directory.
		if dirEntries, err := ioutil.ReadDir(dir); err != nil || len(dirEntries) != 0 {
			break
		}

		// Remove directory if it's (now) empty.
		err := os.Remove(dir)
		if err != nil {
			break
		}

		dir, _ = filepath.Split(dir)
	}

	return nil
}

Make MoveToTrash() remove empty folders left behind, if any.


package options

import (
	"github.com/spf13/pflag"
)

type Config struct {
	Master     string
	KubeConfig string
}

func NewConfig() *Config {
	return &Config{
		Master:     "127.0.0.1:8080",
		KubeConfig: "",
	}
}

func (s *Config) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.Master, "master", "127.0.0.1:8080", "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	fs.StringVar(&s.KubeConfig, "kubeconfig", "", "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
}

package options

import (
	"github.com/spf13/pflag"
)

type Config struct {
	Master     string
	KubeConfig string
}

func NewConfig() *Config {
	return &Config{
		Master:     "",
		KubeConfig: "",
	}
}

func (s *Config) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	fs.StringVar(&s.KubeConfig, "kubeconfig", s.KubeConfig, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
}

Remove default value for --master flag.


package dockerit

import (
	"testing"

	"github.com/vdemeester/libkermit/docker"
)

func TestCreateSimple(t *testing.T) {
	setupTest(t)

	container, err := docker.Create("busybox")

	if err != nil {
		t.Fatalf("expected no error, got %v", err)
	}
	if container.ID == "" {
		t.Fatalf("expected a containerId, got nothing")
	}
}

func TestStartAndStop(t *testing.T) {
	setupTest(t)

	container, err := docker.Start("busybox")

	if err != nil {
		t.Fatalf("expected no error, got %v", err)
	}
	if container.ID == "" {
		t.Fatalf("expected a containerId, got nothing")
	}

	err = docker.Stop(container.ID)
	if err != nil {
		t.Fatal(err)
	}

}

package dockerit

import (
	"testing"

	"github.com/vdemeester/libkermit/docker"
)

func TestCreateSimple(t *testing.T) {
	setupTest(t)

	container, err := docker.Create("busybox")

	if err != nil {
		t.Fatalf("expected no error, got %v", err)
	}
	if container.ID == "" {
		t.Fatalf("expected a containerId, got nothing")
	}
	if container.Name != "/kermit_busybox" {
		t.Fatalf("expected kermit_busyboy as name, got %s", container.Name)
	}
}

func TestStartAndStop(t *testing.T) {
	setupTest(t)

	container, err := docker.Start("busybox")

	if err != nil {
		t.Fatalf("expected no error, got %v", err)
	}
	if container.ID == "" {
		t.Fatalf("expected a containerId, got nothing")
	}
	if container.Name != "/kermit_busybox" {
		t.Fatalf("expected kermit_busyboy as name, got %s", container.Name)
	}

	err = docker.Stop(container.ID)
	if err != nil {
		t.Fatal(err)
	}

}

Update integration tests a bit


package mysqlproto

import (
	"io"
)

type Conn struct {
	*Stream
	CapabilityFlags uint32
}

func Handshake(rw io.ReadWriteCloser, capabilityFlags uint32,
	username, password, database string,
	connectAttrs map[string]string) (Conn, error) {
	stream := NewStream(rw)
	handshakeV10, err := ReadHandshakeV10(stream)
	if err != nil {
		return Conn{}, err
	}

	flags := handshakeV10.CapabilityFlags & capabilityFlags

	res := HandshakeResponse41(
		flags,
		handshakeV10.CharacterSet,
		username,
		password,
		handshakeV10.AuthPluginData,
		database,
		handshakeV10.AuthPluginName,
		connectAttrs,
	)

	conn := Conn{
		stream,
		uint32(res[4]) | uint32(res[5])<<8 | uint32(res[6])<<12 | uint32(res[7])<<16,
	}

	if _, err = conn.Write(res); err != nil {
		return conn, err
	}

	packet, err := conn.NextPacket()
	if err != nil {
		return conn, err
	}

	if packet.Payload[0] == PACKET_OK {
		return conn, nil
	} else {
		return conn, parseError(packet.Payload, conn.CapabilityFlags)
	}
}

package mysqlproto

import (
	"io"
)

type Conn struct {
	*Stream
	CapabilityFlags uint32
}

func Handshake(rw io.ReadWriteCloser, capabilityFlags uint32,
	username, password, database string,
	connectAttrs map[string]string) (Conn, error) {
	stream := NewStream(rw)
	handshakeV10, err := ReadHandshakeV10(stream)
	if err != nil {
		return Conn{}, err
	}

	flags := handshakeV10.CapabilityFlags & capabilityFlags

	res := HandshakeResponse41(
		flags,
		handshakeV10.CharacterSet,
		username,
		password,
		handshakeV10.AuthPluginData,
		database,
		handshakeV10.AuthPluginName,
		connectAttrs,
	)

	conn := Conn{
		stream,
		uint32(res[4]) | uint32(res[5])<<8 | uint32(res[6])<<16 | uint32(res[7])<<24,
	}

	if _, err = conn.Write(res); err != nil {
		return conn, err
	}

	packet, err := conn.NextPacket()
	if err != nil {
		return conn, err
	}

	if packet.Payload[0] == PACKET_OK {
		return conn, nil
	} else {
		return conn, parseError(packet.Payload, conn.CapabilityFlags)
	}
}

Fix reading capability flags in Conn


package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
)

func grep(pattern string, infile *os.File) {
	scanner := bufio.NewScanner(infile)
	for scanner.Scan() {
		line := scanner.Text()
		matched, err := regexp.MatchString(pattern, line)
		if err != nil {
			panic(err)
		}
		if matched {
			fmt.Println(line)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

func main() {
	var pattern string
	var infile *os.File
	var err error

	switch count := len(os.Args); {
	case count > 2:
		pattern = os.Args[1]
		infile, err = os.Open(os.Args[2])
		if err != nil {
			panic(err)
		}
	case count > 1:
		infile = os.Stdin
	default:
		fmt.Println("usage: grep pattern [file]")
		os.Exit(1)
	}

	grep(pattern, infile)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
)

func grep(pattern string, infile *os.File) {
	scanner := bufio.NewScanner(infile)
	for scanner.Scan() {
		line := scanner.Text()
		matched, err := regexp.MatchString(pattern, line)
		if err != nil {
			panic(err)
		}
		if matched {
			fmt.Println(line)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

func main() {
	var pattern string
	var infile *os.File
	var err error

	switch count := len(os.Args); {
	case count > 2:
		pattern = os.Args[1]
		infile, err = os.Open(os.Args[2])
		if err != nil {
			panic(err)
		}
	case count > 1:
		infile = os.Stdin
	default:
		fmt.Fprintln(os.Stderr, "usage: grep pattern [file]")
		os.Exit(1)
	}

	grep(pattern, infile)
}

Use stderr to output an error