<commit_before>package main

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"strings"
)

type part struct {
	Name  string
	Set   string
	Step  int
	Bpm   int
	Lanes matrix
}

type midiNote struct {
	Channel int
	Note    int
}

type noteMap map[string]midiNote

type drums struct {
	Sets []struct {
		Name string
		Kit  []struct {
			Key     string
			Channel int
			Note    int
		}
	}
	Parts []struct {
		Name  string
		Set   string
		Step  int
		Bpm   int
		Lanes []string
	}
	Seqs []struct {
		Name  string
		Parts []string
	}
}

func (d *drums) dump() {
	fmt.Println(*d)
}

func translateKit(set noteMap, s string) int {
	return set[s].Note
}

func text2matrix(set noteMap, txt []string) matrix {
	var m []row
	for _, line := range txt {
		var r []int
		lane := strings.Split(line, " ")
		for _, elem := range lane {
			r = append(r, translateKit(set, elem))
		}
		m = append(m, row(r))
	}
	return m
}

func (d *drums) getSeqs() map[string][]string {
	seqs := make(map[string][]string)
	for _, s := range d.Seqs {
		var seqparts []string
		for _, partname := range s.Parts {
			seqparts = append(seqparts, partname)
		}
		seqs[s.Name] = seqparts
	}
	return seqs
}

func (d *drums) getParts(sets map[string]noteMap) map[string]part {
	parts := make(map[string]part)
	var partsetname string
	var partset noteMap
	for _, inp := range d.Parts {
		if inp.Set == "" {
			partsetname = "default"
		} else {
			partsetname = inp.Set
		}
		if partset, ok := sets[partsetname]; !ok {
			logger.Printf("unknown set \"%s\"", partsetname)
		} else {
			debugf("getParts(): partset %v", partset)
		}
		parts[inp.Name] = part{
			Name:  inp.Name,
			Set:   inp.Set,
			Step:  inp.Step,
			Bpm:   inp.Bpm,
			Lanes: text2matrix(partset, inp.Lanes),
		}
		err := parts[inp.Name].Lanes.check()
		if err != nil {
			logger.Fatalf("part \"%s\" has wrong format: %v", inp.Name, err)
		}
	}
	return parts
}

func (d *drums) getSets() map[string]noteMap {
	sets := make(map[string]noteMap)
	for _, set := range d.Sets {
		debugf("getSets(): %+v", set)
		notes := make(noteMap)
		for _, note := range set.Kit {
			notes[note.Key] = midiNote{
				Channel: note.Channel,
				Note:    note.Note,
			}
			debugf("getSets(): %+v", note)
		}
		sets[set.Name] = notes
	}
	return sets
}

func (d *drums) loadFromFile(fn string) {
	data, err := ioutil.ReadFile(fn)
	if err != nil {
		logger.Fatalf("%v", err)
	}
	err = yaml.Unmarshal(data, d)
	if err != nil {
		logger.Fatalf("Syntax error when reading file \"%s\". Maybe it is not proper YAML format.\n%v", fn, err)
	}
}
<commit_msg>Revert "warn user about unknown sets"<commit_after>package main

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"strings"
)

type part struct {
	Name  string
	Set   string
	Step  int
	Bpm   int
	Lanes matrix
}

type midiNote struct {
	Channel int
	Note    int
}

type noteMap map[string]midiNote

type drums struct {
	Sets []struct {
		Name string
		Kit  []struct {
			Key     string
			Channel int
			Note    int
		}
	}
	Parts []struct {
		Name  string
		Set   string
		Step  int
		Bpm   int
		Lanes []string
	}
	Seqs []struct {
		Name  string
		Parts []string
	}
}

func (d *drums) dump() {
	fmt.Println(*d)
}

func translateKit(set noteMap, s string) int {
	return set[s].Note
}

func text2matrix(set noteMap, txt []string) matrix {
	var m []row
	for _, line := range txt {
		var r []int
		lane := strings.Split(line, " ")
		for _, elem := range lane {
			r = append(r, translateKit(set, elem))
		}
		m = append(m, row(r))
	}
	return m
}

func (d *drums) getSeqs() map[string][]string {
	seqs := make(map[string][]string)
	for _, s := range d.Seqs {
		var seqparts []string
		for _, partname := range s.Parts {
			seqparts = append(seqparts, partname)
		}
		seqs[s.Name] = seqparts
	}
	return seqs
}

func (d *drums) getParts(sets map[string]noteMap) map[string]part {
	parts := make(map[string]part)
	for _, inp := range d.Parts {
		var partset string
		if inp.Set == "" {
			partset = "default"
		} else {
			partset = inp.Set
		}
		parts[inp.Name] = part{
			Name:  inp.Name,
			Set:   inp.Set,
			Step:  inp.Step,
			Bpm:   inp.Bpm,
			Lanes: text2matrix(sets[partset], inp.Lanes),
		}
		err := parts[inp.Name].Lanes.check()
		if err != nil {
			logger.Fatalf("part \"%s\" has wrong format: %v", inp.Name, err)
		}
	}
	return parts
}

func (d *drums) getSets() map[string]noteMap {
	sets := make(map[string]noteMap)
	for _, set := range d.Sets {
		debugf("getSets(): %+v", set)
		notes := make(noteMap)
		for _, note := range set.Kit {
			notes[note.Key] = midiNote{
				Channel: note.Channel,
				Note:    note.Note,
			}
			debugf("getSets(): %+v", note)
		}
		sets[set.Name] = notes
	}
	return sets
}

func (d *drums) loadFromFile(fn string) {
	data, err := ioutil.ReadFile(fn)
	if err != nil {
		logger.Fatalf("%v", err)
	}
	err = yaml.Unmarshal(data, d)
	if err != nil {
		logger.Fatalf("Syntax error when reading file \"%s\". Maybe it is not proper YAML format.\n%v", fn, err)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"io"
	"io/ioutil"
	logpkg "log"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

type keygen func(t *testing.T) (pub, priv interface{}, name string)

func ed25519Keygen() keygen {
	return func(t *testing.T) (pub, priv interface{}, name string) {
		seed := make([]byte, ed25519.SeedSize)
		_, err := io.ReadFull(rand.Reader, seed)
		if err != nil {
			t.Fatal(err)
		}
		key := ed25519.NewKeyFromSeed(seed)
		return key.Public(), key, "ed25519"
	}
}

func ecKeygen(curve elliptic.Curve) keygen {
	return func(t *testing.T) (pub, priv interface{}, name string) {
		var key *ecdsa.PrivateKey
		key, err := ecdsa.GenerateKey(curve, rand.Reader)
		if err != nil {
			t.Fatal(err)
		}
		return key.Public(), key, curve.Params().Name
	}
}

func TestClientCert(t *testing.T) {
	algos := []keygen{
		ed25519Keygen(),
		ecKeygen(elliptic.P256()),
		ecKeygen(elliptic.P384()),
		ecKeygen(elliptic.P521()),
	}

	for _, algo := range algos {
		pub, priv, name := algo(t)
		testClientCert(t, pub, priv, name)
	}
}

func echo(w http.ResponseWriter, r *http.Request) {
	io.Copy(w, r.Body)
}

func testClientCert(t *testing.T, pub, priv interface{}, name string) {
	ca, err := generateAuthority(pub, priv)
	if err != nil {
		t.Error(err)
		return
	}
	keyBlock, err := marshalPrivateKey(ca.PrivateKey)
	if err != nil {
		t.Error(err)
		return
	}
	certBlock, err := createSignedClientCert(pub, ca.PrivateKey, ca.Cert)
	if err != nil {
		t.Error(err)
		return
	}
	keypair, err := tls.X509KeyPair(certBlock, keyBlock)
	if err != nil {
		t.Error(err)
		return
	}

	s := httptest.NewUnstartedServer(http.HandlerFunc(echo))
	s.TLS = &tls.Config{
		MinVersion: tls.VersionTLS12,
		ClientAuth: tls.RequireAndVerifyClientCert,
		ClientCAs:  x509.NewCertPool(),
	}
	s.TLS.ClientCAs.AddCert(ca.Cert)
	defer s.Close()
	s.StartTLS()

	client := s.Client()
	tr := client.Transport.(*http.Transport)
	tr.TLSClientConfig.Certificates = []tls.Certificate{keypair}

	req, err := http.NewRequest("PUT", s.URL, strings.NewReader("balls"))
	if err != nil {
		t.Error(err)
		return
	}
	resp, err := s.Client().Do(req)
	if err != nil {
		t.Errorf("algorithm %s: %v", name, err)
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Error(err)
		return
	}
	if !bytes.Equal(body, []byte("balls")) {
		t.Errorf("echo handler did not return expected result")
	}
}

func TestUntrustedClientCert(t *testing.T) {
	algo := ed25519Keygen()
	pub1, priv1, _ := algo(t) // trusted by server
	pub2, priv2, _ := algo(t) // presented by client

	ca1, err := generateAuthority(pub1, priv1)
	if err != nil {
		t.Error(err)
		return
	}

	ca2, err := generateAuthority(pub2, priv2)
	if err != nil {
		t.Error(err)
		return
	}
	keyBlock2, err := marshalPrivateKey(ca2.PrivateKey)
	if err != nil {
		t.Error(err)
		return
	}
	certBlock2, err := createSignedClientCert(pub2, ca2.PrivateKey, ca2.Cert)
	if err != nil {
		t.Error(err)
		return
	}
	keypair2, err := tls.X509KeyPair(certBlock2, keyBlock2)
	if err != nil {
		t.Error(err)
		return
	}

	s := httptest.NewUnstartedServer(http.HandlerFunc(echo))
	s.Config = &http.Server{
		// Don't log remote cert errors for this negative test
		ErrorLog: logpkg.New(ioutil.Discard, "", 0),
	}
	s.TLS = &tls.Config{
		MinVersion: tls.VersionTLS12,
		ClientAuth: tls.RequireAndVerifyClientCert,
		ClientCAs:  x509.NewCertPool(),
	}
	s.TLS.ClientCAs.AddCert(ca1.Cert)
	defer s.Close()
	s.StartTLS()

	client := s.Client()
	tr := client.Transport.(*http.Transport)
	tr.TLSClientConfig.Certificates = []tls.Certificate{keypair2}

	req, err := http.NewRequest("PUT", s.URL, strings.NewReader("balls"))
	if err != nil {
		t.Error(err)
		return
	}
	_, err = s.Client().Do(req)
	if err == nil {
		t.Errorf("request with bad client cert did not error")
		return
	}
	if !strings.HasSuffix(err.Error(), "tls: bad certificate") {
		t.Errorf("server did not report bad certificate error; "+
			"instead errored with: %v", err)
		return
	}
}
<commit_msg>x509: Fix false positive in untrusted cert test.<commit_after>// Copyright (c) 2020 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"context"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"io"
	"io/ioutil"
	logpkg "log"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

type keygen func(t *testing.T) (pub, priv interface{}, name string)

func ed25519Keygen() keygen {
	return func(t *testing.T) (pub, priv interface{}, name string) {
		seed := make([]byte, ed25519.SeedSize)
		_, err := io.ReadFull(rand.Reader, seed)
		if err != nil {
			t.Fatal(err)
		}
		key := ed25519.NewKeyFromSeed(seed)
		return key.Public(), key, "ed25519"
	}
}

func ecKeygen(curve elliptic.Curve) keygen {
	return func(t *testing.T) (pub, priv interface{}, name string) {
		var key *ecdsa.PrivateKey
		key, err := ecdsa.GenerateKey(curve, rand.Reader)
		if err != nil {
			t.Fatal(err)
		}
		return key.Public(), key, curve.Params().Name
	}
}

func TestClientCert(t *testing.T) {
	algos := []keygen{
		ed25519Keygen(),
		ecKeygen(elliptic.P256()),
		ecKeygen(elliptic.P384()),
		ecKeygen(elliptic.P521()),
	}

	for _, algo := range algos {
		pub, priv, name := algo(t)
		testClientCert(t, pub, priv, name)
	}
}

func echo(w http.ResponseWriter, r *http.Request) {
	io.Copy(w, r.Body)
}

func testClientCert(t *testing.T, pub, priv interface{}, name string) {
	ca, err := generateAuthority(pub, priv)
	if err != nil {
		t.Error(err)
		return
	}
	keyBlock, err := marshalPrivateKey(ca.PrivateKey)
	if err != nil {
		t.Error(err)
		return
	}
	certBlock, err := createSignedClientCert(pub, ca.PrivateKey, ca.Cert)
	if err != nil {
		t.Error(err)
		return
	}
	keypair, err := tls.X509KeyPair(certBlock, keyBlock)
	if err != nil {
		t.Error(err)
		return
	}

	s := httptest.NewUnstartedServer(http.HandlerFunc(echo))
	s.TLS = &tls.Config{
		MinVersion: tls.VersionTLS12,
		ClientAuth: tls.RequireAndVerifyClientCert,
		ClientCAs:  x509.NewCertPool(),
	}
	s.TLS.ClientCAs.AddCert(ca.Cert)
	defer s.Close()
	s.StartTLS()

	client := s.Client()
	tr := client.Transport.(*http.Transport)
	tr.TLSClientConfig.Certificates = []tls.Certificate{keypair}

	req, err := http.NewRequest("PUT", s.URL, strings.NewReader("balls"))
	if err != nil {
		t.Error(err)
		return
	}
	resp, err := s.Client().Do(req)
	if err != nil {
		t.Errorf("algorithm %s: %v", name, err)
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Error(err)
		return
	}
	if !bytes.Equal(body, []byte("balls")) {
		t.Errorf("echo handler did not return expected result")
	}
}

func TestUntrustedClientCert(t *testing.T) {
	algo := ed25519Keygen()
	pub1, priv1, _ := algo(t) // trusted by server
	pub2, priv2, _ := algo(t) // presented by client

	ca1, err := generateAuthority(pub1, priv1)
	if err != nil {
		t.Error(err)
		return
	}

	ca2, err := generateAuthority(pub2, priv2)
	if err != nil {
		t.Error(err)
		return
	}
	keyBlock2, err := marshalPrivateKey(ca2.PrivateKey)
	if err != nil {
		t.Error(err)
		return
	}
	certBlock2, err := createSignedClientCert(pub2, ca2.PrivateKey, ca2.Cert)
	if err != nil {
		t.Error(err)
		return
	}
	keypair2, err := tls.X509KeyPair(certBlock2, keyBlock2)
	if err != nil {
		t.Error(err)
		return
	}

	s := httptest.NewUnstartedServer(http.HandlerFunc(echo))
	s.Config = &http.Server{
		// Don't log remote cert errors for this negative test
		ErrorLog: logpkg.New(ioutil.Discard, "", 0),
	}
	s.TLS = &tls.Config{
		MinVersion: tls.VersionTLS12,
		ClientAuth: tls.RequireAndVerifyClientCert,
		ClientCAs:  x509.NewCertPool(),
	}
	s.TLS.ClientCAs.AddCert(ca1.Cert)
	defer s.Close()
	s.StartTLS()

	client := s.Client()
	tr := client.Transport.(*http.Transport)
	tr.TLSClientConfig.Certificates = []tls.Certificate{keypair2}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	errChan := make(chan error, 2)
	timeout := time.After(time.Second * 5)
	for {
		go func() {
			req, err := http.NewRequest("PUT", s.URL, strings.NewReader("test"))
			if err != nil {
				errChan <- err
				return
			}
			req = req.WithContext(ctx)
			_, err = s.Client().Do(req)
			errChan <- err
		}()

		select {
		case err := <-errChan:
			if err == nil {
				t.Fatalf("request with bad client cert did not error")
			}
			if strings.HasSuffix(err.Error(), "reset by peer") ||
				strings.Contains(err.Error(), "connection was forcibly closed") {

				// Retry.
				continue
			}
			if !strings.HasSuffix(err.Error(), "tls: bad certificate") {
				t.Fatalf("server did not report bad certificate error; "+
					"instead errored with: %v (%T)", err, err)
			}

			// Success.
			return

		case <-timeout:
			t.Fatal("Did not receive response before timeout")
		}
	}
}
<|endoftext|>


<commit_before>package feedloggr2

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

type FeedConfig struct {
	Title string
	URL   string
}

type Config struct {
	Verbose    bool
	Database   string
	OutputPath string
	Feeds      []*FeedConfig
}

func LoadConfig(path string) (*Config, error) {
	data, e := ioutil.ReadFile(path)
	if e != nil {
		return nil, e
	}
	c := &Config{}
	e = json.Unmarshal(data, &c)
	if e != nil {
		return nil, e
	}
	return c, nil
}

func SaveConfig(path string, c *Config) error {
	b, e := json.MarshalIndent(c, "", "    ")
	if e != nil {
		return e
	}

	e = ioutil.WriteFile(path, b, 0644)
	if e != nil {
		return e
	}
	return nil
}
<commit_msg>Add func for creating example config.<commit_after>package feedloggr2

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

type FeedConfig struct {
	Title string
	URL   string
}

type Config struct {
	Verbose    bool
	Database   string
	OutputPath string
	Feeds      []*FeedConfig
}

func NewConfig() *Config {
	c := &Config{
		Verbose:    true,
		Database:   ".feedloggr2.db",
		OutputPath: "feeds",
		Feeds: []*FeedConfig{
			&FeedConfig{"Title of feed", "https://example.com/rss"},
		},
	}

	return c
}

func LoadConfig(path string) (*Config, error) {
	data, e := ioutil.ReadFile(path)
	if e != nil {
		return nil, e
	}
	c := &Config{}
	e = json.Unmarshal(data, &c)
	if e != nil {
		return nil, e
	}
	return c, nil
}

func SaveConfig(path string, c *Config) error {
	b, e := json.MarshalIndent(c, "", "    ")
	if e != nil {
		return e
	}

	e = ioutil.WriteFile(path, b, 0644)
	if e != nil {
		return e
	}
	return nil
}
<|endoftext|>


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

package uuid

import (
	"encoding/binary"
	"time"
)

// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64

const (
	lillian    = 2299160          // Julian day of 15 Oct 1582
	unix       = 2440587          // Julian day of 1 Jan 1970
	epoch      = unix - lillian   // Days between epochs
	g1582      = epoch * 86400    // seconds between epochs
	g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)

var (
	lasttime  uint64 // last time we returned
	clock_seq uint16 // clock sequence for this run

	timeNow = time.Now // for testing
)

// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
	sec = int64(t - g1582ns100)
	nsec = (sec % 10000000) * 100
	sec /= 10000000
	return sec, nsec
}

// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// adjusts the clock sequence as needed.  An error is returned if the current
// time cannot be determined.
func GetTime() (Time, error) {
	t := timeNow()

	// If we don't have a clock sequence already, set one.
	if clock_seq == 0 {
		SetClockSequence(-1)
	}
	now := uint64(t.UnixNano()/100) + g1582ns100

	// If time has gone backwards with this clock sequence then we
	// increment the clock sequence
	if now <= lasttime {
		clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
	}
	lasttime = now
	return Time(now), nil
}

// ClockSequence returns the current clock sequence, generating one if not
// already set.  The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated.  Unless SetClockSequence a new random
// clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID.  (section 4.2.1.1) sequence is generated
// for
func ClockSequence() int {
	if clock_seq == 0 {
		SetClockSequence(-1)
	}
	return int(clock_seq & 0x3fff)
}

// SetClockSeq sets the clock sequence to the lower 14 bits of seq.  Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
	if seq == -1 {
		var b [2]byte
		randomBits(b[:]) // clock sequence
		seq = int(b[0])<<8 | int(b[1])
	}
	old_seq := clock_seq
	clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
	if old_seq != clock_seq {
		lasttime = 0
	}
}

// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid.  It returns false if uuid is not valid.  The time is only well defined
// for version 1 and 2 UUIDs.
func (uuid UUID) Time() (Time, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	time := int64(binary.BigEndian.Uint32(uuid[0:4]))
	time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
	time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
	return Time(time), true
}

// ClockSequence returns the clock sequence encoded in uuid.  It returns false
// if uuid is not valid.  The clock sequence is only well defined for version 1
// and 2 UUIDs.
func (uuid UUID) ClockSequence() (int, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
}
<commit_msg>Add locking around global time functions.<commit_after>// Copyright 2014 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"encoding/binary"
	"sync"
	"time"
)

// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64

const (
	lillian    = 2299160          // Julian day of 15 Oct 1582
	unix       = 2440587          // Julian day of 1 Jan 1970
	epoch      = unix - lillian   // Days between epochs
	g1582      = epoch * 86400    // seconds between epochs
	g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)

var (
	mu        sync.Mutex
	lasttime  uint64 // last time we returned
	clock_seq uint16 // clock sequence for this run

	timeNow = time.Now // for testing
)

// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
	sec = int64(t - g1582ns100)
	nsec = (sec % 10000000) * 100
	sec /= 10000000
	return sec, nsec
}

// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// adjusts the clock sequence as needed.  An error is returned if the current
// time cannot be determined.
func GetTime() (Time, error) {
	defer mu.Unlock()
	mu.Lock()
	return getTime()
}

func getTime() (Time, error) {

	t := timeNow()

	// If we don't have a clock sequence already, set one.
	if clock_seq == 0 {
		setClockSequence(-1)
	}
	now := uint64(t.UnixNano()/100) + g1582ns100

	// If time has gone backwards with this clock sequence then we
	// increment the clock sequence
	if now <= lasttime {
		clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
	}
	lasttime = now
	return Time(now), nil
}

// ClockSequence returns the current clock sequence, generating one if not
// already set.  The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated.  Unless SetClockSequence a new random
// clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID.  (section 4.2.1.1) sequence is generated
// for
func ClockSequence() int {
	defer mu.Unlock()
	mu.Lock()
	return clockSequence()
}

func clockSequence() int {
	if clock_seq == 0 {
		setClockSequence(-1)
	}
	return int(clock_seq & 0x3fff)
}

// SetClockSeq sets the clock sequence to the lower 14 bits of seq.  Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
	defer mu.Unlock()
	mu.Lock()
	setClockSequence(seq)
}

func setClockSequence(seq int) {
	if seq == -1 {
		var b [2]byte
		randomBits(b[:]) // clock sequence
		seq = int(b[0])<<8 | int(b[1])
	}
	old_seq := clock_seq
	clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
	if old_seq != clock_seq {
		lasttime = 0
	}
}

// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid.  It returns false if uuid is not valid.  The time is only well defined
// for version 1 and 2 UUIDs.
func (uuid UUID) Time() (Time, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	time := int64(binary.BigEndian.Uint32(uuid[0:4]))
	time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
	time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
	return Time(time), true
}

// ClockSequence returns the clock sequence encoded in uuid.  It returns false
// if uuid is not valid.  The clock sequence is only well defined for version 1
// and 2 UUIDs.
func (uuid UUID) ClockSequence() (int, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
}
<|endoftext|>


<commit_before>package libvirt

import (
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/common"
	commonssh "github.com/mitchellh/packer/common/ssh"
	"github.com/mitchellh/packer/helper/communicator"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

const BuilderId = "vtolstov.libvirt"

type Builder struct {
	config Config
	runner multistep.Runner
}

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	Comm                communicator.Config `mapstructure:",squash"`
	DomainType          string              `mapstructure:"domain_type"`
	BootCommand         []string            `mapstructure:"boot_command"`
	MemorySize          uint                `mapstructure:"memory_size"`
	Arch                string              `mapstructure:"arch"`
	DiskName            string              `mapstructure:"disk_name"`
	DiskType            string              `mapstructure:"disk_type"`
	DiskSize            uint                `mapstructure:"disk_size"`
	FloppyFiles         []string            `mapstructure:"floppy_files"`
	HTTPDir             string              `mapstructure:"http_directory"`
	HTTPPortMin         uint                `mapstructure:"http_port_min"`
	HTTPPortMax         uint                `mapstructure:"http_port_max"`
	ISOUrl              string              `mapstructure:"iso_url"`
	OutputDir           string              `mapstructure:"output_directory"`
	ShutdownCommand     string              `mapstructure:"shutdown_command"`
	SSHHostPortMin      uint                `mapstructure:"ssh_host_port_min"`
	SSHHostPortMax      uint                `mapstructure:"ssh_host_port_max"`
	SSHKeyPath          string              `mapstructure:"ssh_key_path"`
	SSHPassword         string              `mapstructure:"ssh_password"`
	SSHPort             uint                `mapstructure:"ssh_port"`
	SSHUser             string              `mapstructure:"ssh_username"`
	VMName              string              `mapstructure:"vm_name"`

	DomainXml   string `mapstructure:"domain_xml"`
	VolumeXml   string `mapstructure:"volume_xml"`
	PoolName    string `mapstructure:"pool_name"`
	PoolXml     string `mapstructure:"pool_xml"`
	NetworkName string `mapstructure:"network_name"`
	NetworkXml  string `mapstructure:"network_xml"`
	NetworkType string `mapstructure:"network_type"`
	LibvirtUrl  string `mapstructure:"libvirt_url"`

	RawBootWait        string `mapstructure:"boot_wait"`
	RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
	RawSSHWaitTimeout  string `mapstructure:"ssh_wait_timeout"`

	bootWait        time.Duration ``
	shutdownTimeout time.Duration ``
	sshWaitTimeout  time.Duration ``
	ctx             interpolate.Context
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	var errs *packer.MultiError
	warnings := make([]string, 0)

	err := config.Decode(&b.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &b.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
				"qemuargs",
			},
		},
	}, raws...)
	if err != nil {
		return nil, err
	}

	if b.config.MemorySize < 1 {
		b.config.MemorySize = "512"
	}

	if b.config.DomainType == "" {
		b.config.DomainType = "kvm"
	}

	if b.config.DiskType == "" {
		b.config.DiskType = "raw"
	}

	if b.config.DiskSize == 0 {
		b.config.DiskSize = 5000
	}

	if b.config.PoolXml == "" {
		b.config.PoolXml = PackerPool
	}

	if b.config.PoolName == "" {
		b.config.PoolName = "packer"
	}

	if b.config.NetworkName == "" {
		b.config.NetworkName = "packer"
	}

	if b.config.VolumeXml == "" {
		b.config.VolumeXml = PackerVolume
	}

	if b.config.NetworkType == "" {
		b.config.NetworkType = "user"
	}

	if b.config.NetworkType != "user" {
		if b.config.NetworkXml == "" {
			b.config.NetworkXml = PackerNetwork
		}
	}

	if b.config.DomainXml == "" {
		b.config.DomainXml = PackerQemuXML
	}

	if b.config.FloppyFiles == nil {
		b.config.FloppyFiles = make([]string, 0)
	}

	if b.config.HTTPPortMin == 0 {
		b.config.HTTPPortMin = 8000
	}

	if b.config.HTTPPortMax == 0 {
		b.config.HTTPPortMax = 9000
	}

	if b.config.OutputDir == "" {
		b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName)
	}

	if b.config.RawBootWait == "" {
		b.config.RawBootWait = "10s"
	}

	if b.config.SSHHostPortMin == 0 {
		b.config.SSHHostPortMin = 2222
	}

	if b.config.SSHHostPortMax == 0 {
		b.config.SSHHostPortMax = 4444
	}

	if b.config.SSHPort == 0 {
		b.config.SSHPort = 22
	}

	if b.config.VMName == "" {
		b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
	}

	if b.config.DiskName == "" {
		b.config.DiskName = b.config.VMName
	}

	/*
		// Errors
		templates := map[string]*string{
			"disk_name":        &b.config.DiskName,
			"http_directory":   &b.config.HTTPDir,
			"output_directory": &b.config.OutputDir,
			"shutdown_command": &b.config.ShutdownCommand,
			"ssh_password":     &b.config.SSHPassword,
			"ssh_username":     &b.config.SSHUser,
			"vm_name":          &b.config.VMName,
			"boot_wait":        &b.config.RawBootWait,
			"shutdown_timeout": &b.config.RawShutdownTimeout,
			"ssh_wait_timeout": &b.config.RawSSHWaitTimeout,
			"domain_xml":       &b.config.DomainXml,
			"volume_xml":       &b.config.VolumeXml,
			"pool_name":        &b.config.PoolName,
			"pool_xml":         &b.config.PoolXml,
			"network_name":     &b.config.NetworkName,
			"network_xml":      &b.config.NetworkXml,
		}
	*/
	b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed to parse iso_url: %s", err))
	}

	if b.config.HTTPPortMin > b.config.HTTPPortMax {
		errs = packer.MultiErrorAppend(
			errs, errors.New("http_port_min must be less than http_port_max"))
	}

	if !b.config.PackerForce {
		if _, err := os.Stat(b.config.OutputDir); err == nil {
			errs = packer.MultiErrorAppend(
				errs,
				fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir))
		}
	}

	b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
	}

	if b.config.RawShutdownTimeout == "" {
		b.config.RawShutdownTimeout = "5m"
	}

	if b.config.RawSSHWaitTimeout == "" {
		b.config.RawSSHWaitTimeout = "20m"
	}

	b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
	}

	if b.config.SSHKeyPath != "" {
		if _, err := os.Stat(b.config.SSHKeyPath); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("ssh_key_path is invalid: %s", err))
		} else if _, err := commonssh.FileSigner(b.config.SSHKeyPath); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("ssh_key_path is invalid: %s", err))
		}
	}

	if b.config.SSHHostPortMin > b.config.SSHHostPortMax {
		errs = packer.MultiErrorAppend(
			errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max"))
	}

	if b.config.SSHUser == "" && !strings.HasPrefix(b.config.LibvirtUrl, "lxc") {
		errs = packer.MultiErrorAppend(
			errs, errors.New("An ssh_username must be specified."))
	}

	b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err))
	}

	// Warnings
	if b.config.ShutdownCommand == "" {
		warnings = append(warnings,
			"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
				"will forcibly halt the virtual machine, which may result in data loss.")
	}

	if errs != nil && len(errs.Errors) > 0 {
		return warnings, errs
	}

	return warnings, nil
}

func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	// Check we have the required tools

	steps := []multistep.Step{
		new(stepPrepareOutputDir),
		&common.StepCreateFloppy{
			Files: b.config.FloppyFiles,
		},
		new(stepHTTPServer),
		new(stepCreatePool),
		new(stepCreateNetwork),
		new(stepCreateVolume),
		new(stepCreateDomain),
		new(stepRun),
		new(stepTypeBootCommand),
		&communicator.StepConnect{
			Config:    &b.config.Comm,
			Host:      commHost,
			SSHConfig: sshConfig,
			SSHPort:   commPort,
		},
		// can we upload any guest helpers?
		new(common.StepProvision),
		new(stepShutdown),
		// compact disk?
	}
	/*
	   ▶       ▶       new(stepDownloadVolume),
	   ▶       ▶       new(stepDeleteVolume),

	*/
	// Setup the state bag
	state := &multistep.BasicStateBag{}
	state.Put("cache", cache)
	state.Put("config", &b.config)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Run
	if b.config.PackerDebug {
		b.runner = &multistep.DebugRunner{
			Steps:   steps,
			PauseFn: common.MultistepDebugFn(ui),
		}
	} else {
		b.runner = &multistep.BasicRunner{Steps: steps}
	}

	b.runner.Run(state)

	// If there was an error, return that
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	// Compile the artifact list
	files := make([]string, 0, 5)
	visit := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			files = append(files, path)
		}

		return err
	}

	if err := filepath.Walk(b.config.OutputDir, visit); err != nil {
		return nil, err
	}

	artifact := &Artifact{
		name:  b.config.VMName,
		dir:   b.config.OutputDir,
		f:     files,
		state: make(map[string]interface{}),
	}

	artifact.state["diskType"] = b.config.DiskType
	artifact.state["diskSize"] = b.config.DiskSize
	artifact.state["domainType"] = "kvm"

	return artifact, nil
}

func (b *Builder) Cancel() {
	if b.runner != nil {
		log.Println("Cancelling the step runner...")
		b.runner.Cancel()
	}
}
<commit_msg>fix<commit_after>package libvirt

import (
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/common"
	commonssh "github.com/mitchellh/packer/common/ssh"
	"github.com/mitchellh/packer/helper/communicator"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

const BuilderId = "vtolstov.libvirt"

type Builder struct {
	config Config
	runner multistep.Runner
}

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	Comm                communicator.Config `mapstructure:",squash"`
	DomainType          string              `mapstructure:"domain_type"`
	BootCommand         []string            `mapstructure:"boot_command"`
	MemorySize          uint                `mapstructure:"memory_size"`
	Arch                string              `mapstructure:"arch"`
	DiskName            string              `mapstructure:"disk_name"`
	DiskType            string              `mapstructure:"disk_type"`
	DiskSize            uint                `mapstructure:"disk_size"`
	FloppyFiles         []string            `mapstructure:"floppy_files"`
	HTTPDir             string              `mapstructure:"http_directory"`
	HTTPPortMin         uint                `mapstructure:"http_port_min"`
	HTTPPortMax         uint                `mapstructure:"http_port_max"`
	ISOUrl              string              `mapstructure:"iso_url"`
	OutputDir           string              `mapstructure:"output_directory"`
	ShutdownCommand     string              `mapstructure:"shutdown_command"`
	SSHHostPortMin      uint                `mapstructure:"ssh_host_port_min"`
	SSHHostPortMax      uint                `mapstructure:"ssh_host_port_max"`
	SSHKeyPath          string              `mapstructure:"ssh_key_path"`
	SSHPassword         string              `mapstructure:"ssh_password"`
	SSHPort             uint                `mapstructure:"ssh_port"`
	SSHUser             string              `mapstructure:"ssh_username"`
	VMName              string              `mapstructure:"vm_name"`

	DomainXml   string `mapstructure:"domain_xml"`
	VolumeXml   string `mapstructure:"volume_xml"`
	PoolName    string `mapstructure:"pool_name"`
	PoolXml     string `mapstructure:"pool_xml"`
	NetworkName string `mapstructure:"network_name"`
	NetworkXml  string `mapstructure:"network_xml"`
	NetworkType string `mapstructure:"network_type"`
	LibvirtUrl  string `mapstructure:"libvirt_url"`

	RawBootWait        string `mapstructure:"boot_wait"`
	RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
	RawSSHWaitTimeout  string `mapstructure:"ssh_wait_timeout"`

	bootWait        time.Duration ``
	shutdownTimeout time.Duration ``
	sshWaitTimeout  time.Duration ``
	ctx             interpolate.Context
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	var errs *packer.MultiError
	warnings := make([]string, 0)

	err := config.Decode(&b.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &b.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
				"qemuargs",
			},
		},
	}, raws...)
	if err != nil {
		return nil, err
	}

	if b.config.MemorySize < 1 {
		b.config.MemorySize = 512
	}

	if b.config.DomainType == "" {
		b.config.DomainType = "kvm"
	}

	if b.config.DiskType == "" {
		b.config.DiskType = "raw"
	}

	if b.config.DiskSize == 0 {
		b.config.DiskSize = 5000
	}

	if b.config.PoolXml == "" {
		b.config.PoolXml = PackerPool
	}

	if b.config.PoolName == "" {
		b.config.PoolName = "packer"
	}

	if b.config.NetworkName == "" {
		b.config.NetworkName = "packer"
	}

	if b.config.VolumeXml == "" {
		b.config.VolumeXml = PackerVolume
	}

	if b.config.NetworkType == "" {
		b.config.NetworkType = "user"
	}

	if b.config.NetworkType != "user" {
		if b.config.NetworkXml == "" {
			b.config.NetworkXml = PackerNetwork
		}
	}

	if b.config.DomainXml == "" {
		b.config.DomainXml = PackerQemuXML
	}

	if b.config.FloppyFiles == nil {
		b.config.FloppyFiles = make([]string, 0)
	}

	if b.config.HTTPPortMin == 0 {
		b.config.HTTPPortMin = 8000
	}

	if b.config.HTTPPortMax == 0 {
		b.config.HTTPPortMax = 9000
	}

	if b.config.OutputDir == "" {
		b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName)
	}

	if b.config.RawBootWait == "" {
		b.config.RawBootWait = "10s"
	}

	if b.config.SSHHostPortMin == 0 {
		b.config.SSHHostPortMin = 2222
	}

	if b.config.SSHHostPortMax == 0 {
		b.config.SSHHostPortMax = 4444
	}

	if b.config.SSHPort == 0 {
		b.config.SSHPort = 22
	}

	if b.config.VMName == "" {
		b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
	}

	if b.config.DiskName == "" {
		b.config.DiskName = b.config.VMName
	}

	/*
		// Errors
		templates := map[string]*string{
			"disk_name":        &b.config.DiskName,
			"http_directory":   &b.config.HTTPDir,
			"output_directory": &b.config.OutputDir,
			"shutdown_command": &b.config.ShutdownCommand,
			"ssh_password":     &b.config.SSHPassword,
			"ssh_username":     &b.config.SSHUser,
			"vm_name":          &b.config.VMName,
			"boot_wait":        &b.config.RawBootWait,
			"shutdown_timeout": &b.config.RawShutdownTimeout,
			"ssh_wait_timeout": &b.config.RawSSHWaitTimeout,
			"domain_xml":       &b.config.DomainXml,
			"volume_xml":       &b.config.VolumeXml,
			"pool_name":        &b.config.PoolName,
			"pool_xml":         &b.config.PoolXml,
			"network_name":     &b.config.NetworkName,
			"network_xml":      &b.config.NetworkXml,
		}
	*/
	b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed to parse iso_url: %s", err))
	}

	if b.config.HTTPPortMin > b.config.HTTPPortMax {
		errs = packer.MultiErrorAppend(
			errs, errors.New("http_port_min must be less than http_port_max"))
	}

	if !b.config.PackerForce {
		if _, err := os.Stat(b.config.OutputDir); err == nil {
			errs = packer.MultiErrorAppend(
				errs,
				fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir))
		}
	}

	b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
	}

	if b.config.RawShutdownTimeout == "" {
		b.config.RawShutdownTimeout = "5m"
	}

	if b.config.RawSSHWaitTimeout == "" {
		b.config.RawSSHWaitTimeout = "20m"
	}

	b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
	}

	if b.config.SSHKeyPath != "" {
		if _, err := os.Stat(b.config.SSHKeyPath); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("ssh_key_path is invalid: %s", err))
		} else if _, err := commonssh.FileSigner(b.config.SSHKeyPath); err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("ssh_key_path is invalid: %s", err))
		}
	}

	if b.config.SSHHostPortMin > b.config.SSHHostPortMax {
		errs = packer.MultiErrorAppend(
			errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max"))
	}

	if b.config.SSHUser == "" && !strings.HasPrefix(b.config.LibvirtUrl, "lxc") {
		errs = packer.MultiErrorAppend(
			errs, errors.New("An ssh_username must be specified."))
	}

	b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout)
	if err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err))
	}

	// Warnings
	if b.config.ShutdownCommand == "" {
		warnings = append(warnings,
			"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
				"will forcibly halt the virtual machine, which may result in data loss.")
	}

	if errs != nil && len(errs.Errors) > 0 {
		return warnings, errs
	}

	return warnings, nil
}

func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	// Check we have the required tools

	steps := []multistep.Step{
		new(stepPrepareOutputDir),
		&common.StepCreateFloppy{
			Files: b.config.FloppyFiles,
		},
		new(stepHTTPServer),
		new(stepCreatePool),
		new(stepCreateNetwork),
		new(stepCreateVolume),
		new(stepCreateDomain),
		new(stepRun),
		new(stepTypeBootCommand),
		&communicator.StepConnect{
			Config:    &b.config.Comm,
			Host:      commHost,
			SSHConfig: sshConfig,
			SSHPort:   commPort,
		},
		// can we upload any guest helpers?
		new(common.StepProvision),
		new(stepShutdown),
		// compact disk?
	}
	/*
	   ▶       ▶       new(stepDownloadVolume),
	   ▶       ▶       new(stepDeleteVolume),

	*/
	// Setup the state bag
	state := &multistep.BasicStateBag{}
	state.Put("cache", cache)
	state.Put("config", &b.config)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Run
	if b.config.PackerDebug {
		b.runner = &multistep.DebugRunner{
			Steps:   steps,
			PauseFn: common.MultistepDebugFn(ui),
		}
	} else {
		b.runner = &multistep.BasicRunner{Steps: steps}
	}

	b.runner.Run(state)

	// If there was an error, return that
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	// Compile the artifact list
	files := make([]string, 0, 5)
	visit := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			files = append(files, path)
		}

		return err
	}

	if err := filepath.Walk(b.config.OutputDir, visit); err != nil {
		return nil, err
	}

	artifact := &Artifact{
		name:  b.config.VMName,
		dir:   b.config.OutputDir,
		f:     files,
		state: make(map[string]interface{}),
	}

	artifact.state["diskType"] = b.config.DiskType
	artifact.state["diskSize"] = b.config.DiskSize
	artifact.state["domainType"] = "kvm"

	return artifact, nil
}

func (b *Builder) Cancel() {
	if b.runner != nil {
		log.Println("Cancelling the step runner...")
		b.runner.Cancel()
	}
}
<|endoftext|>


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

package validator

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

// TextErr is an error that also implements the TextMarshaller interface for
// serializing out to various plain text encodings. Packages creating their
// own custom errors should use TextErr if they're intending to use serializing
// formats like json, msgpack etc.
type TextErr struct {
	Err error
}

// Error implements the error interface.
func (t TextErr) Error() string {
	return t.Err.Error()
}

// MarshalText implements the TextMarshaller
func (t TextErr) MarshalText() ([]byte, error) {
	return []byte(t.Err.Error()), nil
}

var (
	// ErrZeroValue is the error returned when variable has zero value
	// and nonzero or nonnil was specified
	ErrZeroValue = TextErr{errors.New("zero value")}
	// ErrMin is the error returned when variable is less than mininum
	// value specified
	ErrMin = TextErr{errors.New("less than min")}
	// ErrMax is the error returned when variable is more than
	// maximum specified
	ErrMax = TextErr{errors.New("greater than max")}
	// ErrLen is the error returned when length is not equal to
	// param specified
	ErrLen = TextErr{errors.New("invalid length")}
	// ErrRegexp is the error returned when the value does not
	// match the provided regular expression parameter
	ErrRegexp = TextErr{errors.New("regular expression mismatch")}
	// ErrUnsupported is the error error returned when a validation rule
	// is used with an unsupported variable type
	ErrUnsupported = TextErr{errors.New("unsupported type")}
	// ErrBadParameter is the error returned when an invalid parameter
	// is provided to a validation rule (e.g. a string where an int was
	// expected (max=foo,len=bar) or missing a parameter when one is required (len=))
	ErrBadParameter = TextErr{errors.New("bad parameter")}
	// ErrUnknownTag is the error returned when an unknown tag is found
	ErrUnknownTag = TextErr{errors.New("unknown tag")}
	// ErrInvalid is the error returned when variable is invalid
	// (normally a nil pointer)
	ErrInvalid = TextErr{errors.New("invalid value")}
	// ErrCannotValidate is the error returned when a struct is unexported
	ErrCannotValidate = TextErr{errors.New("cannot validate unexported struct")}
)

// ErrorMap is a map which contains all errors from validating a struct.
type ErrorMap map[string]ErrorArray

// ErrorMap implements the Error interface so we can check error against nil.
// The returned error is all existing errors with the map.
func (err ErrorMap) Error() string {
	var b bytes.Buffer

	for k, errs := range err {
		if len(errs) > 0 {
			b.WriteString(fmt.Sprintf("%s: %s, ", k, errs.Error()))
		}
	}

	return strings.TrimSuffix(b.String(), ", ")
}

// ErrorArray is a slice of errors returned by the Validate function.
type ErrorArray []error

// ErrorArray implements the Error interface and returns all the errors comma seprated
// if errors exist.
func (err ErrorArray) Error() string {
	var b bytes.Buffer

	for _, errs := range err {
		b.WriteString(fmt.Sprintf("%s, ", errs.Error()))
	}

	errs := b.String()
	return strings.TrimSuffix(errs, ", ")
}

// ValidationFunc is a function that receives the value of a
// field and a parameter used for the respective validation tag.
type ValidationFunc func(v interface{}, param string) error

// Validator implements a validator
type Validator struct {
	// Tag name being used.
	tagName string
	// validationFuncs is a map of ValidationFuncs indexed
	// by their name.
	validationFuncs map[string]ValidationFunc
}

// Helper validator so users can use the
// functions directly from the package
var defaultValidator = NewValidator()

// NewValidator creates a new Validator
func NewValidator() *Validator {
	return &Validator{
		tagName: "validate",
		validationFuncs: map[string]ValidationFunc{
			"nonzero": nonzero,
			"len":     length,
			"min":     min,
			"max":     max,
			"regexp":  regex,
			"nonnil":  nonnil,
		},
	}
}

// SetTag allows you to change the tag name used in structs
func SetTag(tag string) {
	defaultValidator.SetTag(tag)
}

// SetTag allows you to change the tag name used in structs
func (mv *Validator) SetTag(tag string) {
	mv.tagName = tag
}

// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func WithTag(tag string) *Validator {
	return defaultValidator.WithTag(tag)
}

// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func (mv *Validator) WithTag(tag string) *Validator {
	v := mv.copy()
	v.SetTag(tag)
	return v
}

// Copy a validator
func (mv *Validator) copy() *Validator {
	newFuncs := map[string]ValidationFunc{}
	for k, f := range mv.validationFuncs {
		newFuncs[k] = f
	}
	return &Validator{
		tagName:         mv.tagName,
		validationFuncs: newFuncs,
	}
}

// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func SetValidationFunc(name string, vf ValidationFunc) error {
	return defaultValidator.SetValidationFunc(name, vf)
}

// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error {
	if name == "" {
		return errors.New("name cannot be empty")
	}
	if vf == nil {
		delete(mv.validationFuncs, name)
		return nil
	}
	mv.validationFuncs[name] = vf
	return nil
}

// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func Validate(v interface{}) error {
	return defaultValidator.Validate(v)
}

// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func (mv *Validator) Validate(v interface{}) error {
	m := make(ErrorMap)
	if err := mv.validateStruct(reflect.ValueOf(v), m); err != nil {
		return err
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

func (mv *Validator) validateStruct(sv reflect.Value, m ErrorMap) error {
	kind := sv.Kind()
	if (kind == reflect.Ptr || kind == reflect.Interface) && !sv.IsNil() {
		return mv.validateStruct(sv.Elem(), m)
	}
	if kind != reflect.Struct && kind != reflect.Interface {
		return ErrUnsupported
	}

	st := sv.Type()
	nfields := st.NumField()
	for i := 0; i < nfields; i++ {
		if err := mv.validateField(st.Field(i), sv.Field(i), m); err != nil {
			return err
		}
	}

	return nil
}

// validateField validates the field of fieldVal referred to by fieldDef.
// If fieldDef refers to an anonymous/embedded field,
// validateField will walk all of the embedded type's fields and validate them on sv.
func (mv *Validator) validateField(fieldDef reflect.StructField, fieldVal reflect.Value, m ErrorMap) error {
	tag := fieldDef.Tag.Get(mv.tagName)
	if tag == "-" {
		return nil
	}
	// deal with pointers
	for (fieldVal.Kind() == reflect.Ptr || fieldVal.Kind() == reflect.Interface) && !fieldVal.IsNil() {
		fieldVal = fieldVal.Elem()
	}

	// ignore private structs unless Anonymous
	if !fieldDef.Anonymous && fieldDef.PkgPath != "" {
		return nil
	}

	var errs ErrorArray
	if tag != "" {
		var err error
		if fieldDef.PkgPath != "" {
			err = ErrCannotValidate
		} else {
			err = mv.validValue(fieldVal, tag)
		}
		if errarr, ok := err.(ErrorArray); ok {
			errs = errarr
		} else if err != nil {
			errs = ErrorArray{err}
		}
	}

	// no-op if field is not a struct, interface, array, slice or map
	mv.deepValidateCollection(fieldVal, m, func() string {
		return fieldDef.Name
	})

	if len(errs) > 0 {
		m[fieldDef.Name] = errs
	}
	return nil
}

func (mv *Validator) deepValidateCollection(f reflect.Value, m ErrorMap, fnameFn func() string) {
	switch f.Kind() {
	case reflect.Interface, reflect.Ptr:
		if f.IsNil() {
			return
		}
		mv.deepValidateCollection(f.Elem(), m, fnameFn)
	case reflect.Struct:
		subm := make(ErrorMap)
		err := mv.validateStruct(f, subm)
		if err != nil {
			m[fnameFn()] = ErrorArray{err}
		}
		for j, k := range subm {
			m[fnameFn()+"."+j] = k
		}
	case reflect.Array, reflect.Slice:
		// we don't need to loop over every byte in a byte slice so we only end up
		// looping when the kind is something we care about
		switch f.Type().Elem().Kind() {
		case reflect.Struct, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Array, reflect.Slice:
			for i := 0; i < f.Len(); i++ {
				mv.deepValidateCollection(f.Index(i), m, func() string {
					return fmt.Sprintf("%s[%d]", fnameFn(), i)
				})
			}
		}
	case reflect.Map:
		for _, key := range f.MapKeys() {
			mv.deepValidateCollection(key, m, func() string {
				return fmt.Sprintf("%s[%+v](key)", fnameFn(), key.Interface())
			}) // validate the map key
			value := f.MapIndex(key)
			mv.deepValidateCollection(value, m, func() string {
				return fmt.Sprintf("%s[%+v](value)", fnameFn(), key.Interface())
			})
		}
	}
}

// Valid validates a value based on the provided
// tags and returns errors found or nil.
func Valid(val interface{}, tags string) error {
	return defaultValidator.Valid(val, tags)
}

// Valid validates a value based on the provided
// tags and returns errors found or nil.
func (mv *Validator) Valid(val interface{}, tags string) error {
	if tags == "-" {
		return nil
	}
	v := reflect.ValueOf(val)
	if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && !v.IsNil() {
		return mv.validValue(v.Elem(), tags)
	}
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(val, tags)
}

// validValue is like Valid but takes a Value instead of an interface
func (mv *Validator) validValue(v reflect.Value, tags string) error {
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(v.Interface(), tags)
}

// validateVar validates one single variable
func (mv *Validator) validateVar(v interface{}, tag string) error {
	tags, err := mv.parseTags(tag)
	if err != nil {
		// unknown tag found, give up.
		return err
	}
	errs := make(ErrorArray, 0, len(tags))
	for _, t := range tags {
		if err := t.Fn(v, t.Param); err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		return errs
	}
	return nil
}

// tag represents one of the tag items
type tag struct {
	Name  string         // name of the tag
	Fn    ValidationFunc // validation function to call
	Param string         // parameter to send to the validation function
}

// separate by no escaped commas
var sepPattern *regexp.Regexp = regexp.MustCompile(`((?:^|[^\\])(?:\\\\)*),`)

func splitUnescapedComma(str string) []string {
	ret := []string{}
	indexes := sepPattern.FindAllStringIndex(str, -1)
	last := 0
	for _, is := range indexes {
		ret = append(ret, str[last:is[1]-1])
		last = is[1]
	}
	ret = append(ret, str[last:])
	return ret
}

// parseTags parses all individual tags found within a struct tag.
func (mv *Validator) parseTags(t string) ([]tag, error) {
	tl := splitUnescapedComma(t)
	tags := make([]tag, 0, len(tl))
	for _, i := range tl {
		i = strings.Replace(i, `\,`, ",", -1)
		tg := tag{}
		v := strings.SplitN(i, "=", 2)
		tg.Name = strings.Trim(v[0], " ")
		if tg.Name == "" {
			return []tag{}, ErrUnknownTag
		}
		if len(v) > 1 {
			tg.Param = strings.Trim(v[1], " ")
		}
		var found bool
		if tg.Fn, found = mv.validationFuncs[tg.Name]; !found {
			return []tag{}, ErrUnknownTag
		}
		tags = append(tags, tg)

	}
	return tags, nil
}

func parseName(tag string) string {
	if tag == "" {
		return ""
	}

	name := strings.SplitN(tag, ",", 2)[0]

	// if the field as be skipped in json, just return an empty string
	if name == "-" {
		return ""
	}
	return name
}
<commit_msg>fix commit issue<commit_after>// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package validator

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

// TextErr is an error that also implements the TextMarshaller interface for
// serializing out to various plain text encodings. Packages creating their
// own custom errors should use TextErr if they're intending to use serializing
// formats like json, msgpack etc.
type TextErr struct {
	Err error
}

// Error implements the error interface.
func (t TextErr) Error() string {
	return t.Err.Error()
}

// MarshalText implements the TextMarshaller
func (t TextErr) MarshalText() ([]byte, error) {
	return []byte(t.Err.Error()), nil
}

var (
	// ErrZeroValue is the error returned when variable has zero value
	// and nonzero or nonnil was specified
	ErrZeroValue = TextErr{errors.New("zero value")}
	// ErrMin is the error returned when variable is less than mininum
	// value specified
	ErrMin = TextErr{errors.New("less than min")}
	// ErrMax is the error returned when variable is more than
	// maximum specified
	ErrMax = TextErr{errors.New("greater than max")}
	// ErrLen is the error returned when length is not equal to
	// param specified
	ErrLen = TextErr{errors.New("invalid length")}
	// ErrRegexp is the error returned when the value does not
	// match the provided regular expression parameter
	ErrRegexp = TextErr{errors.New("regular expression mismatch")}
	// ErrUnsupported is the error error returned when a validation rule
	// is used with an unsupported variable type
	ErrUnsupported = TextErr{errors.New("unsupported type")}
	// ErrBadParameter is the error returned when an invalid parameter
	// is provided to a validation rule (e.g. a string where an int was
	// expected (max=foo,len=bar) or missing a parameter when one is required (len=))
	ErrBadParameter = TextErr{errors.New("bad parameter")}
	// ErrUnknownTag is the error returned when an unknown tag is found
	ErrUnknownTag = TextErr{errors.New("unknown tag")}
	// ErrInvalid is the error returned when variable is invalid
	// (normally a nil pointer)
	ErrInvalid = TextErr{errors.New("invalid value")}
	// ErrCannotValidate is the error returned when a struct is unexported
	ErrCannotValidate = TextErr{errors.New("cannot validate unexported struct")}
)

// ErrorMap is a map which contains all errors from validating a struct.
type ErrorMap map[string]ErrorArray

// ErrorMap implements the Error interface so we can check error against nil.
// The returned error is all existing errors with the map.
func (err ErrorMap) Error() string {
	var b bytes.Buffer

	for k, errs := range err {
		if len(errs) > 0 {
			b.WriteString(fmt.Sprintf("%s: %s, ", k, errs.Error()))
		}
	}

	return strings.TrimSuffix(b.String(), ", ")
}

// ErrorArray is a slice of errors returned by the Validate function.
type ErrorArray []error

// ErrorArray implements the Error interface and returns all the errors comma seprated
// if errors exist.
func (err ErrorArray) Error() string {
	var b bytes.Buffer

	for _, errs := range err {
		b.WriteString(fmt.Sprintf("%s, ", errs.Error()))
	}

	errs := b.String()
	return strings.TrimSuffix(errs, ", ")
}

// ValidationFunc is a function that receives the value of a
// field and a parameter used for the respective validation tag.
type ValidationFunc func(v interface{}, param string) error

// Validator implements a validator
type Validator struct {
	// Tag name being used.
	tagName string
	// validationFuncs is a map of ValidationFuncs indexed
	// by their name.
	validationFuncs map[string]ValidationFunc
	// printJSON set to true will make errors print with the
	// name of their json field instead of their struct tag.
	// If no json tag is present the name of the struct is used.
	printJSON bool
}

// Helper validator so users can use the
// functions directly from the package
var defaultValidator = NewValidator()

// NewValidator creates a new Validator
func NewValidator() *Validator {
	return &Validator{
		tagName: "validate",
		validationFuncs: map[string]ValidationFunc{
			"nonzero": nonzero,
			"len":     length,
			"min":     min,
			"max":     max,
			"regexp":  regex,
			"nonnil":  nonnil,
		},
		printJSON: false,
	}
}

// SetTag allows you to change the tag name used in structs
func SetTag(tag string) {
	defaultValidator.SetTag(tag)
}

// SetTag allows you to change the tag name used in structs
func (mv *Validator) SetTag(tag string) {
	mv.tagName = tag
}

// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func WithTag(tag string) *Validator {
	return defaultValidator.WithTag(tag)
}

// WithTag creates a new Validator with the new tag name. It is
// useful to chain-call with Validate so we don't change the tag
// name permanently: validator.WithTag("foo").Validate(t)
func (mv *Validator) WithTag(tag string) *Validator {
	v := mv.copy()
	v.SetTag(tag)
	return v
}

// SetPrintJSON allows you to print errors with josn tag names present in struct tags
func SetPrintJSON(printJSON bool) {
	defaultValidator.SetPrintJSON(printJSON)
}

// SetPrintJSON allows you to print errors with josn tag names present in struct tags
func (mv *Validator) SetPrintJSON(printJSON bool) {
	mv.printJSON = printJSON
}

// WithPrintJSON creates a new Validator with printJSON set to new value. It is
// useful to chain-call with Validate so we don't change the print option
// permanently: validator.WithPrintJSON(true).Validate(t)
func WithPrintJSON(printJSON bool) *Validator {
	return defaultValidator.WithPrintJSON(printJSON)
}

// WithPrintJSON creates a new Validator with printJSON set to new value. It is
// useful to chain-call with Validate so we don't change the print option
// permanently: validator.WithTag("foo").WithPrintJSON(true).Validate(t)
func (mv *Validator) WithPrintJSON(printJSON bool) *Validator {
	v := mv.copy()
	v.SetPrintJSON(printJSON)
	return v
}

// Copy a validator
func (mv *Validator) copy() *Validator {
	newFuncs := map[string]ValidationFunc{}
	for k, f := range mv.validationFuncs {
		newFuncs[k] = f
	}
	return &Validator{
		tagName:         mv.tagName,
		validationFuncs: newFuncs,
		printJSON:       mv.printJSON,
	}
}

// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func SetValidationFunc(name string, vf ValidationFunc) error {
	return defaultValidator.SetValidationFunc(name, vf)
}

// SetValidationFunc sets the function to be used for a given
// validation constraint. Calling this function with nil vf
// is the same as removing the constraint function from the list.
func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error {
	if name == "" {
		return errors.New("name cannot be empty")
	}
	if vf == nil {
		delete(mv.validationFuncs, name)
		return nil
	}
	mv.validationFuncs[name] = vf
	return nil
}

// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func Validate(v interface{}) error {
	return defaultValidator.Validate(v)
}

// Validate validates the fields of a struct based
// on 'validator' tags and returns errors found indexed
// by the field name.
func (mv *Validator) Validate(v interface{}) error {
	m := make(ErrorMap)
	if err := mv.validateStruct(reflect.ValueOf(v), m); err != nil {
		return err
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

func (mv *Validator) validateStruct(sv reflect.Value, m ErrorMap) error {
	kind := sv.Kind()
	if (kind == reflect.Ptr || kind == reflect.Interface) && !sv.IsNil() {
		return mv.validateStruct(sv.Elem(), m)
	}
	if kind != reflect.Struct && kind != reflect.Interface {
		return ErrUnsupported
	}

	st := sv.Type()
	nfields := st.NumField()
	for i := 0; i < nfields; i++ {
		if err := mv.validateField(st.Field(i), sv.Field(i), m); err != nil {
			return err
		}
	}

	return nil
}

// validateField validates the field of fieldVal referred to by fieldDef.
// If fieldDef refers to an anonymous/embedded field,
// validateField will walk all of the embedded type's fields and validate them on sv.
func (mv *Validator) validateField(fieldDef reflect.StructField, fieldVal reflect.Value, m ErrorMap) error {
	tag := fieldDef.Tag.Get(mv.tagName)
	if tag == "-" {
		return nil
	}
	// deal with pointers
	for (fieldVal.Kind() == reflect.Ptr || fieldVal.Kind() == reflect.Interface) && !fieldVal.IsNil() {
		fieldVal = fieldVal.Elem()
	}

	// ignore private structs unless Anonymous
	if !fieldDef.Anonymous && fieldDef.PkgPath != "" {
		return nil
	}

	var errs ErrorArray
	if tag != "" {
		var err error
		if fieldDef.PkgPath != "" {
			err = ErrCannotValidate
		} else {
			err = mv.validValue(fieldVal, tag)
		}
		if errarr, ok := err.(ErrorArray); ok {
			errs = errarr
		} else if err != nil {
			errs = ErrorArray{err}
		}
	}

	// no-op if field is not a struct, interface, array, slice or map
	mv.deepValidateCollection(fieldVal, m, func() string {
		return fieldDef.Name
	})

	if len(errs) > 0 {
		n := fieldDef.Name

		if mv.printJSON {
			if jn := parseName(fieldDef.Tag.Get("json")); jn != "" {
				n = jn
			}
		}
		m[n] = errs
	}
	return nil
}

func (mv *Validator) deepValidateCollection(f reflect.Value, m ErrorMap, fnameFn func() string) {
	switch f.Kind() {
	case reflect.Interface, reflect.Ptr:
		if f.IsNil() {
			return
		}
		mv.deepValidateCollection(f.Elem(), m, fnameFn)
	case reflect.Struct:
		subm := make(ErrorMap)
		err := mv.validateStruct(f, subm)
		if err != nil {
			m[fnameFn()] = ErrorArray{err}
		}
		for j, k := range subm {
			m[fnameFn()+"."+j] = k
		}
	case reflect.Array, reflect.Slice:
		// we don't need to loop over every byte in a byte slice so we only end up
		// looping when the kind is something we care about
		switch f.Type().Elem().Kind() {
		case reflect.Struct, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Array, reflect.Slice:
			for i := 0; i < f.Len(); i++ {
				mv.deepValidateCollection(f.Index(i), m, func() string {
					return fmt.Sprintf("%s[%d]", fnameFn(), i)
				})
			}
		}
	case reflect.Map:
		for _, key := range f.MapKeys() {
			mv.deepValidateCollection(key, m, func() string {
				return fmt.Sprintf("%s[%+v](key)", fnameFn(), key.Interface())
			}) // validate the map key
			value := f.MapIndex(key)
			mv.deepValidateCollection(value, m, func() string {
				return fmt.Sprintf("%s[%+v](value)", fnameFn(), key.Interface())
			})
		}
	}
}

// Valid validates a value based on the provided
// tags and returns errors found or nil.
func Valid(val interface{}, tags string) error {
	return defaultValidator.Valid(val, tags)
}

// Valid validates a value based on the provided
// tags and returns errors found or nil.
func (mv *Validator) Valid(val interface{}, tags string) error {
	if tags == "-" {
		return nil
	}
	v := reflect.ValueOf(val)
	if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && !v.IsNil() {
		return mv.validValue(v.Elem(), tags)
	}
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(val, tags)
}

// validValue is like Valid but takes a Value instead of an interface
func (mv *Validator) validValue(v reflect.Value, tags string) error {
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(v.Interface(), tags)
}

// validateVar validates one single variable
func (mv *Validator) validateVar(v interface{}, tag string) error {
	tags, err := mv.parseTags(tag)
	if err != nil {
		// unknown tag found, give up.
		return err
	}
	errs := make(ErrorArray, 0, len(tags))
	for _, t := range tags {
		if err := t.Fn(v, t.Param); err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		return errs
	}
	return nil
}

// tag represents one of the tag items
type tag struct {
	Name  string         // name of the tag
	Fn    ValidationFunc // validation function to call
	Param string         // parameter to send to the validation function
}

// separate by no escaped commas
var sepPattern *regexp.Regexp = regexp.MustCompile(`((?:^|[^\\])(?:\\\\)*),`)

func splitUnescapedComma(str string) []string {
	ret := []string{}
	indexes := sepPattern.FindAllStringIndex(str, -1)
	last := 0
	for _, is := range indexes {
		ret = append(ret, str[last:is[1]-1])
		last = is[1]
	}
	ret = append(ret, str[last:])
	return ret
}

// parseTags parses all individual tags found within a struct tag.
func (mv *Validator) parseTags(t string) ([]tag, error) {
	tl := splitUnescapedComma(t)
	tags := make([]tag, 0, len(tl))
	for _, i := range tl {
		i = strings.Replace(i, `\,`, ",", -1)
		tg := tag{}
		v := strings.SplitN(i, "=", 2)
		tg.Name = strings.Trim(v[0], " ")
		if tg.Name == "" {
			return []tag{}, ErrUnknownTag
		}
		if len(v) > 1 {
			tg.Param = strings.Trim(v[1], " ")
		}
		var found bool
		if tg.Fn, found = mv.validationFuncs[tg.Name]; !found {
			return []tag{}, ErrUnknownTag
		}
		tags = append(tags, tg)

	}
	return tags, nil
}

func parseName(tag string) string {
	if tag == "" {
		return ""
	}

	name := strings.SplitN(tag, ",", 2)[0]

	// if the field as be skipped in json, just return an empty string
	if name == "-" {
		return ""
	}
	return name
}
<|endoftext|>


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

// +build linux

package inotify

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

func TestInotifyEvents(t *testing.T) {
	// Create an inotify watcher instance and initialize it
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher() failed: %s", err)
	}

	t.Logf("NEEDS TO BE CONVERTED TO NEW GO TOOL") // TODO
	return

	// Add a watch for "_test"
	err = watcher.Watch("_test")
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	// Receive errors on the error channel on a separate goroutine
	go func() {
		for err := range watcher.Error {
			t.Fatalf("error received: %s", err)
		}
	}()

	const testFile string = "_test/TestInotifyEvents.testfile"

	// Receive events on the event channel on a separate goroutine
	eventstream := watcher.Event
	var eventsReceived = 0
	done := make(chan bool)
	go func() {
		for event := range eventstream {
			// Only count relevant events
			if event.Name == testFile {
				eventsReceived++
				t.Logf("event received: %s", event)
			} else {
				t.Logf("unexpected event received: %s", event)
			}
		}
		done <- true
	}()

	// Create a file
	// This should add at least one event to the inotify event queue
	_, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		t.Fatalf("creating test file failed: %s", err)
	}

	// We expect this event to be received almost immediately, but let's wait 1 s to be sure
	time.Sleep(1 * time.Second)
	if eventsReceived == 0 {
		t.Fatal("inotify event hasn't been received after 1 second")
	}

	// Try closing the inotify instance
	t.Log("calling Close()")
	watcher.Close()
	t.Log("waiting for the event channel to become closed...")
	select {
	case <-done:
		t.Log("event channel closed")
	case <-time.After(1 * time.Second):
		t.Fatal("event stream was not closed after 1 second")
	}
}

func TestInotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	done := make(chan bool)
	go func() {
		watcher.Close()
		done <- true
	}()

	select {
	case <-done:
	case <-time.After(50 * time.Millisecond):
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	err := watcher.Watch("_test")
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<commit_msg>exp/inotify: remove use of _test Fixes issue 2573.<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux

package inotify

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

func TestInotifyEvents(t *testing.T) {
	// Create an inotify watcher instance and initialize it
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher failed: %s", err)
	}

	dir, err := ioutil.TempDir("", "inotify")
	if err != nil {
		t.Fatalf("TempDir failed: %s", err)
	}
	defer os.RemoveAll(dir)

	// Add a watch for "_test"
	err = watcher.Watch(dir)
	if err != nil {
		t.Fatalf("Watch failed: %s", err)
	}

	// Receive errors on the error channel on a separate goroutine
	go func() {
		for err := range watcher.Error {
			t.Fatalf("error received: %s", err)
		}
	}()

	testFile := dir + "/TestInotifyEvents.testfile"

	// Receive events on the event channel on a separate goroutine
	eventstream := watcher.Event
	var eventsReceived = 0
	done := make(chan bool)
	go func() {
		for event := range eventstream {
			// Only count relevant events
			if event.Name == testFile {
				eventsReceived++
				t.Logf("event received: %s", event)
			} else {
				t.Logf("unexpected event received: %s", event)
			}
		}
		done <- true
	}()

	// Create a file
	// This should add at least one event to the inotify event queue
	_, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		t.Fatalf("creating test file: %s", err)
	}

	// We expect this event to be received almost immediately, but let's wait 1 s to be sure
	time.Sleep(1 * time.Second)
	if eventsReceived == 0 {
		t.Fatal("inotify event hasn't been received after 1 second")
	}

	// Try closing the inotify instance
	t.Log("calling Close()")
	watcher.Close()
	t.Log("waiting for the event channel to become closed...")
	select {
	case <-done:
		t.Log("event channel closed")
	case <-time.After(1 * time.Second):
		t.Fatal("event stream was not closed after 1 second")
	}
}

func TestInotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	done := make(chan bool)
	go func() {
		watcher.Close()
		done <- true
	}()

	select {
	case <-done:
	case <-time.After(50 * time.Millisecond):
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	err := watcher.Watch(os.TempDir())
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<|endoftext|>


<commit_before>package environment

import (
	"errors"
	"github.com/joho/godotenv"
	"os"
)

const (
	DEVELOPMENT string = "development"
	TESTING     string = "testing"
	STAGING     string = "staging"
	PRODUCTION  string = "production"

	PORT              string = "PORT"
	PSQL_DATABASE_URL string = "POSTGRES_DATABASE_URL"
)

var (
	activeEnvironment string
)

func Set(env string) error {
	return SetWithRelativeDirectory("./", env)
}

func SetWithRelativeDirectory(relativeDirectory string, env string) error {
	if isValid(env) {
		activeEnvironment = env
		err := godotenv.Load(relativeDirectory + ".env." + activeEnvironment)
		if err != nil {
			return errors.New("Error loading the .env." + activeEnvironment + " file")
		}
		return nil
	} else {
		return errors.New("Invalid environment parameter")
	}
}

func GetActiveEnvironment() string {
	return activeEnvironment
}

func GetEnvVar(key string) string {
	return os.Getenv(key)
}

func isValid(env string) bool {
	return env == DEVELOPMENT ||
		env == TESTING ||
		env == STAGING ||
		env == PRODUCTION
}
<commit_msg>Clean up environment, allow prod no env file<commit_after>package environment

import (
	"errors"
	"github.com/joho/godotenv"
	"os"
)

// Environment Types
const (
	DEVELOPMENT string = "development"
	TESTING     string = "testing"
	STAGING     string = "staging"
	PRODUCTION  string = "production"
)

// Environment Variables
const (
	PORT              string = "PORT"
	PSQL_DATABASE_URL string = "POSTGRES_DATABASE_URL"
)

var (
	activeEnvironment string
)

func Set(env string) error {
	return SetWithRelativeDirectory("./", env)
}

func SetWithRelativeDirectory(relativeDirectory string, activeEnvironment string) error {
	if isValid(activeEnvironment) {
		// Require an env file
		err := godotenv.Load(relativeDirectory + ".env." + activeEnvironment)
		if err != nil && activeEnvironment != PRODUCTION {
			return errors.New("Error loading the .env." + activeEnvironment + " file")
		}
		return nil
	} else {
		return errors.New("Invalid environment parameter")
	}
}

func GetActiveEnvironment() string {
	return activeEnvironment
}

func GetEnvVar(key string) string {
	return os.Getenv(key)
}

func isValid(env string) bool {
	return env == DEVELOPMENT ||
		env == TESTING ||
		env == STAGING ||
		env == PRODUCTION
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"time"
	"github.com/miekg/dns"
)

type ymmv_message struct {
	ip_family	byte
	ip_protocol	byte
	addr		*net.IP
	query_time	time.Time
	query		*dns.Msg
	answer_time	time.Time
	answer		*dns.Msg
}

func pad_right(s string, length int, pad string) string {
	// if a string is longer than the desired length already, just use it
	if len(s) >= length {
		return s
	}
	// add our padding string until we are long enough
	for len(s) < length {
		s += pad
	}
	// truncate on our return, since our padding string may be multiple
	// characters and result in a string longer than we want
	return s[:length]
}

func (y ymmv_message) print() {
	var protocol_str string
	if y.ip_protocol == 'u' {
		protocol_str = "UDP"
	} else {
		protocol_str = "TCP"
	}
	header := fmt.Sprintf("===[ ymmv message (IPv%d, %s, %s) ]",
			      y.ip_family, protocol_str, y.addr)
	fmt.Printf("%s\n", pad_right(header, 78, "="))
	fmt.Printf("%s\n", y.query)
	if y.query_time.Unix() == 0 {
		fmt.Printf(";; WHEN: unknown\n")
	} else {
		fmt.Printf(";; WHEN: %s\n", y.query_time)
	}
	fmt.Printf("%s\n", pad_right("", 78, "-"))
	fmt.Printf("%s\n", y.answer)
	if y.answer_time.Unix() == 0 {
		fmt.Printf(";; WHEN: unknown\n")
	} else {
		fmt.Printf(";; WHEN: %s\n", y.answer_time)
	}
	fmt.Printf("%s\n", pad_right("", 78, "-"))
}

// TODO: return more details with err if underlying calls fail
func read_next_message() (y *ymmv_message, err error) {
	magic := make([]byte, 4, 4)
	nread, err := os.Stdin.Read(magic)
	if err != nil {
		return nil, err
	}
	if nread != 4 {
		errmsg := fmt.Sprintf("Only read %d of 4 magic bytes", nread)
		return nil, errors.New(errmsg)
	}
	if string(magic) != "ymmv" {
		errmsg := fmt.Sprintf("Magic '%s' instead of 'ymmv'", magic)
		return nil, errors.New(errmsg)
	}

	tmp_ip_family := make([]byte, 1, 1)
	nread, err = os.Stdin.Read(tmp_ip_family)
	if err != nil {
		return nil, err
	}
	if nread != 1 {
		return nil, errors.New("Couldn't read IPv4 or IPv6")
	}
	var ip_family int
	if tmp_ip_family[0] == '4' {
		ip_family = 4
	} else if tmp_ip_family[0] == '6' {
		ip_family = 6
	} else {
		errmsg := fmt.Sprintf("Expecting '4' or '6' for IP family, got '%s'",
				      ip_family)
		return nil, errors.New(errmsg)
	}

	protocol := make([]byte, 1, 1)
	nread, err = os.Stdin.Read(protocol)
	if err != nil {
		return nil, err
	}
	if nread != 1 {
		return nil, errors.New("Couldn't read TCP or UDP")
	}
	if (protocol[0] != 'u') && (protocol[0] != 't') {
		errmsg := fmt.Sprintf("Expecting 't'cp or 'u'dp for protocol, got '%s'",
				      protocol)
		return nil, errors.New(errmsg)
	}

	var tmp_addr []byte
	if ip_family == 4 {
		tmp_addr = make([]byte, 4, 4)
	} else {
		// XXX: should we add an assert()-equivalent here?
		tmp_addr = make([]byte, 16, 16)
	}
	nread, err = os.Stdin.Read(tmp_addr)
	if err != nil {
		return nil, err
	}
	if nread != cap(tmp_addr) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of address",
				      nread, cap(tmp_addr))
		return nil, errors.New(errmsg)
	}
	addr := net.IP(tmp_addr)

	var query_sec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &query_sec)
	if err != nil {
		return nil, err
	}
	var query_nsec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &query_nsec)
	if err != nil {
		return nil, err
	}
	query_time := time.Unix(int64(query_sec), int64(query_nsec))

	var query_len uint16
	err = binary.Read(os.Stdin, binary.BigEndian, &query_len)
	if err != nil {
		return nil, err
	}
	query_raw := make([]byte, query_len, query_len)
	nread, err = os.Stdin.Read(query_raw)
	if err != nil {
		return nil, err
	}
	if nread != int(query_len) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of query message", nread, query_len)
		return nil, errors.New(errmsg)
	}
	query := new(dns.Msg)
	query.Unpack(query_raw)

	var answer_sec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_sec)
	if err != nil {
		return nil, err
	}
	var answer_nsec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_nsec)
	if err != nil {
		return nil, err
	}
	answer_time := time.Unix(int64(answer_sec), int64(answer_nsec))

	var answer_len uint16
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_len)
	if err != nil {
		return nil, err
	}
	answer_raw := make([]byte, answer_len, answer_len)
	nread, err = os.Stdin.Read(answer_raw)
	if err != nil {
		return nil, err
	}
	if nread != int(answer_len) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of answer message", nread, answer_len)
		return nil, errors.New(errmsg)
	}
	answer := new(dns.Msg)
	answer.Unpack(answer_raw)

	var result ymmv_message
	result.ip_family = byte(ip_family)
	result.ip_protocol = protocol[0]
	result.addr = new(net.IP)
	*result.addr = addr
	result.query_time = query_time
	result.query = query
	result.answer_time = answer_time
	result.answer = answer

	return &result, nil
}

func lookup_yeti_servers() []net.IP {
	root_client := new(dns.Client)
	root_client.Net = "tcp"
	ns_query = new(dns.Msg)
	ns_query.SetQuestion(".", dns.TypeNS)
	// TODO: avoid hard-coding a particular root server here
	ns_response, _, err := root_client.Exchange(ns_query,
						    "yeti-ns.wide.ad.jp.")
	if err != nil {
		log.Fatal("Error looking up Yeti root servers")
	}
}

type yeti_server_selection struct {
	next_server int
	ips []net.IP
}

// Main function.
func main() {
	var servers yeti_server_selection
	if len(os.Args) > 1 {
		for _, server := range os.Args[1:] {
			ip := net.ParseIP(server)
			if ip == nil {
				log.Fatalf("Unrecognized IP address '%s'\n",
					   server)
			}
			servers.ips = append(servers.ips, net.ParseIP(server))
		}
	} else {
		servers.ips = lookup_yeti_servers()
	}
	fmt.Printf("%s\n", servers.ips)
	for {
		y , err := read_next_message()
		if (err != nil) && (err != io.EOF) {
			log.Fatal(err)
		}
		if y == nil {
			break
		}
	}
}

<commit_msg>Checkpoint<commit_after>package main

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"time"
	"github.com/miekg/dns"
	"github.com/shane-kerr/ymmv/dnsstub"
)

type ymmv_message struct {
	ip_family	byte
	ip_protocol	byte
	addr		*net.IP
	query_time	time.Time
	query		*dns.Msg
	answer_time	time.Time
	answer		*dns.Msg
}

func pad_right(s string, length int, pad string) string {
	// if a string is longer than the desired length already, just use it
	if len(s) >= length {
		return s
	}
	// add our padding string until we are long enough
	for len(s) < length {
		s += pad
	}
	// truncate on our return, since our padding string may be multiple
	// characters and result in a string longer than we want
	return s[:length]
}

func (y ymmv_message) print() {
	var protocol_str string
	if y.ip_protocol == 'u' {
		protocol_str = "UDP"
	} else {
		protocol_str = "TCP"
	}
	header := fmt.Sprintf("===[ ymmv message (IPv%d, %s, %s) ]",
			      y.ip_family, protocol_str, y.addr)
	fmt.Printf("%s\n", pad_right(header, 78, "="))
	fmt.Printf("%s\n", y.query)
	if y.query_time.Unix() == 0 {
		fmt.Printf(";; WHEN: unknown\n")
	} else {
		fmt.Printf(";; WHEN: %s\n", y.query_time)
	}
	fmt.Printf("%s\n", pad_right("", 78, "-"))
	fmt.Printf("%s\n", y.answer)
	if y.answer_time.Unix() == 0 {
		fmt.Printf(";; WHEN: unknown\n")
	} else {
		fmt.Printf(";; WHEN: %s\n", y.answer_time)
	}
	fmt.Printf("%s\n", pad_right("", 78, "-"))
}

// TODO: return more details with err if underlying calls fail
func read_next_message() (y *ymmv_message, err error) {
	magic := make([]byte, 4, 4)
	nread, err := os.Stdin.Read(magic)
	if err != nil {
		return nil, err
	}
	if nread != 4 {
		errmsg := fmt.Sprintf("Only read %d of 4 magic bytes", nread)
		return nil, errors.New(errmsg)
	}
	if string(magic) != "ymmv" {
		errmsg := fmt.Sprintf("Magic '%s' instead of 'ymmv'", magic)
		return nil, errors.New(errmsg)
	}

	tmp_ip_family := make([]byte, 1, 1)
	nread, err = os.Stdin.Read(tmp_ip_family)
	if err != nil {
		return nil, err
	}
	if nread != 1 {
		return nil, errors.New("Couldn't read IPv4 or IPv6")
	}
	var ip_family int
	if tmp_ip_family[0] == '4' {
		ip_family = 4
	} else if tmp_ip_family[0] == '6' {
		ip_family = 6
	} else {
		errmsg := fmt.Sprintf("Expecting '4' or '6' for IP family, got '%s'",
				      ip_family)
		return nil, errors.New(errmsg)
	}

	protocol := make([]byte, 1, 1)
	nread, err = os.Stdin.Read(protocol)
	if err != nil {
		return nil, err
	}
	if nread != 1 {
		return nil, errors.New("Couldn't read TCP or UDP")
	}
	if (protocol[0] != 'u') && (protocol[0] != 't') {
		errmsg := fmt.Sprintf("Expecting 't'cp or 'u'dp for protocol, got '%s'",
				      protocol)
		return nil, errors.New(errmsg)
	}

	var tmp_addr []byte
	if ip_family == 4 {
		tmp_addr = make([]byte, 4, 4)
	} else {
		// XXX: should we add an assert()-equivalent here?
		tmp_addr = make([]byte, 16, 16)
	}
	nread, err = os.Stdin.Read(tmp_addr)
	if err != nil {
		return nil, err
	}
	if nread != cap(tmp_addr) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of address",
				      nread, cap(tmp_addr))
		return nil, errors.New(errmsg)
	}
	addr := net.IP(tmp_addr)

	var query_sec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &query_sec)
	if err != nil {
		return nil, err
	}
	var query_nsec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &query_nsec)
	if err != nil {
		return nil, err
	}
	query_time := time.Unix(int64(query_sec), int64(query_nsec))

	var query_len uint16
	err = binary.Read(os.Stdin, binary.BigEndian, &query_len)
	if err != nil {
		return nil, err
	}
	query_raw := make([]byte, query_len, query_len)
	nread, err = os.Stdin.Read(query_raw)
	if err != nil {
		return nil, err
	}
	if nread != int(query_len) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of query message", nread, query_len)
		return nil, errors.New(errmsg)
	}
	query := new(dns.Msg)
	query.Unpack(query_raw)

	var answer_sec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_sec)
	if err != nil {
		return nil, err
	}
	var answer_nsec uint32
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_nsec)
	if err != nil {
		return nil, err
	}
	answer_time := time.Unix(int64(answer_sec), int64(answer_nsec))

	var answer_len uint16
	err = binary.Read(os.Stdin, binary.BigEndian, &answer_len)
	if err != nil {
		return nil, err
	}
	answer_raw := make([]byte, answer_len, answer_len)
	nread, err = os.Stdin.Read(answer_raw)
	if err != nil {
		return nil, err
	}
	if nread != int(answer_len) {
		errmsg := fmt.Sprintf("Only read %d of %d bytes of answer message", nread, answer_len)
		return nil, errors.New(errmsg)
	}
	answer := new(dns.Msg)
	answer.Unpack(answer_raw)

	var result ymmv_message
	result.ip_family = byte(ip_family)
	result.ip_protocol = protocol[0]
	result.addr = new(net.IP)
	*result.addr = addr
	result.query_time = query_time
	result.query = query
	result.answer_time = answer_time
	result.answer = answer

	return &result, nil
}

func lookup_yeti_servers() []net.IP {
	// get the list of root servers from a known Yeti root server
	root_client := new(dns.Client)
	root_client.Net = "tcp"
	ns_query := new(dns.Msg)
	ns_query.SetQuestion(".", dns.TypeNS)
	// TODO: avoid hard-coding a particular root server here
	ns_response, _, err := root_client.Exchange(ns_query,
						    "yeti-ns.wide.ad.jp.:53")
	if err != nil {
		log.Fatalf("Error looking up Yeti root server NS; %s", err)
	}

	// lookup the addresses of some of our Yeti servers
	resolver, err := dnsstub.Init(16)
	if err != nil {
		log.Fatalf("Error setting up DNS stub resolver: %s\n", err)
	}
//	num_root_servers := len(ns_response.Answer)
	for _, root_server := range ns_response.Answer {
		switch root_server.(type) {
		case *dns.NS:
			ns := root_server.(*dns.NS).Ns
			resolver.Query(ns, dns.TypeAAAA)
		}
	}
	ips := make([]net.IP, 1, 1)
	for _ = range ns_response.Answer {
		answer, err := resolver.Wait()
		if err != nil {
		}
		if answer != nil {
		}
	}
	resolver.Close()

	return ips
}

type yeti_server_selection struct {
	next_server int
	ips []net.IP
}

// Main function.
func main() {
	var servers yeti_server_selection
	if len(os.Args) > 1 {
		for _, server := range os.Args[1:] {
			ip := net.ParseIP(server)
			if ip == nil {
				log.Fatalf("Unrecognized IP address '%s'\n",
					   server)
			}
			servers.ips = append(servers.ips, net.ParseIP(server))
		}
	} else {
		servers.ips = lookup_yeti_servers()
	}
	fmt.Printf("%s\n", servers.ips)
	for {
		y , err := read_next_message()
		if (err != nil) && (err != io.EOF) {
			log.Fatal(err)
		}
		if y == nil {
			break
		}
	}
}

<|endoftext|>


<commit_before>package generator

import (
	"encoding/xml"

	"socialapi/config"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"
	"socialapi/workers/sitemap/models"

	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/koding/redis"
	"github.com/robfig/cron"
)

type Controller struct {
	log          logging.Logger
	fileSelector FileSelector
	fileName     string
	redisConn    *redis.RedisSession
}

const (
	// before sending this interval, beware that you have to change
	// TIMERANGE in cache key file
	SCHEDULE = "0 0-59/30 * * * *"
)

var (
	cronJob *cron.Cron
)

func New(log logging.Logger) (*Controller, error) {
	conf := *config.Get()
	conf.Redis.DB = conf.Sitemap.RedisDB

	redisConn := helper.MustInitRedisConn(&conf)
	c := &Controller{
		log:          log,
		fileSelector: CachedFileSelector{},
		redisConn:    redisConn,
	}

	return c, c.initCron()
}

func (c *Controller) initCron() error {
	cronJob = cron.New()
	if err := cronJob.AddFunc(SCHEDULE, c.generate); err != nil {
		return err
	}
	cronJob.Start()

	return nil
}

func (c *Controller) Shutdown() {
	cronJob.Stop()
}

func (c *Controller) generate() {
	c.log.Info("Sitemap update started")
	for {
		name, err := c.fileSelector.Select()
		if err == redis.ErrNil {
			return
		}

		if err != nil {
			c.log.Error("Could not fetch file name: %s", err)
			return
		}
		c.log.Info("Updating sitemap: %s", name)
		// there is not any waiting sitemap updates
		if name == "" {
			return
		}

		c.fileName = name

		els, err := c.fetchElements()
		if err != nil {
			c.log.Critical("Could not fetch updated elements: %s", err)
			c.handleError(els)
			continue
		}

		if len(els) == 0 {
			c.log.Info("Items are already added")
			continue
		}

		container := c.buildContainer(els)

		if err := c.updateFile(container); err != nil {
			c.handleError(els)
			c.log.Critical("Could not update file: %s", err)
			continue
		}

	}
}

// handleError re-adds updated items to next file update queue
func (c *Controller) handleError(items []*models.SitemapItem) {
	// re-add filename to next queue
	key := common.PrepareNextFileNameCacheKey()
	if _, err := c.redisConn.AddSetMembers(key, c.fileName); err != nil {
		c.log.Critical("Could not re-add the filename: %s", err)
		return
	}

	key = common.PrepareNextFileCacheKey(c.fileName)
	values := make([]interface{}, len(items))
	for k := range items {
		values[k] = items[k].PrepareSetValue()
	}

	if _, err := c.redisConn.AddSetMembers(key, values...); err != nil {
		c.log.Critical("Could not re-add the updated items: %s", err)
	}

}

func (c *Controller) fetchElements() ([]*models.SitemapItem, error) {
	key := common.PrepareCurrentFileCacheKey(c.fileName)
	els := make([]*models.SitemapItem, 0)

	members, err := c.redisConn.GetSetMembers(key)
	if err != nil && err != redis.ErrNil {
		return nil, err
	}

	for i := range members {
		item, err := c.redisConn.String(members[i])
		if err != nil {
			c.log.Error("Could not convert item: %s", err)
			continue
		}
		if item == "" {
			continue
		}

		i := &models.SitemapItem{}
		// if there is a syntax error in item, do not need to try to
		// recreate it
		if err := i.Populate(item); err != nil {
			c.log.Error("Could not get item %s: %s", item, err)
			continue
		}
		els = append(els, i)
	}
	if _, err := c.redisConn.Del(key); err != nil {
		c.log.Error("Could not delete key %s: %s", key, err)
	}

	return els, nil
}

func (c *Controller) updateFile(container *models.ItemContainer) error {
	sf := models.NewSitemapFile()
	newItem := false
	err := sf.ByName(c.fileName)
	if err == bongo.RecordNotFound {
		newItem = true
	}

	if err != nil && !newItem {
		return err
	}

	s := models.NewItemSet()
	if !newItem && len(sf.Blob) > 0 {
		if err := xml.Unmarshal(sf.Blob, &s); err != nil {
			return err
		}
	}

	s.Populate(container)
	v, err := xml.Marshal(s)
	if err != nil {
		return err
	}
	sf.Blob = v

	if newItem {
		sf.Name = c.fileName
		return sf.Create()
	}

	return sf.Update()
}

func (c *Controller) buildContainer(items []*models.SitemapItem) *models.ItemContainer {
	container := models.NewItemContainer()
	for _, v := range items {
		item := v.Definition(config.Get().Uri)
		switch v.Status {
		case models.STATUS_ADD:
			container.Add = append(container.Add, item)
		case models.STATUS_DELETE:
			container.Delete = append(container.Delete, item)
		case models.STATUS_UPDATE:
			container.Update = append(container.Update, item)
		}
	}

	return container
}
<commit_msg>Sitemap: add cronjob schedule definition<commit_after>package generator

import (
	"encoding/xml"

	"socialapi/config"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"
	"socialapi/workers/sitemap/models"

	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/koding/redis"
	"github.com/robfig/cron"
)

type Controller struct {
	log          logging.Logger
	fileSelector FileSelector
	fileName     string
	redisConn    *redis.RedisSession
}

const (
	// before sending this interval, beware that you have to change
	// TIMERANGE in cache key file
	// run cron job every 30 minutes starting from 0
	SCHEDULE = "0 0-59/30 * * * *"
)

var (
	cronJob *cron.Cron
)

func New(log logging.Logger) (*Controller, error) {
	conf := *config.Get()
	conf.Redis.DB = conf.Sitemap.RedisDB

	redisConn := helper.MustInitRedisConn(&conf)
	c := &Controller{
		log:          log,
		fileSelector: CachedFileSelector{},
		redisConn:    redisConn,
	}

	return c, c.initCron()
}

func (c *Controller) initCron() error {
	cronJob = cron.New()
	if err := cronJob.AddFunc(SCHEDULE, c.generate); err != nil {
		return err
	}
	cronJob.Start()

	return nil
}

func (c *Controller) Shutdown() {
	cronJob.Stop()
}

func (c *Controller) generate() {
	c.log.Info("Sitemap update started")
	for {
		name, err := c.fileSelector.Select()
		if err == redis.ErrNil {
			return
		}

		if err != nil {
			c.log.Error("Could not fetch file name: %s", err)
			return
		}
		c.log.Info("Updating sitemap: %s", name)
		// there is not any waiting sitemap updates
		if name == "" {
			return
		}

		c.fileName = name

		els, err := c.fetchElements()
		if err != nil {
			c.log.Critical("Could not fetch updated elements: %s", err)
			c.handleError(els)
			continue
		}

		if len(els) == 0 {
			c.log.Info("Items are already added")
			continue
		}

		container := c.buildContainer(els)

		if err := c.updateFile(container); err != nil {
			c.handleError(els)
			c.log.Critical("Could not update file: %s", err)
			continue
		}

	}
}

// handleError re-adds updated items to next file update queue
func (c *Controller) handleError(items []*models.SitemapItem) {
	// re-add filename to next queue
	key := common.PrepareNextFileNameCacheKey()
	if _, err := c.redisConn.AddSetMembers(key, c.fileName); err != nil {
		c.log.Critical("Could not re-add the filename: %s", err)
		return
	}

	key = common.PrepareNextFileCacheKey(c.fileName)
	values := make([]interface{}, len(items))
	for k := range items {
		values[k] = items[k].PrepareSetValue()
	}

	if _, err := c.redisConn.AddSetMembers(key, values...); err != nil {
		c.log.Critical("Could not re-add the updated items: %s", err)
	}

}

func (c *Controller) fetchElements() ([]*models.SitemapItem, error) {
	key := common.PrepareCurrentFileCacheKey(c.fileName)
	els := make([]*models.SitemapItem, 0)

	members, err := c.redisConn.GetSetMembers(key)
	if err != nil && err != redis.ErrNil {
		return nil, err
	}

	for i := range members {
		item, err := c.redisConn.String(members[i])
		if err != nil {
			c.log.Error("Could not convert item: %s", err)
			continue
		}
		if item == "" {
			continue
		}

		i := &models.SitemapItem{}
		// if there is a syntax error in item, do not need to try to
		// recreate it
		if err := i.Populate(item); err != nil {
			c.log.Error("Could not get item %s: %s", item, err)
			continue
		}
		els = append(els, i)
	}
	if _, err := c.redisConn.Del(key); err != nil {
		c.log.Error("Could not delete key %s: %s", key, err)
	}

	return els, nil
}

func (c *Controller) updateFile(container *models.ItemContainer) error {
	sf := models.NewSitemapFile()
	newItem := false
	err := sf.ByName(c.fileName)
	if err == bongo.RecordNotFound {
		newItem = true
	}

	if err != nil && !newItem {
		return err
	}

	s := models.NewItemSet()
	if !newItem && len(sf.Blob) > 0 {
		if err := xml.Unmarshal(sf.Blob, &s); err != nil {
			return err
		}
	}

	s.Populate(container)
	v, err := xml.Marshal(s)
	if err != nil {
		return err
	}
	sf.Blob = v

	if newItem {
		sf.Name = c.fileName
		return sf.Create()
	}

	return sf.Update()
}

func (c *Controller) buildContainer(items []*models.SitemapItem) *models.ItemContainer {
	container := models.NewItemContainer()
	for _, v := range items {
		item := v.Definition(config.Get().Uri)
		switch v.Status {
		case models.STATUS_ADD:
			container.Add = append(container.Add, item)
		case models.STATUS_DELETE:
			container.Delete = append(container.Delete, item)
		case models.STATUS_UPDATE:
			container.Update = append(container.Update, item)
		}
	}

	return container
}
<|endoftext|>