package slack

// Conversation is the foundation for IM and BaseGroupConversation
type conversation struct {
	ID                 string   `json:"id"`
	Created            JSONTime `json:"created"`
	IsOpen             bool     `json:"is_open"`
	LastRead           string   `json:"last_read,omitempty"`
	Latest             *Message `json:"latest,omitempty"`
	UnreadCount        int      `json:"unread_count,omitempty"`
	UnreadCountDisplay int      `json:"unread_count_display,omitempty"`
}

// GroupConversation is the foundation for Group and Channel
type groupConversation struct {
	conversation
	Name       string   `json:"name"`
	Creator    string   `json:"creator"`
	IsArchived bool     `json:"is_archived"`
	Members    []string `json:"members"`
	NumMembers int      `json:"num_members,omitempty"`
	Topic      Topic    `json:"topic"`
	Purpose    Purpose  `json:"purpose"`
}

// Topic contains information about the topic
type Topic struct {
	Value   string   `json:"value"`
	Creator string   `json:"creator"`
	LastSet JSONTime `json:"last_set"`
}

// Purpose contains information about the purpose
type Purpose struct {
	Value   string   `json:"value"`
	Creator string   `json:"creator"`
	LastSet JSONTime `json:"last_set"`
}

package slack

// Conversation is the foundation for IM and BaseGroupConversation
type conversation struct {
	ID                 string   `json:"id"`
	Created            JSONTime `json:"created"`
	IsOpen             bool     `json:"is_open"`
	LastRead           string   `json:"last_read,omitempty"`
	Latest             *Message `json:"latest,omitempty"`
	UnreadCount        int      `json:"unread_count,omitempty"`
	UnreadCountDisplay int      `json:"unread_count_display,omitempty"`
}

// GroupConversation is the foundation for Group and Channel
type groupConversation struct {
	conversation
	Name       string   `json:"name"`
	Creator    string   `json:"creator"`
	IsArchived bool     `json:"is_archived"`
	Members    []string `json:"members"`
	Topic      Topic    `json:"topic"`
	Purpose    Purpose  `json:"purpose"`
}

// Topic contains information about the topic
type Topic struct {
	Value   string   `json:"value"`
	Creator string   `json:"creator"`
	LastSet JSONTime `json:"last_set"`
}

// Purpose contains information about the purpose
type Purpose struct {
	Value   string   `json:"value"`
	Creator string   `json:"creator"`
	LastSet JSONTime `json:"last_set"`
}

Remove num_members as it's not exposed anymore


package randstr

import "testing"

func BenchmarkNew(b *testing.B) {
	for i := 0; i < b.N; i++ {
		New(50, ASCIIRunes)
	}
}

package randstr

import "testing"

func BenchmarkNewSmallSource(b *testing.B) {
	runes := ASCIIRunes
	for i := 0; i < b.N; i++ {
		New(50, runes)
	}
}

func BenchmarkNewLargeSource(b *testing.B) {
	runesLit := [9999999]rune{}
	runes := runesLit[:]
	for i := 0; i < b.N; i++ {
		New(50, runes)
	}
}

Add additional benchmarks with larges sources.


package similarity

import (
	"fmt"
	"github.com/mcroydon/goplayground/similarity"
)

func ExampleUse() {
	// Create a similarity engine
	sim := similarity.New()

	// Create some items
	critic1 := "critic1"
	critic2 := "critic2"
	rating1 := similarity.Item{"In a World", 3.5}
	rating2 := similarity.Item{"In a World", 2.0}
	rating3 := similarity.Item{"War Games", 4.5}
	rating4 := similarity.Item{"War Games", 3.0}

	// Add items to the similarity with a string key.
	// In this case we are using the critic's name.
	sim.Add(critic1, rating1)
	sim.Add(critic1, rating3)
	sim.Add(critic2, rating2)
	sim.Add(critic2, rating4)

	// Get similar keys (in this case critics) and the
	// rated items.
	results := sim.SimilarEuclidean("critic1", 5)

	// We can then retrieve the critic's name and similarity score.
	fmt.Println(results[0].Name)
	fmt.Println(results[0].Similarity)
	// Output:
	// critic2
	// 0.32037724101704074
}

package similarity

import (
	"fmt"
	"github.com/mcroydon/goplayground/similarity"
)

func Example() {
	// Create a similarity engine
	sim := similarity.New()

	// Create some items
	critic1 := "critic1"
	critic2 := "critic2"
	rating1 := similarity.Item{"In a World", 3.5}
	rating2 := similarity.Item{"In a World", 2.0}
	rating3 := similarity.Item{"War Games", 4.5}
	rating4 := similarity.Item{"War Games", 3.0}

	// Add items to the similarity with a string key.
	// In this case we are using the critic's name.
	sim.Add(critic1, rating1)
	sim.Add(critic1, rating3)
	sim.Add(critic2, rating2)
	sim.Add(critic2, rating4)

	// Get similar keys (in this case critics) and the
	// rated items.
	results := sim.SimilarEuclidean("critic1", 5)

	// We can then retrieve the critic's name and similarity score.
	fmt.Println(results[0].Name)
	fmt.Println(results[0].Similarity)
	// Output:
	// critic2
	// 0.32037724101704074
}

Use Example while there is a single example.


// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package audit

import (
	"gopkg.in/juju/charm.v6-unstable"
	"time"
)

// Operation represents the type of an entry.
type Operation string

const (
	// OpSetPerm represents the setting of ACLs on an entity.
	// Required fields: Entity, ACL
	OpSetPerm Operation = "set-perm"

	// OpSetPromulgated, OpSetPromulgated represent the promulgation on an entity.
	// Required fields: Entity
	OpSetPromulgate Operation = "set-promulgate"
	OpSetUnPromulgate Operation = "set-unpromulgate"
)

// ACL represents an access control list.
type ACL struct {
	Read  []string `json:"read,omitempty"`
	Write []string `json:"write,omitempty"`
}

// Entry represents an audit log entry.
type Entry struct {
	Time        time.Time        `json:"time"`
	User        string           `json:"user"`
	Op          Operation        `json:"op"`
	Entity      *charm.Reference `json:"entity,omitempty"`
	ACL         *ACL             `json:"acl,omitempty"`
}

// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package audit

import (
	"gopkg.in/juju/charm.v6-unstable"
	"time"
)

// Operation represents the type of an entry.
type Operation string

const (
	// OpSetPerm represents the setting of ACLs on an entity.
	// Required fields: Entity, ACL
	OpSetPerm Operation = "set-perm"

	// OpSetPromulgate, OpSetUnPromulgate represent the promulgation on an entity.
	// Required fields: Entity
	OpSetPromulgate Operation = "set-promulgate"
	OpSetUnPromulgate Operation = "set-unpromulgate"
)

// ACL represents an access control list.
type ACL struct {
	Read  []string `json:"read,omitempty"`
	Write []string `json:"write,omitempty"`
}

// Entry represents an audit log entry.
type Entry struct {
	Time        time.Time        `json:"time"`
	User        string           `json:"user"`
	Op          Operation        `json:"op"`
	Entity      *charm.Reference `json:"entity,omitempty"`
	ACL         *ACL             `json:"acl,omitempty"`
}

Use ops only instead of ops + boolean.


package cli

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.3.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""

package cli

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.3.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"

Tag with dev for builds


package buildbox

import "fmt"

// buildVersion can be overriden at compile time by using:
//
//  go run -ldflags "-X github.com/buildbox/agent/buildbox.buildVersion abc" *.go --version

var baseVersion string = "1.0-beta.6"
var buildVersion string = ""

func Version() string {
	if buildVersion != "" {
		return fmt.Sprintf("%s-%s", baseVersion, buildVersion)
	} else {
		return baseVersion
	}
}

package buildbox

import "fmt"

// buildVersion can be overriden at compile time by using:
//
//  go run -ldflags "-X github.com/buildbox/agent/buildbox.buildVersion abc" *.go --version

var baseVersion string = "1.0-beta.6"
var buildVersion string = ""

func Version() string {
	if buildVersion != "" {
		return fmt.Sprintf("%s.%s", baseVersion, buildVersion)
	} else {
		return baseVersion
	}
}

Switch to using a . for the buildVersion.


package slack

// https://api.slack.com/docs/attachments
// It is possible to create more richly-formatted messages using Attachments.
type AttachmentField struct {
	Title string `json:"title"`
	Value string `json:"value"`
	Short bool   `json:"short"`
}

type Attachment struct {
	Color    string `json:"color,omitempty"`
	Fallback string `json:"fallback"`

	AuthorName    string `json:"author_name,omitempty"`
	AuthorSubname string `json:"author_subname,omitempty"`
	AuthorLink    string `json:"author_link,omitempty"`
	AuthorIcon    string `json:"author_icon,omitempty"`

	Title     string `json:"title,omitempty"`
	TitleLink string `json:"title_link,omitempty"`
	Pretext   string `json:"pretext,omitempty"`
	Text      string `json:"text"`

	ImageURL string `json:"image_url,omitempty"`
	ThumbURL string `json:"thumb_url,omitempty"`

	Fields     []*AttachmentField `json:"fields,omitempty"`
	MarkdownIn []string           `json:"mrkdwn_in,omitempty"`
}

package slack

// https://api.slack.com/docs/attachments
// It is possible to create more richly-formatted messages using Attachments.
type AttachmentField struct {
	Title string `json:"title"`
	Value string `json:"value"`
	Short bool   `json:"short"`
}

type Attachment struct {
	Color    string `json:"color,omitempty"`
	Fallback string `json:"fallback"`

	AuthorName    string `json:"author_name,omitempty"`
	AuthorSubname string `json:"author_subname,omitempty"`
	AuthorLink    string `json:"author_link,omitempty"`
	AuthorIcon    string `json:"author_icon,omitempty"`

	Title     string `json:"title,omitempty"`
	TitleLink string `json:"title_link,omitempty"`
	Pretext   string `json:"pretext,omitempty"`
	Text      string `json:"text"`

	ImageURL string `json:"image_url,omitempty"`
	ThumbURL string `json:"thumb_url,omitempty"`

	Footer     string `json:"footer,omitempty"`
	FooterIcon string `json:"footer_icon,omitempty"`

	Fields     []*AttachmentField `json:"fields,omitempty"`
	MarkdownIn []string           `json:"mrkdwn_in,omitempty"`
}

Add footer fields to Attachment


/*
Package identity provides type that allows to authorize request
*/
package identity

import (
	"github.com/google/uuid"
)

// Identity data to be encode in auth token
type Identity struct {
	ID    uuid.UUID `json:"id"`
	Email string    `json:"email"`
	Roles []string  `json:"roles"`
}

// WithEmail returns a new Identity with given email value
func WithEmail(email string) (*Identity, error) {
	i, err := New()
	if err != nil {
		return nil, err
	}
	i.Email = email

	return i, nil
}

// WithValues returns a new Identity for given values
func WithValues(id uuid.UUID, email string, roles []string) *Identity {
	return &Identity{id, email, roles}
}

// New returns a new Identity
func New() (*Identity, error) {
	id, err := uuid.NewRandom()
	if err != nil {
		return nil, err
	}

	return &Identity{
		ID: id,
	}, nil
}

/*
Package identity provides type that allows to authorize request
*/
package identity

import (
	"github.com/google/uuid"
)

// Identity data to be encode in auth token
type Identity struct {
	ID    uuid.UUID `json:"id"`
	Email string    `json:"email"`
	Roles []string  `json:"roles"`
}

// WithEmail returns a new Identity with given email value
func WithEmail(email string) (*Identity, error) {
	i, err := New()
	if err != nil {
		return nil, err
	}

	i.Email = email

	return i, nil
}

// WithValues returns a new Identity for given values
func WithValues(id uuid.UUID, email string, roles []string) *Identity {
	return &Identity{id, email, roles}
}

// New returns a new Identity
func New() (*Identity, error) {
	id, err := uuid.NewRandom()

	return &Identity{
		ID: id,
	}, err
}

Remove some err checks, return it directly


package api

import (
	"errors"
	"fmt"
)

var ErrAudienceTooLong = errors.New("the API only supports at most one element in the audience")

type OidcToken struct {
	Token string `json:"token"`
}

func (c *Client) OidcToken(jobId string, audience ...string) (*OidcToken, *Response, error) {
	type oidcTokenRequest struct {
		Audience string `json:"audience"`
	}

	var m *oidcTokenRequest
	switch len(audience) {
	case 0:
		m = nil
	case 1:
		m = &oidcTokenRequest{Audience: audience[0]}
	default:
		return nil, nil, ErrAudienceTooLong
	}

	u := fmt.Sprintf("jobs/%s/oidc/tokens", jobId)
	req, err := c.newRequest("POST", u, m)
	if err != nil {
		return nil, nil, err
	}

	t := &OidcToken{}
	resp, err := c.doRequest(req, t)
	if err != nil {
		return nil, nil, err
	}

	return t, resp, err
}

package api

import (
	"errors"
	"fmt"
)

var ErrAudienceTooLong = errors.New("the API only supports at most one element in the audience")

type OidcToken struct {
	Token string `json:"token"`
}

func (c *Client) OidcToken(jobId string, audience ...string) (*OidcToken, *Response, error) {
	type oidcTokenRequest struct {
		Audience string `json:"audience"`
	}

	var m *oidcTokenRequest
	switch len(audience) {
	case 0:
		m = nil
	case 1:
		m = &oidcTokenRequest{Audience: audience[0]}
	default:
		// While the spec supports multiple audiences in an Id JWT, our API does
		// not support issuing them.
		// See: https://openid.net/specs/openid-connect-core-1_0.html#IDToken.
		return nil, nil, ErrAudienceTooLong
	}

	u := fmt.Sprintf("jobs/%s/oidc/tokens", jobId)
	req, err := c.newRequest("POST", u, m)
	if err != nil {
		return nil, nil, err
	}

	t := &OidcToken{}
	resp, err := c.doRequest(req, t)
	if err != nil {
		return nil, nil, err
	}

	return t, resp, err
}

Add a comment about audience


package main

import (
	"github.com/op/go-logging"
	"github.com/CaliDog/certstream-go"
)

var log = logging.MustGetLogger("example")

func main() {
	stream := certstream.CertStreamEventStream(false)

	for jq := range stream {

		message_type, err := jq.String("message_type")

		if err != nil {
			log.Fatalf("Error parsing message_type", err)
		}

		log.Info("Message type -> ", message_type)
		log.Info("recv: ", jq)

	}
}

package main

import (
	"github.com/CaliDog/certstream-go"
	logging "github.com/op/go-logging"
)

var log = logging.MustGetLogger("example")

func main() {
	stream := certstream.CertStreamEventStream(false)

	for jq := range stream {

		message_type, err := jq.String("message_type")

		if err != nil {
			log.Fatalf("Error parsing message_type", err)
		}

		log.Info("Message type -> ", message_type)
		log.Info("recv: ", jq)

	}
}

Add proper library prefix in example.


package response

import (
	"encoding/json"
	"time"
)

type Response interface {
	MakeATimestamp()
}

type baseResponse struct {
	Command   string
	Timestamp int64
}

func (r *baseResponse) MakeATimestamp() {
	r.Timestamp = time.Now().UnixNano() / 1e6
}

func Send(r Response, sender func([]byte)) error {
	r.MakeATimestamp()
	serialized, err := json.Marshal(r)
	if err == nil {
		sender(serialized)
	}
	return err
}

package response

import (
	"encoding/json"
	"time"
)

type Timestamp int64

type baseResponse struct {
	Command   string
	Timestamp Timestamp
}

func (t *Timestamp) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Now().UnixNano() / 1e6)
}

func Send(r interface{}, sender func([]byte)) error {
	serialized, err := json.Marshal(r)
	if err == nil {
		sender(serialized)
	}
	return err
}

Fix the marshaling of timestamp in response


package main

import (
	"fmt"
	"strconv"

	"github.com/blockfreight/blockfreight-alpha/blockfreight/bft/leveldb"
)

func main() {
	//db_path := "bft-db/db"
	db_path := "bft-db"
	db, err := leveldb.OpenDB(db_path)
	defer leveldb.CloseDB(db)
	leveldb.HandleError(err, "Create or Open Database")
	//fmt.Println("Database created / open on "+db_path)

	for i := 1; i <= 50000; i++ {
		err = leveldb.InsertBFTX(strconv.Itoa(i), "Value for "+strconv.Itoa(i), db)
		//leveldb.HandleError(err, "Insert data for value "+strconv.Itoa(i))
		//fmt.Println("Record saved!")
	}

	//Iteration
	var n int
	n, err = leveldb.Iterate(db)
	leveldb.HandleError(err, "Iteration")
	fmt.Println("Total: "+strconv.Itoa(n))
}

Move code to a db library


package integration_test

import (
	"io/ioutil"
	"os"
	"testing"

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

	bmtestutils "github.com/cloudfoundry/bosh-micro-cli/testutils"
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	BeforeSuite(func() {
		err := bmtestutils.BuildExecutable()
		Expect(err).NotTo(HaveOccurred())
	})

	var (
		homePath string
		oldHome  string
	)
	BeforeEach(func() {
		oldHome = os.Getenv("HOME")

		var err error
		homePath, err = ioutil.TempDir("", "micro-bosh-cli-integration")
		Expect(err).NotTo(HaveOccurred())

		err = os.Setenv("HOME", homePath)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.Setenv("HOME", oldHome)
		Expect(err).NotTo(HaveOccurred())

		err = os.RemoveAll(homePath)
		Expect(err).NotTo(HaveOccurred())
	})

	RunSpecs(t, "bosh-micro-cli Integration Suite")
}

package integration_test

import (
	"io/ioutil"
	"os"
	"testing"

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

	bmtestutils "github.com/cloudfoundry/bosh-micro-cli/testutils"
)

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	BeforeSuite(func() {
		err := bmtestutils.BuildExecutable()
		Expect(err).NotTo(HaveOccurred())
	})

	var (
		homePath string
		oldHome  string
	)
	BeforeEach(func() {
		oldHome = os.Getenv("HOME")

		var err error
		homePath, err = ioutil.TempDir("", "micro-bosh-cli-integration")
		Expect(err).NotTo(HaveOccurred())

		err = os.Setenv("HOME", homePath)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.Setenv("HOME", oldHome)
		Expect(err).NotTo(HaveOccurred())

		err = os.RemoveAll(homePath)
		Expect(err).NotTo(HaveOccurred())
	})

	RunSpecs(t, "Integration Suite")
}

Remove bosh-micro-cli from 'Integration Suite'


// Package vpki provides a layer of abstraction between the golang stdlib
// crypto primitives and common crypto uses (e.g. serving HTTPS) and the
// functionality provided by Vault. Internally, the library generates private
// keys locally and sends CSRs to the vault server, so that private keys are
// never transmitted.
package vpki // import "astuart.co/vpki"

Update import statement to only allow single source


package main

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

	"github.com/labstack/echo"
)

func (h *Handler) getGithubRepoHealth(c echo.Context) error {
	db := h.DB.Clone()
	defer db.Close()

	owner := c.Param("owner")
	repo := c.Param("repo")
	queryParams := c.QueryParams()

	health := &Health{
		RepositoryName: fmt.Sprintf("%s/%s", owner, repo),
		RepositoryURL:  fmt.Sprintf("github.com/%s/%s", owner, repo),
		Timestamp:      time.Now(),
	}

	for queryKey, queryValues := range queryParams {
		switch queryKey {
		case "indicators":
			fmt.Println(queryValues)
		}
	}

	return c.JSON(http.StatusOK, health)
}

func (h *Handler) getIndicators(c echo.Context) error {
	db := h.DB.Clone()
	defer db.Close()

	i := db.DB("healthyrepo").C("indicators")

	result := []Indicator{}

	err := i.Find(nil).All(&result)
	if err != nil {
		log.Fatal(err)
	}

	return c.JSON(http.StatusOK, result)
}

package main

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

	"github.com/labstack/echo"
)

func (h *Handler) getGithubRepoHealth(c echo.Context) error {
	db := h.DB.Clone()
	defer db.Close()

	owner := c.Param("owner")
	repo := c.Param("repo")
	queryParams := c.QueryParams()

	health := &Health{
		RepositoryName: fmt.Sprintf("%s/%s", owner, repo),
		RepositoryURL:  fmt.Sprintf("https://github.com/%s/%s", owner, repo),
		Timestamp:      time.Now(),
	}

	for queryKey, queryValues := range queryParams {
		switch queryKey {
		case "indicators":
			fmt.Println(queryValues)
		}
	}

	return c.JSON(http.StatusOK, health)
}

func (h *Handler) getIndicators(c echo.Context) error {
	db := h.DB.Clone()
	defer db.Close()

	i := db.DB("healthyrepo").C("indicators")

	result := []Indicator{}

	err := i.Find(nil).All(&result)
	if err != nil {
		log.Fatal(err)
	}

	return c.JSON(http.StatusOK, result)
}

Return full URL in health


// TODO
// * improve JRD output
// * do stuff with the JRD
package main

import (
	"flag"
	"fmt"
	"github.com/ant0ine/go-webfinger"
	"io/ioutil"
	"log"
	"os"
)

func printHelp() {
	fmt.Println("webfinger [-vh] <resource uri>")
	flag.PrintDefaults()
	fmt.Println("example: webfinger -v bob@example.com") // same Bob as in the draft
}

func main() {

	// cmd line flags
	verbose := flag.Bool("v", false, "print details about the resolution")
	help := flag.Bool("h", false, "display this message")
	flag.Parse()

	if *help {
		printHelp()
		os.Exit(0)
	}

	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	email := flag.Arg(0)

	if email == "" {
		printHelp()
		os.Exit(1)
	}

	log.SetFlags(0)

	client := webfinger.NewClient(nil)
	client.AllowHTTP = true

	jrd, err := client.Lookup(email, nil)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Printf("JRD: %+v", jrd)
	os.Exit(0)
}

// TODO
// * improve JRD output
// * do stuff with the JRD
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/ant0ine/go-webfinger"
	"io/ioutil"
	"log"
	"os"
)

func printHelp() {
	fmt.Println("webfinger [-vh] <resource uri>")
	flag.PrintDefaults()
	fmt.Println("example: webfinger -v bob@example.com") // same Bob as in the draft
}

func main() {

	// cmd line flags
	verbose := flag.Bool("v", false, "print details about the resolution")
	help := flag.Bool("h", false, "display this message")
	flag.Parse()

	if *help {
		printHelp()
		os.Exit(0)
	}

	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	email := flag.Arg(0)

	if email == "" {
		printHelp()
		os.Exit(1)
	}

	log.SetFlags(0)

	client := webfinger.NewClient(nil)
	client.AllowHTTP = true

	jrd, err := client.Lookup(email, nil)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	bytes, err := json.MarshalIndent(jrd, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", bytes)

	os.Exit(0)
}

Change the output for a nicely indented JSON...


package goat

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

// LogManager is responsible for creating the main loggers
func LogManager() {
	// Create log directory and file, and pull current date to add to logfile name
	now := time.Now()
	os.Mkdir("logs", os.ModeDir|os.ModePerm)
	logFile, err := os.Create(fmt.Sprintf("logs/goat-%d-%d-%d.log", now.Year(), now.Month(), now.Day()))
	if err != nil {
		fmt.Println(err)
	}

	// create a logger that will use the writer created above
	logger := log.New(bufio.NewWriter(logFile), "", log.Lmicroseconds|log.Lshortfile)

	// Start the system status logger
	go StatusLogger()

	// Wait for error to be passed on the logChan channel, or termination signal
	for {
		select {
		case msg := <-Static.LogChan:
			now := time.Now()
			log := fmt.Sprintf("%s : [%4d-%02d-%02d %02d:%02d:%02d] %s\n", App, now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), msg)
			logger.Print(log)
			fmt.Print(log)
		}
	}
}

// StatusLogger logs and displays system status at regular intervals
func StatusLogger() {
	ticker := time.NewTicker(5 * time.Minute)

	// Loop infinitely, trigger events via ticker
	for {
		select {
		case <-ticker.C:
			// Fetch status, log it
			go PrintCurrentStatus()
		}
	}
}

package goat

import (
	"fmt"
	"time"
)

// LogManager is responsible for creating the main loggers
func LogManager() {
	// Start the system status logger
	go StatusLogger()

	// Wait for error to be passed on the logChan channel, or termination signal
	for {
		select {
		case msg := <-Static.LogChan:
			now := time.Now()
			out := fmt.Sprintf("%s : [%4d-%02d-%02d %02d:%02d:%02d] %s\n", App, now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), msg)
			fmt.Print(out)
		}
	}
}

// StatusLogger logs and displays system status at regular intervals
func StatusLogger() {
	ticker := time.NewTicker(5 * time.Minute)

	// Loop infinitely, trigger events via ticker
	for {
		select {
		case <-ticker.C:
			// Fetch status, log it
			go PrintCurrentStatus()
		}
	}
}

Remove file logging for now, as it is broken


package rel

import (
	"reflect"
)

type AscendingNode OrderingNode

func (node AscendingNode) Eq(other AscendingNode) bool {
	return reflect.DeepEqual(node, other)
}

func (node AscendingNode) Direction() string {
	return "ASC"
}

func (node AscendingNode) Reverse() *DescendingNode {
	return &DescendingNode{Expr: node.Expr}
}

package rel

import (
	"reflect"
)

type AscendingNode OrderingNode

func (node AscendingNode) Eq(other AscendingNode) bool {
	return reflect.DeepEqual(node, other)
}

func (node *AscendingNode) Direction() string {
	return "ASC"
}

func (node *AscendingNode) Reverse() *DescendingNode {
	return &DescendingNode{Expr: node.Expr}
}

Use ptrs to ascending nodes


package cassandra

import (
	"github.com/Sirupsen/logrus"
	"github.com/intelsdi-x/swan/pkg/cassandra"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestCassandraConnection(t *testing.T) {
	logrus.SetLevel(logrus.ErrorLevel)
	Convey("While creating Cassandra config with proper parameters", t, func() {
		config, err := cassandra.CreateConfigWithSession("127.0.0.1", "snap")
		Convey("I should receive not nil config", func() {
			So(config, ShouldNotBeNil)
			So(err, ShouldBeNil)
			Convey("Config should have not nil session", func() {
				session := config.CassandraSession()
				So(session, ShouldNotBeNil)
			})
		})
	})
}

package cassandra

import (
	"github.com/Sirupsen/logrus"
	"github.com/intelsdi-x/swan/pkg/cassandra"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestCassandraConnection(t *testing.T) {
	logrus.SetLevel(logrus.ErrorLevel)
	Convey("While creating Cassandra config with proper parameters", t, func() {
		config, err := cassandra.CreateConfigWithSession("127.0.0.1", "snap")
		Convey("I should receive not nil config", func() {
			So(err, ShouldBeNil)
			So(config, ShouldNotBeNil)
			Convey("Config should have not nil session", func() {
				session := config.CassandraSession()
				So(session, ShouldNotBeNil)
			})
		})
	})
}

Test error before config in connector test.


package honeybadger

// nullBackend implements the Backend interface but swallows errors and does not
// send them to Honeybadger.
type nullBackend struct{}

// Ensure nullBackend implements Backend.
var _ Backend = &nullBackend{}

// NewNullBackend creates a backend which swallows all errors and does not send
// them to Honeybadger. This is useful for development and testing to disable
// sending unnecessary errors.
func NewNullBackend() Backend {
	return nullBackend{}
}

// Notify swallows error reports, does nothing, and returns no error.
func (b nullBackend) Notify(_ Feature, _ Payload) error {
	return nil
}

package honeybadger

// nullBackend implements the Backend interface but swallows errors and does not
// send them to Honeybadger.
type nullBackend struct{}

// Ensure nullBackend implements Backend.
var _ Backend = &nullBackend{}

// NewNullBackend creates a backend which swallows all errors and does not send
// them to Honeybadger. This is useful for development and testing to disable
// sending unnecessary errors.
func NewNullBackend() Backend {
	return &nullBackend{}
}

// Notify swallows error reports, does nothing, and returns no error.
func (*nullBackend) Notify(_ Feature, _ Payload) error {
	return nil
}

Make NewNullBackend returns a pointer to nullBackend


// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

// +build gofuzz

package vm

import (
	"bytes"
	"flag"
	"fmt"
)

func Fuzz(data []byte) int {
	// Enable this when debugging with a fuzz crash artifact.
	dumpDebug := false
	// We need to successfully parse flags to initialize the glog logger used
	// by the compiler, but the fuzzer gets called with flags captured by the
	// libfuzzer main, which we don't want to intercept here.
	flag.CommandLine = flag.NewFlagSet("", flag.ContinueOnError)
	flag.CommandLine.Parse([]string{})
	if _, err := Compile("fuzz", bytes.NewReader(data), dumpDebug, dumpDebug, false, nil); err != nil {
		if dumpDebug {
			fmt.Print(err)
		}
		return 0
	}
	return 1
}

// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

// +build gofuzz

package vm

import (
	"bytes"
	"flag"
	"fmt"
	"os"
)

func Fuzz(data []byte) int {
	// Enable this when debugging with a fuzz crash artifact.
	dumpDebug := false
	// We need to successfully parse flags to initialize the glog logger used
	// by the compiler, but the fuzzer gets called with flags captured by the
	// libfuzzer main, which we don't want to intercept here.
	flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
	flag.CommandLine.Parse([]string{})
	if _, err := Compile("fuzz", bytes.NewReader(data), dumpDebug, dumpDebug, false, nil); err != nil {
		if dumpDebug {
			fmt.Print(err)
		}
		return 0
	}
	return 1
}

Use os.Args for the command name.


// +build appenginevm

package google

import (
	"strings"

	"github.com/golang/oauth2"
	"google.golang.org/appengine"
)

type AppEngineConfig struct {
	context appengine.Context
	scopes  []string
	cache   oauth2.Cache
}

func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineConfig {
	return &AppEngineConfig{context: context, scopes: scopes}
}

func (c *AppEngineConfig) NewTransport() oauth2.Transport {
	return oauth2.NewAuthorizedTransport(c, nil)
}

func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
	token, err := cache.Read()
	if err != nil {
		return nil, err
	}
	c.cache = cache
	return oauth2.NewAuthorizedTransport(c, token), nil
}

func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
	token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
	if err != nil {
		return nil, err
	}
	return &oauth2.Token{
		AccessToken: token,
		Expiry:      expiry,
	}, nil
}

func (c *AppEngineConfig) Cache() oauth2.Cache {
	return c.cache
}

// +build !appengine

package google

import (
	"strings"

	"github.com/golang/oauth2"
	"google.golang.org/appengine"
)

type AppEngineConfig struct {
	context appengine.Context
	scopes  []string
	cache   oauth2.Cache
}

func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineConfig {
	return &AppEngineConfig{context: context, scopes: scopes}
}

func (c *AppEngineConfig) NewTransport() oauth2.Transport {
	return oauth2.NewAuthorizedTransport(c, nil)
}

func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
	token, err := cache.Read()
	if err != nil {
		return nil, err
	}
	c.cache = cache
	return oauth2.NewAuthorizedTransport(c, token), nil
}

func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
	token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
	if err != nil {
		return nil, err
	}
	return &oauth2.Token{
		AccessToken: token,
		Expiry:      expiry,
	}, nil
}

func (c *AppEngineConfig) Cache() oauth2.Cache {
	return c.cache
}

Make app engine main implementation godoced.


package sack

import (
	"fmt"
	"github.com/wsxiaoys/terminal/color"
	"io/ioutil"
	"regexp"
	"strings"
)

func display() {
	lines := content()

	dat, err := ioutil.ReadFile(termPath)
	check(err)

	// Header
	fmt.Print(header)

	for i, line := range lines {
		li := strings.SplitN(line, " ", 3)
		s := displayLines(string(dat), i, li[0], li[1], li[2])
		fmt.Println(s)
	}
}

func displayLines(term string, ind int, line string, file string, content string) string {
	str := fmt.Sprint("(?i)", term)
	reg, _ := regexp.Compile(str)
	hiContent := reg.ReplaceAllString(content, color.Sprintf("@{r!}%s", term))
	s := color.Sprintf("@r[%2d]@{|} @b%5s@{|}  @g%s@{|} %s", ind, line, file, hiContent)
	return s
}

package sack

import (
	"fmt"
	"github.com/wsxiaoys/terminal/color"
	"io/ioutil"
	"regexp"
	"strings"
)

func display() {
	lines := content()

	dat, err := ioutil.ReadFile(termPath)
	check(err)

	// Header
	fmt.Print(header)

	for i, line := range lines {
		li := strings.SplitN(line, " ", 3)
		s := displayLines(string(dat), i, li[0], li[1], li[2])
		fmt.Println(s)
	}
}

func displayLines(term string, ind int, line string, file string, content string) string {
	str := fmt.Sprint("(?i)", "(", term, ")")
	reg, _ := regexp.Compile(str)
	hiContent := reg.ReplaceAllString(content, color.Sprintf("@{r!}$1"))
	s := color.Sprintf("@r[%2d]@{|} @b%5s@{|}  @g%s@{|} %s", ind, line, file, hiContent)
	return s
}

Fix case issue in highlighted match


// Package time contains functions to help work with date and time
package time

import (
	"time"
)

// ZoneName - a convenience function for determining the current timezone's name
func ZoneName() string {
	n, _ := time.Now().Zone()
	return n
}

// ZoneOffset - determine the current timezone's offset, in seconds east of UTC
func ZoneOffset() int {
	_, o := time.Now().Zone()
	return o
}

// Package time contains functions to help work with date and time
package time

import (
	"time"

	"github.com/hairyhenderson/gomplate/v3/env"
)

// ZoneName - a convenience function for determining the current timezone's name
func ZoneName() string {
	n, _ := zone()
	return n
}

// ZoneOffset - determine the current timezone's offset, in seconds east of UTC
func ZoneOffset() int {
	_, o := zone()
	return o
}

func zone() (string, int) {
	// re-read TZ env var in case it's changed since the process started.
	// This may happen in certain rare instances when this is being called as a
	// library, or in a test. It allows for a bit more flexibility too, as
	// changing time.Local is prone to data races.
	tz := env.Getenv("TZ", "Local")
	loc, err := time.LoadLocation(tz)
	if err != nil {
		loc = time.Local
	}
	return time.Now().In(loc).Zone()
}

Support changing TZ env var in Zone functions


// +build !consulent

package structs

import (
	"hash"

	"github.com/hashicorp/consul/acl"
)

// EnterpriseMeta stub
type EnterpriseMeta struct{}

func (m *EnterpriseMeta) estimateSize() int {
	return 0
}

func (m *EnterpriseMeta) addToHash(hasher hash.Hash) {
	// do nothing
}

// ReplicationEnterpriseMeta stub
func ReplicationEnterpriseMeta() *EnterpriseMeta {
	return nil
}

// DefaultEnterpriseMeta stub
func DefaultEnterpriseMeta() *EnterpriseMeta {
	return nil
}

// InitDefault stub
func (m *EnterpriseMeta) InitDefault() {}

// FillAuthzContext stub
func (m *EnterpriseMeta) FillAuthzContext(*acl.EnterpriseAuthorizerContext) {}

// FillAuthzContext stub
func (d *DirEntry) FillAuthzContext(*acl.EnterpriseAuthorizercontext) {}

Add DirEntry method to fill enterprise authz context


package logic

import (
	"github.com/jclebreton/opensirene/database"
	"github.com/pkg/errors"
)

type track struct {
	Database database.PgxClient
}

type Tracker interface {
	Save(action, msg, filename string, isSuccess bool) error
}

func NewTracker(db database.PgxClient) *track {
	return &track{Database: db}
}

// Save logs to database the milestones
func (t *track) Save(action, msg, filename string, isSuccess bool) error {
	var err error

	_, err = t.Database.Conn.Exec(
		"INSERT INTO history (action, is_success, filename, msg) VALUES ($1, $2, $3, $4)",
		action,
		isSuccess,
		filename,
		msg,
	)

	if err != nil {
		return errors.Wrap(err, "couldn't log sql transaction")
	}

	return nil
}

// Truncate will erase all logs
func (t *track) Truncate() error {
	var err error

	_, err = t.Database.Conn.Exec("TRUNCATE TABLE history")

	if err != nil {
		return errors.Wrap(err, "couldn't truncate history table")
	}

	return nil
}

Truncate history during a full import


package main

import (
	"fmt"
	"socialapi/workers/common/runner"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/sitemapfeeder/feeder"
)

var (
	Name = "SitemapInitializer"
)

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}
	defer r.Close()

	redisConn := helper.MustInitRedisConn(r.Conf)
	defer redisConn.Close()

	controller := feeder.New(r.Log)

	if err := controller.Start(); err != nil {
		r.Log.Fatal("Could not finish sitemap initialization: %s", err)
	}

}

package main

import (
	"fmt"
	"socialapi/workers/common/runner"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/sitemapfeeder/feeder"
)

var (
	Name = "SitemapInitializer"
)

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}
	defer r.Close()

	conf := *r.Conf
	conf.Redis.DB = r.Conf.Sitemap.RedisDB

	redisConn := helper.MustInitRedisConn(r.Conf)
	defer redisConn.Close()

	controller := feeder.New(r.Log)

	if err := controller.Start(); err != nil {
		r.Log.Fatal("Could not finish sitemap initialization: %s", err)
	}

}

Add optional redisDB for initializer


package authboss

import (
	"bytes"
	"strings"
	"testing"
)

func TestMailer(t *testing.T) {
	mailServer := &bytes.Buffer{}

	config := NewConfig()
	config.Mailer = LogMailer(mailServer)
	config.Storer = mockStorer{}
	Init(config)

	err := SendMail(Email{
		To:       []string{"some@email.com", "a@a.com"},
		ToNames:  []string{"Jake", "Noname"},
		From:     "some@guy.com",
		FromName: "Joseph",
		ReplyTo:  "an@email.com",
		Subject:  "Email!",
		TextBody: "No html here",
		HTMLBody: "<html>body</html>",
	})
	if err != nil {
		t.Error(err)
	}

	if mailServer.Len() == 0 {
		t.Error("It should have logged the e-mail.")
	}

	str := mailServer.String()
	if !strings.Contains(str, "From: Joseph <some@guy.com>") {
		t.Error("From line not present.")
	}

	if !strings.Contains(str, "To: Jake <some@email.com>, Noname <a@a.com>") {
		t.Error("To line not present.")
	}
}

package authboss

import (
	"bytes"
	"strings"
	"testing"
)

func TestMailer(t *testing.T) {
	mailServer := &bytes.Buffer{}

	config := NewConfig()
	config.Mailer = LogMailer(mailServer)
	config.Storer = mockStorer{}
	Init(config)

	err := SendMail(Email{
		To:       []string{"some@email.com", "a@a.com"},
		ToNames:  []string{"Jake", "Noname"},
		From:     "some@guy.com",
		FromName: "Joseph",
		ReplyTo:  "an@email.com",
		Subject:  "Email!",
		TextBody: "No html here",
		HTMLBody: "body",
	})
	if err != nil {
		t.Error(err)
	}

	if mailServer.Len() == 0 {
		t.Error("It should have logged the e-mail.")
	}

	str := mailServer.String()
	if !strings.Contains(str, "From: Joseph <some@guy.com>") {
		t.Error("From line not present.")
	}

	if !strings.Contains(str, "To: Jake <some@email.com>, Noname ") {
		t.Error("To line not present.")
	}

	if !strings.Contains(str, "No html here") {
		t.Error("Text body not present.")
	}

	if !strings.Contains(str, "body") {
		t.Error("Html body not present.")
	}
}

Make mailer test a bit more inclusive.


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

package policy

import "time"

// Event data that will be sent by policy handlers
type Event struct {
	Time   time.Time
	Policy Policy
	Data   map[string]interface{} // Data may include status, stats, etc.
}

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

package policy

import "time"

// Event data that will be sent by policy handlers
type Event struct {
	Time       time.Time
	PolicyName string      `bson:"policy_name"`
	AgentUID   string      `bson:"agent_uid"`
	Data       interface{} // Data may include status, stats, etc.
}

Change the Event to not include complete Policy


package data

import (
	"time"

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

type Memeber struct {
	ID        bson.ObjectId "bson:`_id`"
	ProjectID bson.ObjectId "bson:`project_id`"
	AccountID bson.ObjectId "bson:`account_id`"
	InviterID bson.ObjectId "bson:`inviter_id`"
	InvitedAt time.Time     "bson:`invited_at`"
}

func GetMember(id bson.ObjectId) (*Memeber, error) {
	mem := Memeber{}
	err := sess.DB("").C(memberC).FindId(id).One(&mem)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &mem, nil
}

package data

import (
	"time"

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

type Memeber struct {
	ID        bson.ObjectId `bson:"_id"`
	ProjectID bson.ObjectId `bson:"project_id"`
	AccountID bson.ObjectId `bson:"account_id"`
	InviterID bson.ObjectId `bson:"inviter_id"`
	InvitedAt time.Time     `bson:"invited_at"`

	ModifiedAt time.Time `bson:"modified_at"`
	CreatedAt  time.Time `bson:"created_at"`
}

func GetMember(id bson.ObjectId) (*Memeber, error) {
	mem := Memeber{}
	err := sess.DB("").C(memberC).FindId(id).One(&mem)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &mem, nil
}

Add date fields in Member struct


package cfg

/*
    Configuration of Procession services can be done via either command line
    options (flags) or via environment variables.

    *Some* environment variables, e.g. PROCESSION_LOG_LEVEL,  may be changed
    **after** a service is started, and the value of the environment variable
    will override anything that had initially been provided via a command line
    option.
*/

import (
    flag "github.com/ogier/pflag"
    "github.com/jaypipes/procession/pkg/env"
)

const (
    defaultLogLevel = 0
)

var (
    optLogLevel = flag.Int(
        "log-level",
        env.EnvOrDefaultInt(
            "PROCESSION_LOG_LEVEL", defaultLogLevel,
        ),
        "The verbosity of logging. 0 (default) = virtually no logging. " +
        "1 = some logging. 2 = debug-level logging",
    )
)

// Returns the logging level.
func LogLevel() int {
    return env.EnvOrDefaultInt(
        "PROCESSION_LOG_LEVEL",
        *optLogLevel,
    )
}

func ParseCliOpts() {
    flag.Parse()
}

package cfg

/*
    Configuration of Procession services can be done via either command line
    options (flags) or via environment variables.

    *Some* environment variables, e.g. PROCESSION_LOG_LEVEL,  may be changed
    **after** a service is started, and the value of the environment variable
    will override anything that had initially been provided via a command line
    option.
*/

import (
    "time"

    flag "github.com/ogier/pflag"
    "github.com/jaypipes/procession/pkg/env"
)

const (
    defaultLogLevel = 0
    defaultConnectTimeoutSeconds = 60
)

var (
    optLogLevel = flag.Int(
        "log-level",
        env.EnvOrDefaultInt(
            "PROCESSION_LOG_LEVEL", defaultLogLevel,
        ),
        "The verbosity of logging. 0 (default) = virtually no logging. " +
        "1 = some logging. 2 = debug-level logging",
    )
    optConnectTimeoutSeconds = flag.Int(
        "connect-timeout",
        env.EnvOrDefaultInt(
            "PROCESSION_CONNECT_TIMEOUT_SECONDS", defaultConnectTimeoutSeconds,
        ),
        "Number of seconds to wait while attempting to initially make a " +
        "connection to some external or dependent service",
    )
)

// Returns the logging level.
func LogLevel() int {
    return env.EnvOrDefaultInt(
        "PROCESSION_LOG_LEVEL",
        *optLogLevel,
    )
}

func ConnectTimeout() time.Duration {
    return time.Duration(
        env.EnvOrDefaultInt(
            "PROCESSION_CONNECT_TIMEOUT_SECONDS",
            *optConnectTimeoutSeconds,
        ),
    )
}

func ParseCliOpts() {
    flag.Parse()
}

Add connection timeout configuration common param


package main

import (
    "encoding/json"
    "fmt"
    "os"
)

func parseObj(in interface{}, out map[string]interface{}, prefix string) {
    switch vv := in.(type) {
    case map[string]interface{}:
        for key, value := range vv {
            parseObj(value, out, fmt.Sprintf("%s.%s", prefix, key))
        }
    case []interface{}:
        for index, value := range vv {
            parseObj(value, out, fmt.Sprintf("%s.%d", prefix, index))
        }
    case string:
        out[prefix[1:]] = vv
    case int:
        out[prefix[1:]] = vv
    case bool:
        out[prefix[1:]] = vv
    default:
        fmt.Fprintln(os.Stderr, "Input appears to be invalid json")
        os.Exit(1)
    }
}

func main() {
    var in interface{}

    out := make(map[string]interface{})

    dec := json.NewDecoder(os.Stdin)

    dec.Decode(&in)

    parseObj(in, out, "")

    if len(os.Args) > 1 {
        key := os.Args[1]

        if value, ok := out[key]; ok {
            fmt.Println(value)
        }
    } else {
        for key, value := range out {
            fmt.Printf("%s=%v\n", key, value)
        }
    }
}

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

func parseObj(in interface{}, out map[string]interface{}, prefix string) {
    switch vv := in.(type) {
    case map[string]interface{}:
        for key, value := range vv {
            parseObj(value, out, fmt.Sprintf("%s.%s", prefix, key))
        }
    case []interface{}:
        for index, value := range vv {
            parseObj(value, out, fmt.Sprintf("%s.%d", prefix, index))
        }
    case string:
        out[prefix[1:]] = vv
    case float64:
        out[prefix[1:]] = vv
    case bool:
        out[prefix[1:]] = vv
    default:
        fmt.Fprintln(os.Stderr, "Input appears to be invalid json")
        os.Exit(1)
    }
}

func main() {
    var in interface{}

    out := make(map[string]interface{})

    dec := json.NewDecoder(os.Stdin)

    dec.Decode(&in)

    parseObj(in, out, "")

    if len(os.Args) > 1 {
        key := os.Args[1]

        if value, ok := out[key]; ok {
            fmt.Println(value)
        }
    } else {
        for key, value := range out {
            fmt.Printf("%s=%v\n", key, value)
        }
    }
}

Use the correct type for numbers!


package buildcfg

import (
	"net/url"
	"strings"
)

func loadGoConfig(remote string, c *Config) {
	u, _ := url.Parse(remote)
	importPath := u.Hostname() + strings.Replace(u.Path, ".git", "", 1)

	// Most part of this just moves everything from builddir to the correct go-import-path
	setup := []string{
		"export GOPATH=/build",
		"export PATH=$PATH:/build/bin",
		"mkdir /tmp/dat",
		"rsync -az . /tmp/dat",
		"rm -rf *",
		"mkdir -p src/" + importPath,
		"rsync -az /tmp/dat/ src/" + importPath,
		"rm -rf /tmp/dat",
		"cd src/" + importPath,
	}
	c.Setup.V = append(setup, c.Setup.V...)
	c.Addons.Apt.Packages = append(c.Addons.Apt.Packages, "rsync")

	if len(c.Script.V) == 0 && len(c.Install.V) == 0 {
		c.Script.V = []string{
			"go get -t -v ./...",
			"go test -v ./...",
		}
	}
	c.DockerImage = "golang"
}

package buildcfg

import (
	"net/url"
	"strings"
)

func goImportPath(remote string) string {
	if strings.Contains(remote, ":") && strings.Contains(remote, "@") {
		rem := remote[strings.Index(remote, "@")+1:]
		return strings.Replace(strings.Replace(rem, ".git", "", 1), ":", "/", 1)
	}
	u, err := url.Parse(remote)
	if err != nil {
		return remote
	}
	return u.Hostname() + strings.Replace(u.Path, ".git", "", 1)
}

func loadGoConfig(remote string, c *Config) {
	importPath := goImportPath(remote)

	// Most part of this just moves everything from builddir to the correct go-import-path
	setup := []string{
		"export GOPATH=/build/.gopath",
		"export PATH=$PATH:/build/bin",
		"mkdir -p /build/.gopath/src/" + importPath,
		"mount -o bind /build /build/.gopath/src/" + importPath,
		"cd /build/.gopath/src/" + importPath,
	}
	c.Setup.V = append(setup, c.Setup.V...)
	c.Addons.Apt.Packages = append(c.Addons.Apt.Packages, "rsync")

	if len(c.Script.V) == 0 && len(c.Install.V) == 0 {
		c.Script.V = []string{
			"go get -t -v ./...",
			"go test -v ./...",
		}
	}
	c.DockerImage = "golang"
}

Change the way golang packages are built


package main

import (
	"fmt"
	"http"
)

// support for running "redwood -test http://example.com"

// runURLTest prints debugging information about how the URL and its content would be rated.
func runURLTest(u string) {
	url, err := http.ParseURL(u)
	if err != nil {
		fmt.Println("Could not parse the URL.")
		return
	}

	fmt.Println("URL:", url)
	fmt.Println()

	matches := URLRules.MatchingRules(url)
	if len(matches) == 0 {
		fmt.Println("No URL rules match.")
	} else {
		fmt.Println("The following URL rules match:")
		for _, s := range matches {
			fmt.Println(s)
		}
	}
}

package main

import (
	"fmt"
	"http"
	"mahonia.googlecode.com/hg"
)

// support for running "redwood -test http://example.com"

// runURLTest prints debugging information about how the URL and its content would be rated.
func runURLTest(u string) {
	url, err := http.ParseURL(u)
	if err != nil {
		fmt.Println("Could not parse the URL.")
		return
	}

	fmt.Println("URL:", url)
	fmt.Println()

	matches := URLRules.MatchingRules(url)
	if len(matches) == 0 {
		fmt.Println("No URL rules match.")
	} else {
		fmt.Println("The following URL rules match:")
		for _, s := range matches {
			fmt.Println(s)
		}
	}

	fmt.Println()
	fmt.Println("Downloading content...")
	res, err := http.Get(u)
	if err != nil {
		fmt.Println(err)
		return
	}

	defer res.Body.Close()
	wr := newWordReader(res.Body, mahonia.NewDecoder("UTF-8"))
	ps := newPhraseScanner()
	ps.scanByte(' ')
	buf := make([]byte, 4096)
	for {
		n, err := wr.Read(buf)
		if err != nil {
			break
		}
		for i := 0; i < n; i++ {
			ps.scanByte(buf[i])
		}
	}
	ps.scanByte(' ')

	fmt.Println()

	if len(ps.tally) == 0 {
		fmt.Println("No content phrases match.")
	} else {
		fmt.Println("The following content phrases match:")
		for rule, count := range ps.tally {
			fmt.Println(rule, count)
		}
	}
}

Test mode now scans for phrases.


package h2spec

import (
	"github.com/bradfitz/http2"
	"github.com/bradfitz/http2/hpack"
)

func FrameSizeTestGroup() *TestGroup {
	tg := NewTestGroup("4.2", "Frame Size")

	tg.AddTestCase(NewTestCase(
		"Sends large size frame that exceeds the SETTINGS_MAX_FRAME_SIZE",
		"The endpoint MUST send a FRAME_SIZE_ERROR error.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, false)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteSettings()

			hdrs := []hpack.HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", ctx.Authority()),
			}

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, true, []byte(dummyData(16385)))

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}

package h2spec

import (
	"github.com/bradfitz/http2"
	"github.com/bradfitz/http2/hpack"
)

func FrameSizeTestGroup() *TestGroup {
	tg := NewTestGroup("4.2", "Frame Size")

	tg.AddTestCase(NewTestCase(
		"Sends large size frame that exceeds the SETTINGS_MAX_FRAME_SIZE",
		"The endpoint MUST send a FRAME_SIZE_ERROR error.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, false)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteSettings()

			hdrs := []hpack.HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", ctx.Authority()),
			}

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, true, []byte(dummyData(16385)))

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}

Fix test 4.2 to test for stream error


package skin

import (
	"errors"
	"fmt"
	"image/png"
	"net/http"
)

const (
	skinURL = "http://skins.minecraft.net/MinecraftSkins/%s.png"
)

// Follow all redirects
var skinClient = &http.Client{
	CheckRedirect: func(*http.Request, []*http.Request) error {
		return nil
	},
}

func Download(player string) (skin *Skin, err error) {
	resp, err := http.Get(fmt.Sprintf(skinURL, player))
	if err != nil {
		return
	}

	if resp.StatusCode != http.StatusOK {
		err = errors.New(resp.Request.URL.String() + " returned " + resp.Status)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if contentType != "image/png" {
		err = errors.New("expected image/png, " + resp.Request.URL.String() + " returned " + contentType + " instead")
		return
	}

	defer resp.Body.Close()
	img, err := png.Decode(resp.Body)
	if err != nil {
		return
	}

	return (*Skin)(rgba(img)), nil
}

package skin

import (
	"errors"
	"fmt"
	"image/png"
	"net/http"
)

const (
	skinURL = "http://skins.minecraft.net/MinecraftSkins/%s.png"
)

func Download(player string) (skin *Skin, err error) {
	resp, err := http.Get(fmt.Sprintf(skinURL, player))
	if err != nil {
		return
	}

	if resp.StatusCode != http.StatusOK {
		err = errors.New(resp.Request.URL.String() + " returned " + resp.Status)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if contentType != "image/png" {
		err = errors.New("expected image/png, " + resp.Request.URL.String() + " returned " + contentType + " instead")
		return
	}

	defer resp.Body.Close()
	img, err := png.Decode(resp.Body)
	if err != nil {
		return
	}

	return (*Skin)(rgba(img)), nil
}

Remove unused custom http client


package tracks

import "testing"

func elem(s SegmentType) Element {
	return Element{
		Segment: TS_MAP[s],
	}
}

func TestNotPossible(t *testing.T) {
	testCases := []struct {
		input          Element
		notPossibility Element
	}{
		{elem(ELEM_FLAT_TO_25_DEG_UP), elem(ELEM_LEFT_QUARTER_TURN_5_TILES)},
	}
	for _, tt := range testCases {
		possibilities := tt.input.Possibilities()
		for _, poss := range possibilities {
			if poss.Segment.Type == tt.notPossibility.Segment.Type {
				t.Errorf("expected %s to not be a possibility for %s, but was", poss.Segment.String(), tt.notPossibility.Segment.String())
			}
		}
	}
}

Add basic test for generated track


package pkg

import "sync"

func fn() {
	s := []int{}

	v := sync.Pool{}
	v.Put(s) // MATCH /Non-pointer type /
	v.Put(&s)

	p := &sync.Pool{}
	p.Put(s) // MATCH /Non-pointer type /
	p.Put(&s)
}

package pkg

import "sync"

func fn() {
	s := []int{}

	v := sync.Pool{}
	v.Put(s) // MATCH /non-pointer type/
	v.Put(&s)

	p := &sync.Pool{}
	p.Put(s) // MATCH /non-pointer type/
	p.Put(&s)
}

Fix tests for sync.Pool check


package wav

import (
	"fmt"
	"os"
	"testing"
	"time"

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

func TestBasicWav(t *testing.T) {
	fmt.Println("Running Basic Wav")
	f, err := os.Open("test.wav")
	fmt.Println(f)
	require.Nil(t, err)
	a, err := Load(f)
	require.Nil(t, err)
	err = <-a.Play()
	require.Nil(t, err)
	time.Sleep(4 * time.Second)
	// In addition to the error tests here, this should play noise
}

package wav

import (
	"fmt"
	"os"
	"testing"
	"time"
)

func TestBasicWav(t *testing.T) {
	fmt.Println("Running Basic Wav")
	f, err := os.Open("test.wav")
	fmt.Println(f)
	if err != nil {
		t.Fatal("expected open err to be nil, was", err)
	}
	a, err := Load(f)
	if err != nil {
		t.Fatal("expected load err to be nil, was", err)
	}
	err = <-a.Play()
	if err != nil {
		t.Fatal("expected play err to be nil, was", err)
	}
	time.Sleep(4 * time.Second)
	// In addition to the error tests here, this should play noise
}

Remove require from wav test


package web

import (
	"html/template"
	"log"
	"net/http"

	"github.com/johnmaguire/wbc/database"
)

type IndexHandler struct {
	address  string
	database string
}

func (ih *IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := getClient("index", r)

	// Connect to database
	db, err := database.Connect(ih.database)
	if err != nil {
		log.Fatal(err)
	}

	// Get URLs from database
	urls, err := db.FetchUrls()
	if err != nil {
		log.Fatal(err)
	}

	// Load template, parse vars, write to client
	t, _ := template.New("index").Parse(indexTemplate)
	t.Execute(w, struct {
		Client string
		URLs   []string
	}{
		id,
		urls,
	})
}

type WelcomeHandler struct {
	address  string
	database string
}

func (ih *WelcomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := getClient("welcome", r)

	// Load template, parse vars, write to client
	t, _ := template.New("welcome").Parse(welcomeTemplate)
	t.Execute(w, struct {
		Client     string
		RemoteAddr string
	}{
		id,
		r.RemoteAddr,
	})
}

package web

import (
	"html/template"
	"log"
	"net/http"
	"strings"

	"github.com/johnmaguire/wbc/database"
)

type IndexHandler struct {
	address  string
	database string
}

func (ih *IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := getClient("index", r)

	// Connect to database
	db, err := database.Connect(ih.database)
	if err != nil {
		log.Fatal(err)
	}

	// Get URLs from database
	urls, err := db.FetchUrls()
	if err != nil {
		log.Fatal(err)
	}

	// Load template, parse vars, write to client
	t, _ := template.New("index").Parse(indexTemplate)
	t.Execute(w, struct {
		Client string
		URLs   []string
	}{
		id,
		urls,
	})
}

type WelcomeHandler struct {
	address  string
	database string
}

func (ih *WelcomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	id := getClient("welcome", r)

	// Load template, parse vars, write to client
	t, _ := template.New("welcome").Parse(welcomeTemplate)
	t.Execute(w, struct {
		Client     string
		RemoteAddr string
	}{
		id,
		r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")],
	})
}

Drop port from welcome page


// Package logrusadapter provides a logger that writes to a github.com/sirupsen/logrus.Logger
// log.
package logrusadapter

import (
	"github.com/jackc/pgx"
	"github.com/sirupsen/logrus"
)

type Logger struct {
	l *logrus.Logger
}

func NewLogger(l *logrus.Logger) *Logger {
	return &Logger{l: l}
}

func (l *Logger) Log(level pgx.LogLevel, msg string, data map[string]interface{}) {
	var logger logrus.FieldLogger
	if data != nil {
		logger = l.l.WithFields(data)
	} else {
		logger = l.l
	}

	switch level {
	case pgx.LogLevelTrace:
		logger.WithField("PGX_LOG_LEVEL", level).Debug(msg)
	case pgx.LogLevelDebug:
		logger.Debug(msg)
	case pgx.LogLevelInfo:
		logger.Info(msg)
	case pgx.LogLevelWarn:
		logger.Warn(msg)
	case pgx.LogLevelError:
		logger.Error(msg)
	default:
		logger.WithField("INVALID_PGX_LOG_LEVEL", level).Error(msg)
	}
}

// Package logrusadapter provides a logger that writes to a github.com/sirupsen/logrus.Logger
// log.
package logrusadapter

import (
	"github.com/jackc/pgx"
	"github.com/sirupsen/logrus"
)

type Logger struct {
	l logrus.FieldLogger
}

func NewLogger(l logrus.FieldLogger) *Logger {
	return &Logger{l: l}
}

func (l *Logger) Log(level pgx.LogLevel, msg string, data map[string]interface{}) {
	var logger logrus.FieldLogger
	if data != nil {
		logger = l.l.WithFields(data)
	} else {
		logger = l.l
	}

	switch level {
	case pgx.LogLevelTrace:
		logger.WithField("PGX_LOG_LEVEL", level).Debug(msg)
	case pgx.LogLevelDebug:
		logger.Debug(msg)
	case pgx.LogLevelInfo:
		logger.Info(msg)
	case pgx.LogLevelWarn:
		logger.Warn(msg)
	case pgx.LogLevelError:
		logger.Error(msg)
	default:
		logger.WithField("INVALID_PGX_LOG_LEVEL", level).Error(msg)
	}
}

Use logrus.FieldLogger instead of *logrus.Logger


package azure_test

import (
	"io/ioutil"

	"github.com/cloudfoundry/bosh-bootloader/storage"
	"github.com/cloudfoundry/bosh-bootloader/terraform/azure"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("TemplateGenerator", func() {
	var (
		templateGenerator azure.TemplateGenerator
	)

	BeforeEach(func() {
		templateGenerator = azure.NewTemplateGenerator()
	})

	Describe("Generate", func() {
		It("generates a terraform template for azure", func() {
			expectedTemplate, err := ioutil.ReadFile("fixtures/azure_template_rg.tf")
			Expect(err).NotTo(HaveOccurred())

			template := templateGenerator.Generate(storage.State{
				EnvID: "azure-environment",
				Azure: storage.Azure{
					SubscriptionID: "subscription-id",
					TenantID:       "tenant-id",
					ClientID:       "client-id",
					ClientSecret:   "client-secret",
				},
			})
			Expect(template).To(Equal(string(expectedTemplate)))
		})
	})
})

package azure_test

import (
	"io/ioutil"

	"github.com/cloudfoundry/bosh-bootloader/storage"
	"github.com/cloudfoundry/bosh-bootloader/terraform/azure"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("TemplateGenerator", func() {
	var (
		templateGenerator azure.TemplateGenerator
	)

	BeforeEach(func() {
		templateGenerator = azure.NewTemplateGenerator()
	})

	Describe("Generate", func() {
		It("generates a terraform template for azure", func() {
			expectedTemplate, err := ioutil.ReadFile("fixtures/azure_template.tf")
			Expect(err).NotTo(HaveOccurred())

			template := templateGenerator.Generate(storage.State{
				EnvID: "azure-environment",
				Azure: storage.Azure{
					SubscriptionID: "subscription-id",
					TenantID:       "tenant-id",
					ClientID:       "client-id",
					ClientSecret:   "client-secret",
				},
			})
			Expect(template).To(Equal(string(expectedTemplate)))
		})
	})
})

Fix azure terraform fixture filename.


package pipeline

import (
	"time"
)

// TimingPipe invokes a custom callback function with the amount of time required to run a specific Pipe
type TimingPipe struct {
	timedPipe Pipe
	callback  func(begin time.Time, duration time.Duration)
}

// NewTimingPipe creates a new timing pipe
func NewTimingPipe(timedPipe Pipe, callback func(begin time.Time, duration time.Duration)) Pipe {
	return &TimingPipe{
		timedPipe: timedPipe,
		callback:  callback,
	}
}

func (t TimingPipe) Process(in chan Data) chan Data {
	out := make(chan Data)
	go func() {
		defer close(out)
		for request := range in {
			begin := time.Now()
			innerPipeline := NewPipeline(t.timedPipe)
			go func() {
				innerPipeline.Enqueue(request)
				innerPipeline.Close()
			}()
			innerPipeline.Dequeue(func(response Data) {
				out <- response
			})
			t.callback(begin, time.Since(begin))
		}
	}()
	return out
}

package pipeline

import (
	"time"
)

// TimingPipe invokes a custom callback function with the amount of time required to run a specific Pipe
type TimingPipe struct {
	timedPipe Pipe
	callback  func(begin time.Time, duration time.Duration)
}

// NewTimingPipe creates a new timing pipe
func NewTimingPipe(timedPipe Pipe, callback func(begin time.Time, duration time.Duration)) *TimingPipe {
	return &TimingPipe{
		timedPipe: timedPipe,
		callback:  callback,
	}
}

func (t *TimingPipe) Process(in chan Data) chan Data {
	out := make(chan Data)
	go func() {
		defer close(out)
		for request := range in {
			begin := time.Now()
			innerPipeline := NewPipeline(t.timedPipe)
			go func() {
				innerPipeline.Enqueue(request)
				innerPipeline.Close()
			}()
			innerPipeline.Dequeue(func(response Data) {
				out <- response
			})
			t.callback(begin, time.Since(begin))
		}
	}()
	return out
}

Return pointer from NewTimingPipe function


package isdomain

// ExtendedTLDs is a set of additional "TLDs", allowing decentralized name
// systems, like TOR and Namecoin.
var ExtendedTLDs = map[string]bool{
	"BIT":   true,
	"ONION": true,
	"ETH":   true,
}

package isdomain

// ExtendedTLDs is a set of additional "TLDs", allowing decentralized name
// systems, like TOR and Namecoin.
var ExtendedTLDs = map[string]bool{
	"BIT":   true,
	"ONION": true,
	"ETH":   true,
	"BBS":   true,
	"CHAN":  true,
	"CYB":   true,
	"DYN":   true,
	"EPIC":  true,
	"GEEK":  true,
	"GOPHER":true,
	"INDY":  true,
	"LIBRE": true,
	"NEO":   true,
	"NULL":  true,
	"O":     true,
	"OSS":   true,
	"OZ":    true,
	"PARODY":true,
	"PIRATE":true,
}

Add OpenNIC domains to extended TLDs.


package utils

import "math"

func IsPrime(num int) bool {
	floatNum := float64(num)
	for i := 2; i <= int(math.Floor(math.Sqrt(floatNum))); i++ {
		if num%i == 0 {
			return false
		}
	}
	return true
}

func Gcd(a, b int) int {
	var min, max int
	if a < b {
		min, max = a, b
	} else {
		min, max = b, a
	}
	for min != 0 {
		max, min = min, max%min
	}
	return max
}

func PrimeFactors(n int) []int {
	factors := make([]int, 0)
	d := 2
	for n > 1 {
		for n%d == 0 {
			factors = append(factors, d)
			n /= d
		}
		d += 1
		if d*d > n {
			if n > 1 {
				factors = append(factors, n)
			}
			break
		}
	}
	return factors
}

Add GCD and prime factors algorithms


package iam

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

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-accesskey.html
var AccessKey = Resource{
	AwsType: "AWS::IAM::AccessKey",

	Attributes: map[string]Schema{
		"SecretAccessKey": Schema{
			Type: ValueString,
		},
	},

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

	Properties: Properties{
		"Serial": Schema{
			Type: ValueNumber,
		},

		"Status": Schema{
			Type: EnumValue{
				Description: "Status",
				Options:     []string{"Active", "Inactive"},
			},
			Required: constraints.Always,
		},

		"UserName": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},
	},
}

package iam

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

// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-accesskey.html
var AccessKey = Resource{
	AwsType: "AWS::IAM::AccessKey",

	Attributes: map[string]Schema{
		"SecretAccessKey": Schema{
			Type: ValueString,
		},
	},

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

	Properties: Properties{
		"Serial": Schema{
			Type: ValueNumber,
		},

		"Status": Schema{
			Type: EnumValue{
				Description: "Status",
				Options:     []string{"Active", "Inactive"},
			},
			Default: "Active",
		},

		"UserName": Schema{
			Type:     ValueString,
			Required: constraints.Always,
		},
	},
}

Remove mandatory requirement for AccessKey.Status and add default


package metadata

// Restrict to Linux because, although omreport runs fine on Windows, the
// Windows metadata uses WMI to fetch this information.

import (
	"strings"

	"bosun.org/util"
)

func init() {
	metafuncs = append(metafuncs, collectMetadataOmreport)
}

func collectMetadataOmreport() {
	_ = util.ReadCommand(func(line string) error {
		fields := strings.Split(line, ";")
		if len(fields) != 2 {
			return nil
		}
		switch fields[0] {
		case "Chassis Service Tag":
			AddMeta("", nil, "svctag", fields[1], true)
		case "Chassis Model":
			AddMeta("", nil, "model", fields[1], true)
		}
		return nil
	}, "omreport", "chassis", "info", "-fmt", "ssv")
}

package metadata

// Restrict to Linux because, although omreport runs fine on Windows, the
// Windows metadata uses WMI to fetch this information.

import (
	"strings"

	"bosun.org/util"
)

func init() {
	metafuncs = append(metafuncs, collectMetadataOmreport)
}

func collectMetadataOmreport() {
	_ = util.ReadCommand(func(line string) error {
		fields := strings.Split(line, ";")
		if len(fields) != 2 {
			return nil
		}
		switch fields[0] {
		case "Chassis Service Tag":
			AddMeta("", nil, "serialNumber", fields[1], true)
		case "Chassis Model":
			AddMeta("", nil, "model", fields[1], true)
		}
		return nil
	}, "omreport", "chassis", "info", "-fmt", "ssv")
}

Change dell svctag metakey to be serialNumber


package parse

import (
	"bytes"
	"io"
	"testing"

	"github.com/tdewolff/test"
)

func TestPosition(t *testing.T) {
	var newlineTests = []struct {
		pos  int
		s    string
		line int
		col  int
		err  error
	}{
		{0, "x", 1, 1, nil},
		{1, "xx", 1, 2, nil},
		{2, "x\nx", 2, 1, nil},
		{2, "\n\nx", 3, 1, nil},
		{3, "\nxxx", 2, 3, nil},
		{2, "\r\nx", 2, 1, nil},

		// edge cases
		{0, "", 1, 1, io.EOF},
		{0, "\n", 1, 1, nil},
		{1, "\r\n", 1, 2, nil},
		{-1, "x", 1, 2, io.EOF},
	}
	for _, nt := range newlineTests {
		t.Run(nt.s, func(t *testing.T) {
			r := bytes.NewBufferString(nt.s)
			line, col, err := Pos(r, nt.pos)

			test.Error(t, err, nt.err)
			test.Int(t, line, nt.line, "line")
			test.Int(t, col, nt.col, "col")
		})
	}
}

package parse

import (
	"bytes"
	"io"
	"testing"

	"github.com/tdewolff/test"
)

func TestPosition(t *testing.T) {
	var newlineTests = []struct {
		pos  int
		s    string
		line int
		col  int
		err  error
	}{
		{0, "x", 1, 1, nil},
		{1, "xx", 1, 2, nil},
		{2, "x\nx", 2, 1, nil},
		{2, "\n\nx", 3, 1, nil},
		{3, "\nxxx", 2, 3, nil},
		{2, "\r\nx", 2, 1, nil},

		// edge cases
		{0, "", 1, 1, io.EOF},
		{0, "\n", 1, 1, nil},
		{1, "\r\n", 1, 2, nil},
		{-1, "x", 1, 2, io.EOF},
	}
	for _, nt := range newlineTests {
		t.Run(nt.s, func(t *testing.T) {
			r := bytes.NewBufferString(nt.s)
			line, col, err := Pos(r, nt.pos)

			test.Error(t, err, nt.err)
			test.V(t, "line", line, nt.line)
			test.V(t, "column", col, nt.col)
		})
	}
}

Update position test to use test.V


package fs

import (
	"time"
)

var vfs map[string]*Item

type Item struct {
	Contents  string
	Dir       bool
	User      string
	Group     string
	Mode      uint
	CreatedAt time.Time
	UpdatedAt time.Time
}

func init() {
	now := time.Now()
	vfs = map[string]*Item{
		"/": &Item{
			Contents:  "",
			Dir:       true,
			User:      "root",
			Group:     "root",
			Mode:      777,
			CreatedAt: now,
			UpdatedAt: now,
		},
		"/README": &Item{
			Contents:  "Welcomeeeeee!",
			Dir:       false,
			User:      "root",
			Group:     "root",
			Mode:      777,
			CreatedAt: now,
			UpdatedAt: now,
		},
	}
}

package fs

import (
	"time"
)

var vfs map[string]*Item

type Item struct {
	Contents  string
	Dir       bool
	User      string
	Group     string
	Mode      uint
	CreatedAt time.Time
	UpdatedAt time.Time
}

func init() {
	now := time.Now()
	vfs = map[string]*Item{
		"/": &Item{
			Contents:  "",
			Dir:       true,
			User:      "root",
			Group:     "root",
			Mode:      644,
			CreatedAt: now,
			UpdatedAt: now,
		},
		"/README": &Item{
			Contents:  "Welcomeeeeee!",
			Dir:       false,
			User:      "root",
			Group:     "root",
			Mode:      644,
			CreatedAt: now,
			UpdatedAt: now,
		},
	}
}

Change default mode on files that won't exist much longer.


// +build appengine

package main

import (
	"net/http"
	"time"

	_ "gnd.la/admin"                 // required for make-assets command
	_ "gnd.la/cache/driver/memcache" // enable memcached cache driver
	_ "gnd.la/orm/driver/gcs"        // enable Google Could Storage blobstore driver
	// Uncomment the following line to use Google Cloud SQL
	//_ "gnd.la/orm/driver/mysql"
)

var (
	wg sync.WaitGroup
)

func _app_engine_app_init() {
	// Make sure App is initialized before the rest
	// of this function runs.
	for App == nil {
		time.Sleep(5 * time.Millisecond)
	}
	if err := App.Prepare(); err != nil {
		panic(err)
	}
	http.Handle("/", App)
	wg.Done()
}

// Only executed on the development server. Required for
// precompiling assets.
func main() {
	wg.Wait()
}

func init() {
	wg.Add(1)
	go _app_engine_app_init()
}

// +build appengine

package main

import (
	"net/http"
	"time"

	_ "gnd.la/admin"                 // required for make-assets command
	_ "gnd.la/cache/driver/memcache" // enable memcached cache driver
	_ "gnd.la/orm/blobstore/gcs"     // enable Google Could Storage blobstore driver
	// Uncomment the following line to use Google Cloud SQL
	//_ "gnd.la/orm/driver/mysql"
)

var (
	wg sync.WaitGroup
)

func _app_engine_app_init() {
	// Make sure App is initialized before the rest
	// of this function runs.
	for App == nil {
		time.Sleep(5 * time.Millisecond)
	}
	if err := App.Prepare(); err != nil {
		panic(err)
	}
	http.Handle("/", App)
	wg.Done()
}

// Only executed on the development server. Required for
// precompiling assets.
func main() {
	wg.Wait()
}

func init() {
	wg.Add(1)
	go _app_engine_app_init()
}

Fix import path for blobstore gcs driver in project template


/*
Copyright 2015 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.
*/

// go-to-protobuf generates a Protobuf IDL from a Go struct, respecting any
// existing IDL tags on the Go struct.
package main

import (
	"k8s.io/code-generator/cmd/go-to-protobuf/protobuf"

	flag "github.com/spf13/pflag"
)

var g = protobuf.New()

func init() {
	g.BindFlags(flag.CommandLine)
}

func main() {
	flag.Parse()
	protobuf.Run(g)
}

/*
Copyright 2015 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.
*/

// go-to-protobuf generates a Protobuf IDL from a Go struct, respecting any
// existing IDL tags on the Go struct.
package main

import (
	goflag "flag"

	flag "github.com/spf13/pflag"
	"k8s.io/code-generator/cmd/go-to-protobuf/protobuf"
)

var g = protobuf.New()

func init() {
	g.BindFlags(flag.CommandLine)
	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
}

func main() {
	flag.Parse()
	protobuf.Run(g)
}

Add go flags to go-to-protobuf


package jobs

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"

	"github.com/Yu-taro/taue/taue/models"
)

func postSlack(users []models.User) {
	webHookURL := "https://hooks.slack.com/services/" + os.Getenv("SLACK_WEBHOOK_ENDPOINT")

	var text string
	for _, user := range users {
		text = "@" + user.SlackName + " " + strconv.Itoa(user.TodayContributs()) + "回\n"
	}

	parameters := models.SlackParameters{
		Text:      text,
		Username:  "taue",
		IconEmoji: ":seedling:",
		IconURL:   "",
		Channel:   "#general",
		LinkNames: 1,
	}

	params, _ := json.Marshal(parameters)

	value := url.Values{"payload": {string(params)}}
	resp, err := http.PostForm(webHookURL, value)

	if err != nil {
		return
	}

	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	fmt.Println(string(body))

}

package jobs

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"

	"github.com/Yu-taro/taue/taue/models"
)

func postSlack(users []models.User) {
	webHookURL := "https://hooks.slack.com/services/" + os.Getenv("SLACK_WEBHOOK_ENDPOINT")

	var text string
	for _, user := range users {
		text = "@" + user.SlackName + " " + strconv.Itoa(user.TodayContributs()) + "回\n"
	}

	parameters := models.SlackParameters{
		Text:      text,
		Username:  "taue",
		IconEmoji: ":seedling:",
		IconURL:   "",
		Channel:   "",
		LinkNames: 1,
	}

	params, _ := json.Marshal(parameters)

	value := url.Values{"payload": {string(params)}}
	resp, err := http.PostForm(webHookURL, value)

	if err != nil {
		return
	}

	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	fmt.Println(string(body))

}

Fix select general channel on slack


package main

import "fmt"

func main() {
	fmt.Println("hello world")

}

package main

import (
	"fmt"

	slackPkg "github.com/nlopes/slack"
)

func main() {
	fmt.Println("hello world")
	api := slackPkg.New("Your-Token")
	Users, err := api.GetUsers()
	if err != nil {
		fmt.Printf("Get Slack users info failed: %v", err)
	}
	for _, user := range Users {
		fmt.Println(user.Profile.Email, user.ID)
	}
	Channels, err := api.GetChannels(true)
	if err != nil {
		fmt.Printf("Get Slack channels info failed: %v", err)
	}
	for _, channel := range Channels {
		fmt.Println(channel.Name, channel.ID)
	}

}

Add slack token test function


package channels

import "testing"

func TestInfiniteChannel(t *testing.T) {
	var ch Channel

	ch = NewInfiniteChannel()
	testChannel(t, "infinite channel", ch)

	ch = NewInfiniteChannel()
	testChannelPair(t, "infinite channel", ch, ch)
}

func BenchmarkInfiniteChannelSerial(b *testing.B) {
	ch := NewInfiniteChannel()
	for i := 0; i < b.N; i++ {
		ch.In() <- nil
	}
	for i := 0; i < b.N; i++ {
		<-ch.Out()
	}
}

func BenchmarkInfiniteChannelParallel(b *testing.B) {
	ch := NewInfiniteChannel()
	go func() {
		for i := 0; i < b.N; i++ {
			<-ch.Out()
		}
		ch.Close()
	}()
	for i := 0; i < b.N; i++ {
		ch.In() <- nil
	}
	<-ch.Out()
}

func BenchmarkInfiniteChannelTickTock(b *testing.B) {
	ch := NewInfiniteChannel()
	for i := 0; i < b.N; i++ {
		ch.In() <- nil
		<-ch.Out()
	}
}

Add two more benchmark styles


package tests

import (
	"fmt"
	networking "git.cyberdust.com/radicalapp/go-networking"
	"testing"
)

func TestGetConnection(t *testing.T) {
	urlString := "https://jsonplaceholder.typicode.com/posts"
	params := networking.NewParams()
	connection := networking.NewConnection(urlString, params)

	connection.OnReceived = func(response []byte) {
		fmt.Println("Response: !!! ", string(response))
	}

	connection.GET()
}

//func TestPostConnection(t *testing.T) {
//
//}

//func TestUploadConnection(t *testing.T) {
//
//}

//connection := networking.NewConnection(url).WithParams(params).WithCompletion(completion).WithOnReveived(received).GET()

package tests

import (
	"fmt"
	networking "git.cyberdust.com/radicalapp/go-networking"
	"testing"
)

func TestGetConnection(t *testing.T) {
	urlString := "https://jsonplaceholder.typicode.com/posts"
	params := networking.NewParams()
	connection := networking.NewConnection(urlString, params)

	connection.OnReceived = func(response []byte) {
		fmt.Println("Response: !!! ", string(response))
	}
	connection.OnError = func (err error) {
		t.Error("Error in GET request for url: ", urlString)
		t.Fail()
	}

	connection.GET()
}

func TestPostConnection(t *testing.T) {
	urlString := "https://jsonplaceholder.typicode.com/posts"

	params := networking.NewParams()
	params.PutString("title", "foo")
	params.PutString("body", "bar")
	params.PutInt("userId", 1)

	connection := networking.NewConnection(urlString, params)
	connection.OnReceived = func (response []byte) {
		fmt.Println("Response: !!! ", string(response))
	}
	connection.OnError = func (err error) {
		t.Error("Error in POST request for url: ", urlString)
		t.Fail()
	}
	connection.POST()

}

Add test cases for GET and POST


package psql

import (
	"errors"

	_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/postgres"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var (
	DB      *gorm.DB
	DBError error
)

func init() {
	cobra.OnInitialize(ConnectDB)
}

func ConnectDB() {
	viper.SetDefault("database_scheme", "postgres")
	scheme := viper.GetString("database_scheme")
	url := viper.GetString("database_url")

	if len(url) == 0 {
		DBError = errors.New("Missing database_url")
	} else {
		if scheme != "postgres" {
			gorm.RegisterDialect(scheme, gorm.DialectsMap["postgres"])
		}
		DB, DBError = gorm.Open(scheme, url)
	}
}

package psql

import (
	"errors"

	"database/sql/driver"
	"encoding/json"
	_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/postgres"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var (
	DB      *gorm.DB
	DBError error
)

func init() {
	cobra.OnInitialize(ConnectDB)
}

func ConnectDB() {
	viper.SetDefault("database_scheme", "postgres")
	scheme := viper.GetString("database_scheme")
	url := viper.GetString("database_url")

	if len(url) == 0 {
		DBError = errors.New("Missing database_url")
	} else {
		if scheme != "postgres" {
			gorm.RegisterDialect(scheme, gorm.DialectsMap["postgres"])
		}
		DB, DBError = gorm.Open(scheme, url)

	}
}

type JsonB map[string]interface{}

func (j JsonB) Value() (driver.Value, error) {
	return json.Marshal(j)
}
func (j *JsonB) Scan(src interface{}) error {
	source, ok := src.([]byte)
	if !ok {
		return errors.New("Type assertion .([]byte) failed.")
	}

	var i interface{}
	err := json.Unmarshal(source, &i)
	if err != nil {
		return err
	}

	*j, ok = i.(map[string]interface{})
	if !ok {
		return errors.New("Type assertion .(map[string]interface{}) failed.")
	}

	return nil
}

Introduce type for parsing jsonb


// Package pu makes solving projecteuler problems easier and reduces boilerplate.
package pu

import (
	"fmt"
	"testing"

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

// Problem is a Project Euler (.net) problem
type Problem struct {
	// ID is the id of the problem on projecteuler.net
	ID int
	// Solver is the function which solves the problem.
	Solver func() string
	// CorrectAnswer is the answer to the problem (used for testing purposes)
	CorrectAnswer string
	// Attempts is the count of submissions to projecteuler.net it took to submit the correct answer.
	Attempts int
}

// Bench benchmarks the problem. Great for testing for improvements.
func (p Problem) Bench(b *testing.B) {
	for i := 0; i < b.N; i++ {
		p.Solver()
	}
}

// Answer prints out the answer for viewing.
func (p Problem) Answer() {
	if p.CorrectAnswer == "NA" {
		fmt.Println("Problem", p.ID, "has not been solved yet.")
	} else {
		fmt.Println("Answer to problem", p.ID, "is", p.Solver())
	}
}

// Test ensures the answer is correct. Will fail until problem is solved.
func (p Problem) Test(t *testing.T) {
	assert.Equal(t, p.CorrectAnswer, p.Solver(), "These should be equal. Either it hasn't been solved or something broke.")
}

// Package pu makes solving projecteuler problems easier and reduces boilerplate.
package pu

import (
	"fmt"
	"testing"

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

// Problem is a Project Euler (.net) problem
type Problem struct {
	// ID is the id of the problem on projecteuler.net
	ID int
	// Solver is the function which solves the problem.
	Solver func() string
	// CorrectAnswer is the answer to the problem (used for testing purposes)
	CorrectAnswer string
	// Attempts is the count of submissions to projecteuler.net it took to submit the correct answer.
	Attempts int
}

// Bench benchmarks the problem. Great for testing for improvements.
func (p Problem) Bench(b *testing.B) {
	for i := 0; i < b.N; i++ {
		p.Solver()
	}
}

// Answer prints out the answer for viewing.
func (p Problem) Answer() {
	if p.CorrectAnswer == "NA" {
		fmt.Println("Problem", p.ID, "has not been solved yet.")
	} else {
		fmt.Println("Answer to problem", p.ID, "is", p.Solver(), "(took", p.Attempts, "attempts)")
	}
}

// Test ensures the answer is correct. Will fail until problem is solved.
func (p Problem) Test(t *testing.T) {
	assert.Equal(t, p.CorrectAnswer, p.Solver(), "These should be equal. Either it hasn't been solved or something broke.")
}

Include attempts when printing answer


package main

import (
	"fmt"

	"github.com/almighty/almighty-core/app"
	"github.com/almighty/almighty-core/swagger"
	"github.com/goadesign/goa"
	"github.com/goadesign/goa/middleware"
)

var (
	// Commit current build commit set by build script
	Commit string
	// BuildTime set by build script
	BuildTime string
)

func main() {
	// Create service
	service := goa.New("API")

	// Setup middleware
	service.Use(middleware.RequestID())
	service.Use(middleware.LogRequest(true))
	service.Use(middleware.ErrorHandler(service, true))
	service.Use(middleware.Recover())

	// Mount "version" controller
	c := NewVersionController(service)
	app.MountVersionController(service, c)
	// Mount Swagger spec provider controller
	swagger.MountController(service)

	fmt.Println("Git Commit SHA: ", Commit)
	fmt.Println("UTC Build Time: ", BuildTime)

	service.ListenAndServe(":8080")
}

package main

import (
	"fmt"

	"github.com/almighty/almighty-core/app"
	"github.com/almighty/almighty-core/swagger"
	"github.com/goadesign/goa"
	"github.com/goadesign/goa/middleware"
)

var (
	// Commit current build commit set by build script
	Commit = "0"
	// BuildTime set by build script
	BuildTime = "0"
)

func main() {
	// Create service
	service := goa.New("API")

	// Setup middleware
	service.Use(middleware.RequestID())
	service.Use(middleware.LogRequest(true))
	service.Use(middleware.ErrorHandler(service, true))
	service.Use(middleware.Recover())

	// Mount "version" controller
	c := NewVersionController(service)
	app.MountVersionController(service, c)
	// Mount Swagger spec provider controller
	swagger.MountController(service)

	fmt.Println("Git Commit SHA: ", Commit)
	fmt.Println("UTC Build Time: ", BuildTime)

	service.ListenAndServe(":8080")
}

Add default values to Build variables


package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof" // import for side effects

	"github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/hello/{name}", helloHandler)

	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	args := mux.Vars(r)
	fmt.Fprintf(w, "Hello %s!", args["name"])
}

package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof" // import for side effects

	"encoding/json"
	"github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/hello/{name}", helloHandler)
	r.HandleFunc("/add_job", jobHandler)

	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	args := mux.Vars(r)
	fmt.Fprintf(w, "Hello %s!", args["name"])
}

func jobHandler(w http.ResponseWriter, r *http.Request) {
	var d audioData

	if err := json.NewDecoder(r.Body).Decode(&d); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	json.NewEncoder(w).Encode(d)
}

type audioData struct {
	AudioURL string `json:"audioURL"`
}

Add /add_job endpoint which takes a POST containing just a audio url (for now)


// Package src scans directory trees for source code packages.
package srcscan

// test imports
import _ "github.com/kr/pretty"

Add test imports in non-test code so that `go get` picks them up


package main

import (
	"testing"
	. "github.com/onsi/gomega"
)

func TestNewURL(t *testing.T) {
	httpsUrl, err := NewURL("https://github.com/motemen/pusheen-explorer")
	Expect(httpsUrl.String()).To(Equal("https://github.com/motemen/pusheen-explorer"))
	Expect(err).To(BeNil())

	sshUrl, err := NewURL("git@github.com:motemen/pusheen-explorer.git")
	Expect(sshUrl.String()).To(Equal("ssh://git@github.com/motemen/pusheen-explorer.git"))
	Expect(err).To(BeNil())
}

package main

import (
	"testing"
	. "github.com/onsi/gomega"
)

func TestNewURL(t *testing.T) {
	RegisterTestingT(t)

	httpsUrl, err := NewURL("https://github.com/motemen/pusheen-explorer")
	Expect(httpsUrl.String()).To(Equal("https://github.com/motemen/pusheen-explorer"))
	Expect(httpsUrl.Host).To(Equal("github.com"))
	Expect(err).To(BeNil())

	sshUrl, err := NewURL("git@github.com:motemen/pusheen-explorer.git")
	Expect(sshUrl.String()).To(Equal("ssh://git@github.com/motemen/pusheen-explorer.git"))
	Expect(sshUrl.Host).To(Equal("github.com"))
	Expect(err).To(BeNil())
}

Fix test to run `url_tesg.go`


package cli

import (
	"bytes"
	"testing"
)

func TestFlagC(t *testing.T) {
	var in, out, err bytes.Buffer
	c := CLI{
		In:  &in,
		Out: &out,
		Err: &err,
	}
	args := []string{"-c", "echo aaa"}
	code := c.Run(args)
	if code != 0 {
		t.Errorf("Run: got %v, want %v", code, 0)
	}
	if got, want := out.String(), "aaa\n"; got != want {
		t.Errorf("output: got %v, want %v", got, want)
	}
}

func TestArgs(t *testing.T) {
	var in, out, err bytes.Buffer
	c := CLI{
		In:  &in,
		Out: &out,
		Err: &err,
	}
	args := []string{"testdata/basic.coco"}
	code := c.Run(args)
	if code != 0 {
		t.Errorf("Run: got %v, want %v", code, 0)
	}
	if got, want := out.String(), "aaa\nbbb\n"; got != want {
		t.Errorf("output: got %v, want %v", got, want)
	}
}

package cli

import (
	"bytes"
	"testing"
)

func TestFlagC(t *testing.T) {
	var in, out, err bytes.Buffer
	c := CLI{
		In:  &in,
		Out: &out,
		Err: &err,
	}
	args := []string{"-c", "echo aaa"}
	code := c.Run(args)
	if code != 0 {
		t.Errorf("Run: got %v, want %v", code, 0)
	}
	if got, want := out.String(), "aaa\n"; got != want {
		t.Errorf("output: got %v, want %v", got, want)
	}
	if e := err.String(); e != "" {
		t.Errorf("error: %v", e)
	}
}

func TestArgs(t *testing.T) {
	var in, out, err bytes.Buffer
	c := CLI{
		In:  &in,
		Out: &out,
		Err: &err,
	}
	args := []string{"testdata/basic.coco"}
	code := c.Run(args)
	if code != 0 {
		t.Errorf("Run: got %v, want %v", code, 0)
	}
	if got, want := out.String(), "aaa\nbbb\n"; got != want {
		t.Errorf("output: got %v, want %v", got, want)
	}
	if e := err.String(); e != "" {
		t.Errorf("error: %v", e)
	}
}

Print error if it exists


// +build darwin freebsd linux netbsd openbsd

package flags

import (
	"syscall"
	"unsafe"
)

type winsize struct {
	ws_row, ws_col       uint16
	ws_xpixel, ws_ypixel uint16
}

func getTerminalColumns() int {
	ws := winsize{}

	syscall.Syscall(syscall.SYS_IOCTL,
		uintptr(0),
		uintptr(0x5413),
		uintptr(unsafe.Pointer(&ws)))

	return int(ws.ws_col)
}

// +build darwin freebsd linux netbsd openbsd

package flags

import (
	"syscall"
	"unsafe"
)

// #include <sys/ioctl.h>
// enum { _GO_TIOCGWINSZ = TIOCGWINSZ };
import "C"

type winsize struct {
	ws_row, ws_col       uint16
	ws_xpixel, ws_ypixel uint16
}

func getTerminalColumns() int {
	ws := winsize{}

	syscall.Syscall(syscall.SYS_IOCTL,
		uintptr(0),
		uintptr(C._GO_TIOCGWINSZ),
		uintptr(unsafe.Pointer(&ws)))

	return int(ws.ws_col)
}

Use the TIOCGWINSZ macro from C to determine correct value of option


package types

const (
	ZigbeeCertificationType string = "zigbee"
	MatterCertificationType string = "matter"
)

//	List of Certification Types
type CertificationTypes []string

var CertificationTypesList = CertificationTypes{ZigbeeCertificationType, MatterCertificationType}

func IsValidCertificationType(certificationType string) bool {
	for _, i := range CertificationTypesList {
		if i == certificationType {
			return true
		}
	}

	return false
}

const (
	CodeProvisional uint32 = 1
	CodeCertified   uint32 = 2
	CodeRevoked     uint32 = 3
)

const (
	ParentPFCCertificationRoute  = "parent"
	ChildPFCCertificationRoute   = "child"
	DefaultPFCCertificationRoute = ""
)

// List of PFC Certification Routes.
type PFCCertificationRoutes []string

var PFCCertificationRouteList = PFCCertificationRoutes{ParentPFCCertificationRoute, ChildPFCCertificationRoute, DefaultPFCCertificationRoute}

func IsValidPFCCertificationRoute(certificationRoute string) bool {
	for _, i := range PFCCertificationRouteList {
		if i == certificationRoute {
			return true
		}
	}

	return false
}

package types

const (
	ZigbeeCertificationType string = "zigbee"
	MatterCertificationType string = "matter"
	AccessControlType       string = "access control"
	ProductSecurityType     string = "product security"
)

//	List of Certification Types
type CertificationTypes []string

var CertificationTypesList = CertificationTypes{ZigbeeCertificationType, MatterCertificationType, AccessControlType, ProductSecurityType}

func IsValidCertificationType(certificationType string) bool {
	for _, i := range CertificationTypesList {
		if i == certificationType {
			return true
		}
	}

	return false
}

const (
	CodeProvisional uint32 = 1
	CodeCertified   uint32 = 2
	CodeRevoked     uint32 = 3
)

const (
	ParentPFCCertificationRoute  = "parent"
	ChildPFCCertificationRoute   = "child"
	DefaultPFCCertificationRoute = ""
)

// List of PFC Certification Routes.
type PFCCertificationRoutes []string

var PFCCertificationRouteList = PFCCertificationRoutes{ParentPFCCertificationRoute, ChildPFCCertificationRoute, DefaultPFCCertificationRoute}

func IsValidPFCCertificationRoute(certificationRoute string) bool {
	for _, i := range PFCCertificationRouteList {
		if i == certificationRoute {
			return true
		}
	}

	return false
}

Add new CertificationTypes for section compliance


package main

import (
	"os"

	"github.com/nsf/termbox-go"
)

type Lesser struct {
	file *os.File
}

func (l Lesser) Run() {
	for {
		e := termbox.PollEvent()
		switch e.Type {
		case termbox.EventKey:
			switch e.Ch {
			case 'q':
				return
			}
		}
	}
}

func NewLesser(f *os.File) Lesser {
	return Lesser{file: f}
}

package main

import (
	"os"

	"github.com/nsf/termbox-go"
)

type Event int

const (
	EventQuit Event = iota
)

type Lesser struct {
	file *os.File

	events chan Event
}

func (l Lesser) listenEvents() {
	for {
		e := termbox.PollEvent()
		switch e.Type {
		case termbox.EventKey:
			switch e.Ch {
			case 'q':
				l.events <- EventQuit
			}
		}
	}
}

func (l Lesser) Run() {
	go l.listenEvents()

	select {
	case e := <-l.events:
		switch e {
		case EventQuit:
			return
		}
	}
}

func NewLesser(f *os.File) Lesser {
	return Lesser{
		file:   f,
		events: make(chan Event, 1),
	}
}

Create a channel of Lesser events


package main

import (
	"fmt"

	"github.com/containerd/containerd/log"
	"github.com/urfave/cli"
)

var pullCommand = cli.Command{
	Name:      "pull",
	Usage:     "pull an image from a remote",
	ArgsUsage: "[flags] <ref>",
	Description: `Fetch and prepare an image for use in containerd.

After pulling an image, it should be ready to use the same reference in a run
command. As part of this process, we do the following:

1. Fetch all resources into containerd.
2. Prepare the snapshot filesystem with the pulled resources.
3. Register metadata for the image.
`,
	Flags: append(registryFlags, snapshotterFlags...),
	Action: func(clicontext *cli.Context) error {
		var (
			ref = clicontext.Args().First()
		)

		ctx, cancel := appContext(clicontext)
		defer cancel()

		img, err := fetch(ctx, ref, clicontext)
		if err != nil {
			return err
		}

		log.G(ctx).WithField("image", ref).Debug("unpacking")

		// TODO: Show unpack status
		fmt.Printf("unpacking %s...", img.Target().Digest)
		err = img.Unpack(ctx, clicontext.String("snapshotter"))
		fmt.Println("done")
		return err
	},
}

package main

import (
	"fmt"

	"github.com/containerd/containerd/log"
	"github.com/urfave/cli"
)

var pullCommand = cli.Command{
	Name:      "pull",
	Usage:     "pull an image from a remote",
	ArgsUsage: "[flags] <ref>",
	Description: `Fetch and prepare an image for use in containerd.

After pulling an image, it should be ready to use the same reference in a run
command. As part of this process, we do the following:

1. Fetch all resources into containerd.
2. Prepare the snapshot filesystem with the pulled resources.
3. Register metadata for the image.
`,
	Flags: append(registryFlags, snapshotterFlags...),
	Action: func(clicontext *cli.Context) error {
		var (
			ref = clicontext.Args().First()
		)

		ctx, cancel := appContext(clicontext)
		defer cancel()

		img, err := fetch(ctx, ref, clicontext)
		if err != nil {
			return err
		}

		log.G(ctx).WithField("image", ref).Debug("unpacking")

		// TODO: Show unpack status
		fmt.Printf("unpacking %s...\n", img.Target().Digest)
		err = img.Unpack(ctx, clicontext.String("snapshotter"))
		fmt.Println("done")
		return err
	},
}

Add newline char to avoid mix of logs


package main

import "crypto"
import "strings"

// Checksum algos
import (
    _ "crypto/md5"
    _ "crypto/sha1"
    _ "crypto/sha256"
    _ "crypto/sha512"
)

// Man, why don't people allow their table to be exported...
var checksumLookupTable = map[string]crypto.Hash{
    "md5":       crypto.MD5,
    "sha1":      crypto.SHA1,
    "sha256":    crypto.SHA256,
    "sha256sum": crypto.SHA256,
    "sha512":    crypto.SHA512,
}

var checksumAlgos = map[string]crypto.Hash{}

func filterChecksumAlgos() {
    i := strings.Split(checksums, ",")
    var j = map[string]crypto.Hash{}
    for _, checksum := range i {
        if checksumLookupTable[checksum].Available() == false {
            Error.Fatalln("Unsupported checksum algorithm: " + checksum)
        }
        j[checksum] = checksumLookupTable[checksum]
    }
    checksumLookupTable = j
}

package main

import "crypto"
import "strings"

// Checksum algos
import (
    _ "crypto/md5"
    _ "crypto/sha1"
    _ "crypto/sha256"
    _ "crypto/sha512"
)

// Man, why don't people allow their table to be exported...
var checksumLookupTable = map[string]crypto.Hash{
    "md5":       crypto.MD5,
    "sha1":      crypto.SHA1,
    "sha256":    crypto.SHA256,
    "sha512":    crypto.SHA512,
}

var checksumAlgos = map[string]crypto.Hash{}

func filterChecksumAlgos() {
    i := strings.Split(checksums, ",")
    var j = map[string]crypto.Hash{}
    for _, checksum := range i {
        if checksumLookupTable[checksum].Available() == false {
            Error.Fatalln("Unsupported checksum algorithm: " + checksum)
        }
        j[checksum] = checksumLookupTable[checksum]
    }
    checksumLookupTable = j
}

Format mismatch, can not use historic node name


package main

import (
	"encoding/json"
	"io"

	"github.com/hackebrot/turtle"
)

// JSONWriter writes Emojis as JSON
type JSONWriter struct {
	e *json.Encoder
}

// NewJSONWriter creates a new JSONWriter
func NewJSONWriter(w io.Writer) *JSONWriter {
	return &JSONWriter{e: json.NewEncoder(w)}
}

// WriteEmoji to an io.Writer
func (j *JSONWriter) WriteEmoji(emoji *turtle.Emoji) error {
	return j.e.Encode(emoji)
}

// WriteEmojis to an io.Writer
func (j *JSONWriter) WriteEmojis(emojis []*turtle.Emoji) error {
	return j.e.Encode(emojis)
}

package main

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/hackebrot/turtle"
)

// JSONWriter writes Emojis as JSON
type JSONWriter struct {
	e *json.Encoder
}

// NewJSONWriter creates a new JSONWriter
func NewJSONWriter(w io.Writer, options ...func(*JSONWriter) error) (*JSONWriter, error) {
	j := &JSONWriter{e: json.NewEncoder(w)}

	for _, option := range options {
		if err := option(j); err != nil {
			return nil, fmt.Errorf("error applying option: %v", err)
		}
	}

	return j, nil
}

// WithIndent sets an indent on  adds a separator to a thread
func WithIndent(prefix, indent string) func(*JSONWriter) error {
	return func(j *JSONWriter) error {
		j.e.SetIndent(prefix, indent)
		return nil
	}
}

// WriteEmoji to an io.Writer
func (j *JSONWriter) WriteEmoji(emoji *turtle.Emoji) error {
	return j.e.Encode(emoji)
}

// WriteEmojis to an io.Writer
func (j *JSONWriter) WriteEmojis(emojis []*turtle.Emoji) error {
	return j.e.Encode(emojis)
}

Implement JSONWriter option for indentation