<commit_before>package cryptopals

import (
	"crypto/rand"
	"fmt"
	"math/big"

	"strings"
	"testing"

	"github.com/ianferguson/cryptopals/encodings"
	"github.com/ianferguson/cryptopals/pkcs7"
	"github.com/ianferguson/cryptopals/unsafeaes"
)

func TestChallenge9(test *testing.T) {
	padded := pkcs7.Pad([]byte("YELLOW SUBMARINE"), 20)
	if len(padded) != 20 {
		test.Errorf("returned slice should've had a length of 20, but was %v", len(padded))
	}

	expected := "YELLOW SUBMARINE\x04\x04\x04\x04"
	if string(padded) != expected {
		test.Errorf("padding returned %q instead of %q", string(padded), expected)
	}
}

// I'm back and I'm ringin' the bell
func TestChallenge10(test *testing.T) {
	key := []byte("YELLOW SUBMARINE")
	ciphertext := encodings.Base64ToBytes(getURL("https://cryptopals.com/static/challenge-data/10.txt"))
	decrypted, err := unsafeaes.DecryptCBC(ciphertext, key)
	if err != nil {
		panic(err)
	}

	if !strings.Contains(string(decrypted), "bell") {
		test.Errorf("Expected %s to contain the phrase I'm back and I'm ringin' the bell", string(decrypted))
	}
}

/*
Now that you have ECB and CBC working:

Write a function to generate a random AES key; that's just 16 random bytes.

Write a function that encrypts data under an unknown key --- that is, a function that generates a random key and
encrypts under it.

The function should look like:

encryption_oracle(your-input)
=> [MEANINGLESS JIBBER JABBER]
Under the hood, have the function append 5-10 bytes (count chosen randomly) before the plaintext and 5-10 bytes
after the plaintext.

Now, have the function choose to encrypt under ECB 1/2 the time, and under CBC the other half (just use random IVs each
time for CBC).
Use rand(2) to decide which to use.

Detect the block cipher mode the function is using each time. You should end up with a piece of code that, pointed at
a block box that might be encrypting ECB or CBC, tells you which one is happening.
*/
func TestChallenge11Cbc(test *testing.T) {
	mode, err := unsafeaes.DetectMode(cbcOracle{})
	if err != nil {
		panic(err)
	}

	if mode != "CBC" {
		test.Errorf("expected AES mode CBC to be detected but instead detected %s", mode)
	}
}

type cbcOracle struct{}

func (oracle cbcOracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	frontPad := randomBytes(5, 10)
	backPad := randomBytes(5, 10)
	plaintext := append(append(frontPad, input...), backPad...)
	key := key(16)
	return unsafeaes.EncryptCBC(plaintext, key)
}

func TestChallenge11Ecb(test *testing.T) {
	mode, err := unsafeaes.DetectMode(ecbOracle{})
	if err != nil {
		panic(err)
	}

	if mode != "ECB" {
		test.Errorf("expected AES mode ECB to be detected but instead detected %s", mode)
	}
}

type ecbOracle struct{}

func (oracle ecbOracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	frontPad := randomBytes(5, 10)
	backPad := randomBytes(5, 10)
	plaintext := append(append(frontPad, input...), backPad...)
	key := key(16)
	return unsafeaes.EncryptECB(plaintext, key)
}

// decode encrypted text returned by an oracle
// challenge guidlines/steps are interpolated as comments
func TestChallenge12(test *testing.T) {
	// Feed identical bytes of your-string to the function 1 at a time --- start with 1 byte ("A"),
	// then "AA", then "AAA" and so on. Discover the block size of the cipher. You know it, but do this step anyway.
	oracle := challenge12Oracle{key(16)}
	blockSize, err := unsafeaes.DetectBlockSize(oracle)
	if err != nil {
		panic(err)
	}
	if blockSize != 16 {
		test.Errorf("Expected block size to be 16 but was %d", blockSize)
	}

	// Detect that the function is using ECB. You already know, but do this step anyways.
	mode, err := unsafeaes.DetectMode(oracle)
	if err != nil {
		panic(err)
	}
	if mode != "ECB" {
		test.Errorf("Expected to detect AES mode ECB, but instead detected %s", mode)
	}

	// Knowing the block size, craft an input block that is exactly 1 byte short (for instance, if the block size is
	// 8 bytes, make "AAAAAAA"). Think about what the oracle function is going to put in that last byte position.
	shortBlock := make([]byte, blockSize-1)
	plaintextSize, err := findTextLength(oracle)
	if err != nil {
		panic(err)
	}
	test.Logf("Oracle's plaintext is %d bytes long", plaintextSize)

	// Make a dictionary of every possible last byte by feeding different strings to the oracle; for instance, "AAAAAAAA",
	// "AAAAAAAB", "AAAAAAAC", remembering the first block of each invocation.
	lastbyte := make(map[string]byte)

	// XXX handle 255 without rolling over and missing the loop condition
	for b := 0; b < 256; b++ {
		fmt.Printf("Evaluating byte %x\n", b)
		ciphertext, err := oracle.Encrypt(append(shortBlock, byte(b)))
		if err != nil {
			panic(err)
		}
		firstBlock := ciphertext[:blockSize]
		fmt.Printf("Got back %x\n", firstBlock)
		lastbyte[encodings.BytesToHex(firstBlock)] = byte(b)
	}

	ciphertext, err := oracle.Encrypt(shortBlock)
	if err != nil {
		panic(err)
	}

	// Match the output of the one-byte-short input to one of the entries in your dictionary.
	// You've now discovered the first byte of unknown-string.
	firstBlock := ciphertext[:blockSize]
	b := lastbyte[encodings.BytesToHex(firstBlock)]
	test.Logf("found byte %x/%#U for %x", b, rune(b), firstBlock)

	// Repeat for the next byte.

	test.Error("not yet implemented")
}

func findTextLength(oracle unsafeaes.Oracle) (length int, err error) {
	maxPadSize := 1024
	for padSize := 0; padSize < maxPadSize; padSize++ {
		plaintext := make([]byte, padSize)
		ciphertext, err := oracle.Encrypt(plaintext)
		if err != nil {
			return -1, err
		}

		if length == 0 {
			length = len(ciphertext)
		}

		if len(ciphertext) > length {
			return len(ciphertext) - padSize, nil
		}
	}

	return -1, fmt.Errorf("Unable to detect size of hidden text used by oracle, tested up to %d bytes in padding", maxPadSize)
}

type challenge12Oracle struct {
	key []byte
}

func (this challenge12Oracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	backPad := encodings.Base64ToBytes("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg" +
		"aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq" +
		"dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg")
	plaintext := append(input, backPad...)
	return unsafeaes.EncryptECB(plaintext, this.key)
}

// XXX below here is not for final commit, sketch space for Set 2, Challenge 11-12
func key(size int) []byte {
	key := make([]byte, size)
	_, err := rand.Read(key)
	if err != nil {
		panic("unreachable")
	}
	return key
}

func randomBytes(min, max int) []byte {
	random, err := rand.Int(rand.Reader, big.NewInt(int64(max-min)))
	if err != nil {
		panic(err)
	}
	return make([]byte, random.Add(random, big.NewInt(int64(min))).Int64())
}
<commit_msg>Challenge 12 almost working (though gnarly)<commit_after>package cryptopals

import (
	"crypto/rand"
	"fmt"
	"math/big"

	"strings"
	"testing"

	"github.com/ianferguson/cryptopals/encodings"
	"github.com/ianferguson/cryptopals/pkcs7"
	"github.com/ianferguson/cryptopals/unsafeaes"
)

func TestChallenge9(test *testing.T) {
	padded := pkcs7.Pad([]byte("YELLOW SUBMARINE"), 20)
	if len(padded) != 20 {
		test.Errorf("returned slice should've had a length of 20, but was %v", len(padded))
	}

	expected := "YELLOW SUBMARINE\x04\x04\x04\x04"
	if string(padded) != expected {
		test.Errorf("padding returned %q instead of %q", string(padded), expected)
	}
}

// I'm back and I'm ringin' the bell
func TestChallenge10(test *testing.T) {
	key := []byte("YELLOW SUBMARINE")
	ciphertext := encodings.Base64ToBytes(getURL("https://cryptopals.com/static/challenge-data/10.txt"))
	decrypted, err := unsafeaes.DecryptCBC(ciphertext, key)
	if err != nil {
		panic(err)
	}

	if !strings.Contains(string(decrypted), "bell") {
		test.Errorf("Expected %s to contain the phrase I'm back and I'm ringin' the bell", string(decrypted))
	}
}

/*
Now that you have ECB and CBC working:

Write a function to generate a random AES key; that's just 16 random bytes.

Write a function that encrypts data under an unknown key --- that is, a function that generates a random key and
encrypts under it.

The function should look like:

encryption_oracle(your-input)
=> [MEANINGLESS JIBBER JABBER]
Under the hood, have the function append 5-10 bytes (count chosen randomly) before the plaintext and 5-10 bytes
after the plaintext.

Now, have the function choose to encrypt under ECB 1/2 the time, and under CBC the other half (just use random IVs each
time for CBC).
Use rand(2) to decide which to use.

Detect the block cipher mode the function is using each time. You should end up with a piece of code that, pointed at
a block box that might be encrypting ECB or CBC, tells you which one is happening.
*/
func TestChallenge11Cbc(test *testing.T) {
	mode, err := unsafeaes.DetectMode(cbcOracle{})
	if err != nil {
		panic(err)
	}

	if mode != "CBC" {
		test.Errorf("expected AES mode CBC to be detected but instead detected %s", mode)
	}
}

type cbcOracle struct{}

func (oracle cbcOracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	frontPad := randomBytes(5, 10)
	backPad := randomBytes(5, 10)
	plaintext := append(append(frontPad, input...), backPad...)
	key := key(16)
	return unsafeaes.EncryptCBC(plaintext, key)
}

func TestChallenge11Ecb(test *testing.T) {
	mode, err := unsafeaes.DetectMode(ecbOracle{})
	if err != nil {
		panic(err)
	}

	if mode != "ECB" {
		test.Errorf("expected AES mode ECB to be detected but instead detected %s", mode)
	}
}

type ecbOracle struct{}

func (oracle ecbOracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	frontPad := randomBytes(5, 10)
	backPad := randomBytes(5, 10)
	plaintext := append(append(frontPad, input...), backPad...)
	key := key(16)
	return unsafeaes.EncryptECB(plaintext, key)
}

// decode encrypted text returned by an oracle
// challenge guidlines/steps are interpolated as comments
func TestChallenge12(test *testing.T) {
	// Feed identical bytes of your-string to the function 1 at a time --- start with 1 byte ("A"),
	// then "AA", then "AAA" and so on. Discover the block size of the cipher. You know it, but do this step anyway.
	oracle := challenge12Oracle{key(16)}
	blockSize, err := unsafeaes.DetectBlockSize(oracle)
	if err != nil {
		panic(err)
	}
	if blockSize != 16 {
		test.Errorf("Expected block size to be 16 but was %d", blockSize)
	}

	// Detect that the function is using ECB. You already know, but do this step anyways.
	mode, err := unsafeaes.DetectMode(oracle)
	if err != nil {
		panic(err)
	}
	if mode != "ECB" {
		test.Errorf("Expected to detect AES mode ECB, but instead detected %s", mode)
	}

	// Knowing the block size, craft an input block that is exactly 1 byte short (for instance, if the block size is
	// 8 bytes, make "AAAAAAA"). Think about what the oracle function is going to put in that last byte position.
	plaintextSize, err := findTextLength(oracle)
	if err != nil {
		panic(err)
	}
	test.Logf("Oracle's plaintext is %d bytes long", plaintextSize)
	// round up to the nearest full block size, so we have enough capacity
	// in our chosen text to slurp up the target text char by char
	blocks := (plaintextSize / blockSize) + 1
	plaintext := make([]byte, 0, plaintextSize)
	for i := 1; i <= plaintextSize; i++ {
		chosentext := make([]byte, (blocks*blockSize)-i)
		// Make a dictionary of every possible last byte by feeding different strings to the oracle; for instance, "AAAAAAAA",
		// "AAAAAAAB", "AAAAAAAC", remembering the first block of each invocation.
		lastbyte := make(map[string]byte)

		for b := 0; b < 256; b++ {
			knowntext := append(chosentext, plaintext...)
			testtext := append(knowntext, byte(b))
			ciphertext, err := oracle.Encrypt(testtext)
			if err != nil {
				panic(err)
			}
			firstBlock := ciphertext[:blocks*blockSize]
			lastbyte[encodings.BytesToHex(firstBlock)] = byte(b)
		}

		ciphertext, err := oracle.Encrypt(chosentext)
		if err != nil {
			panic(err)
		}

		// Match the output of the one-byte-short input to one of the entries in your dictionary.
		// You've now discovered the first byte of unknown-string.
		firstBlock := ciphertext[:blocks*blockSize]
		b := lastbyte[encodings.BytesToHex(firstBlock)]
		plaintext = append(plaintext, b)
		test.Logf("%s", plaintext)
	}

	expected := "# Rollin' in my 5.0\n" +
		"With my rag-top down so my hair can blow\n" +
		"The girlies on standby waving just to say hi\n" +
		"Did you stop? No, I just drove by"
	if string(plaintext) != expected {
		test.Errorf("Expected:\n%s\nActual:\n%s\n", expected, string(plaintext))
	}
}

func findTextLength(oracle unsafeaes.Oracle) (length int, err error) {
	maxPadSize := 1024
	for padSize := 0; padSize < maxPadSize; padSize++ {
		plaintext := make([]byte, padSize)
		ciphertext, err := oracle.Encrypt(plaintext)
		if err != nil {
			return -1, err
		}

		if length == 0 {
			length = len(ciphertext)
		}

		if len(ciphertext) > length {
			return len(ciphertext) - padSize, nil
		}
	}

	return -1, fmt.Errorf("Unable to detect size of hidden text used by oracle, tested up to %d bytes in padding", maxPadSize)
}

type challenge12Oracle struct {
	key []byte
}

func (this challenge12Oracle) Encrypt(input []byte) (ciphertext []byte, err error) {
	backPad := encodings.Base64ToBytes("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg" +
		"aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq" +
		"dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg")
	plaintext := append(input, backPad...)
	return unsafeaes.EncryptECB(plaintext, this.key)
}

// XXX below here is not for final commit, sketch space for Set 2, Challenge 11-12
func key(size int) []byte {
	key := make([]byte, size)
	_, err := rand.Read(key)
	if err != nil {
		panic("unreachable")
	}
	return key
}

func randomBytes(min, max int) []byte {
	random, err := rand.Int(rand.Reader, big.NewInt(int64(max-min)))
	if err != nil {
		panic(err)
	}
	return make([]byte, random.Add(random, big.NewInt(int64(min))).Int64())
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.105"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.72", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<commit_msg>fnlb: 0.0.106 release [skip ci]<commit_after>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.106"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.73", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
)

const VERSION = "0.0.24"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.7", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<commit_msg>fnlb: 0.0.25 release [skip ci]<commit_after>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
)

const VERSION = "0.0.25"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.7", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.78"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.45", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<commit_msg>fnlb: 0.0.79 release [skip ci]<commit_after>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.79"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.46", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<|endoftext|>


<commit_before>package linode

import (
	"context"
	"fmt"
	"strconv"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/linode/linodego"
)

func TestAccLinodeStackscriptBasic(t *testing.T) {
	t.Parallel()

	resName := "linode_stackscript.foobar"
	var stackscriptName = acctest.RandomWithPrefix("tf_test")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},

			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func TestAccLinodeStackscriptUpdate(t *testing.T) {
	t.Parallel()

	var stackscriptName = acctest.RandomWithPrefix("tf_test")
	var resName = "linode_stackscript.foobar"
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasicRenamed(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", fmt.Sprintf("%s_renamed", stackscriptName)),
				),
			},
			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func TestAccLinodeStackscriptCodeChange(t *testing.T) {
	t.Parallel()

	var stackscriptName = acctest.RandomWithPrefix("tf_test")
	var resName = "linode_stackscript.foobar"
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "script", "#!/bin/bash\necho hello\n"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptCodeChange(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "second"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "images.1", "linode/ubuntu16.04lts"),
					resource.TestCheckResourceAttr(resName, "script", "#!/bin/bash\necho bye\n"),
					resource.TestCheckResourceAttr(resName, "label", fmt.Sprintf("%s", stackscriptName)),
				),
			},
			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func testAccCheckLinodeStackscriptExists(s *terraform.State) error {
	client := testAccProvider.Meta().(linodego.Client)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "linode_stackscript" {
			continue
		}

		id, err := strconv.Atoi(rs.Primary.ID)

		_, err = client.GetStackscript(context.Background(), id)
		if err != nil {
			return fmt.Errorf("Error retrieving state of Stackscript %s: %s", rs.Primary.Attributes["label"], err)
		}
	}

	return nil
}

func testAccCheckLinodeStackscriptDestroy(s *terraform.State) error {
	client, ok := testAccProvider.Meta().(linodego.Client)
	if !ok {
		return fmt.Errorf("Error getting Linode client")
	}
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "linode_stackscript" {
			continue
		}

		id, err := strconv.Atoi(rs.Primary.ID)
		if err != nil {
			return fmt.Errorf("Error parsing %v to int", rs.Primary.ID)
		}
		if id == 0 {
			return fmt.Errorf("Would have considered %v as %d", rs.Primary.ID, id)

		}

		_, err = client.GetStackscript(context.Background(), id)

		if err == nil {
			return fmt.Errorf("Linode Stackscript with id %d still exists", id)
		}

		if apiErr, ok := err.(*linodego.Error); ok && apiErr.Code != 404 {
			return fmt.Errorf("Error requesting Linode Stackscript with id %d", id)
		}
	}

	return nil
}

func testAccCheckLinodeStackscriptBasic(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s"
	script = <<EOF
#!/bin/bash
echo hello
EOF
	images = ["linode/ubuntu18.04"]
	description = "tf_test stackscript"
	rev_note = "initial"
}`, stackscript)
}

func testAccCheckLinodeStackscriptBasicRenamed(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s_renamed"
	script = <<EOF
#!/bin/bash
echo hello
EOF
	images = ["linode/ubuntu18.04"]
	description = "tf_test stackscript"
	rev_note = "initial"
}`, stackscript)
}

func testAccCheckLinodeStackscriptCodeChange(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s"
	script = <<EOF
#!/bin/bash
echo bye
EOF
	images = ["linode/ubuntu18.04", "linode/ubuntu16.04lts"]
	description = "tf_test stackscript"
	rev_note = "second"
}`, stackscript)
}
<commit_msg>rename stackscript tests so their names can be used as a test list pattern<commit_after>package linode

import (
	"context"
	"fmt"
	"strconv"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/linode/linodego"
)

func TestAccLinodeStackscript_basic(t *testing.T) {
	t.Parallel()

	resName := "linode_stackscript.foobar"
	var stackscriptName = acctest.RandomWithPrefix("tf_test")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},

			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func TestAccLinodeStackscript_update(t *testing.T) {
	t.Parallel()

	var stackscriptName = acctest.RandomWithPrefix("tf_test")
	var resName = "linode_stackscript.foobar"
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasicRenamed(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "label", fmt.Sprintf("%s_renamed", stackscriptName)),
				),
			},
			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func TestAccLinodeStackscript_codeChange(t *testing.T) {
	t.Parallel()

	var stackscriptName = acctest.RandomWithPrefix("tf_test")
	var resName = "linode_stackscript.foobar"
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckLinodeStackscriptDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptBasic(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "initial"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "script", "#!/bin/bash\necho hello\n"),
					resource.TestCheckResourceAttr(resName, "label", stackscriptName),
				),
			},
			resource.TestStep{
				Config: testAccCheckLinodeStackscriptCodeChange(stackscriptName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckLinodeStackscriptExists,
					resource.TestCheckResourceAttr(resName, "description", "tf_test stackscript"),
					resource.TestCheckResourceAttr(resName, "rev_note", "second"),
					resource.TestCheckResourceAttr(resName, "images.0", "linode/ubuntu18.04"),
					resource.TestCheckResourceAttr(resName, "images.1", "linode/ubuntu16.04lts"),
					resource.TestCheckResourceAttr(resName, "script", "#!/bin/bash\necho bye\n"),
					resource.TestCheckResourceAttr(resName, "label", fmt.Sprintf("%s", stackscriptName)),
				),
			},
			resource.TestStep{
				ResourceName: resName,
				ImportState:  true,
			},
		},
	})
}

func testAccCheckLinodeStackscriptExists(s *terraform.State) error {
	client := testAccProvider.Meta().(linodego.Client)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "linode_stackscript" {
			continue
		}

		id, err := strconv.Atoi(rs.Primary.ID)

		_, err = client.GetStackscript(context.Background(), id)
		if err != nil {
			return fmt.Errorf("Error retrieving state of Stackscript %s: %s", rs.Primary.Attributes["label"], err)
		}
	}

	return nil
}

func testAccCheckLinodeStackscriptDestroy(s *terraform.State) error {
	client, ok := testAccProvider.Meta().(linodego.Client)
	if !ok {
		return fmt.Errorf("Error getting Linode client")
	}
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "linode_stackscript" {
			continue
		}

		id, err := strconv.Atoi(rs.Primary.ID)
		if err != nil {
			return fmt.Errorf("Error parsing %v to int", rs.Primary.ID)
		}
		if id == 0 {
			return fmt.Errorf("Would have considered %v as %d", rs.Primary.ID, id)

		}

		_, err = client.GetStackscript(context.Background(), id)

		if err == nil {
			return fmt.Errorf("Linode Stackscript with id %d still exists", id)
		}

		if apiErr, ok := err.(*linodego.Error); ok && apiErr.Code != 404 {
			return fmt.Errorf("Error requesting Linode Stackscript with id %d", id)
		}
	}

	return nil
}

func testAccCheckLinodeStackscriptBasic(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s"
	script = <<EOF
#!/bin/bash
echo hello
EOF
	images = ["linode/ubuntu18.04"]
	description = "tf_test stackscript"
	rev_note = "initial"
}`, stackscript)
}

func testAccCheckLinodeStackscriptBasicRenamed(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s_renamed"
	script = <<EOF
#!/bin/bash
echo hello
EOF
	images = ["linode/ubuntu18.04"]
	description = "tf_test stackscript"
	rev_note = "initial"
}`, stackscript)
}

func testAccCheckLinodeStackscriptCodeChange(stackscript string) string {
	return fmt.Sprintf(`
resource "linode_stackscript" "foobar" {
	label = "%s"
	script = <<EOF
#!/bin/bash
echo bye
EOF
	images = ["linode/ubuntu18.04", "linode/ubuntu16.04lts"]
	description = "tf_test stackscript"
	rev_note = "second"
}`, stackscript)
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 JT Olds
// See LICENSE for copying information

// Package whlog provides functionality to log incoming requests and results.
package whlog // import "gopkg.in/webhelp.v1/whlog"

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

	"gopkg.in/webhelp.v1/whmon"
	"gopkg.in/webhelp.v1/whroute"
)

type Loggerf func(format string, arg ...interface{})

var (
	Default Loggerf = log.Printf
)

// LogRequests takes a Handler and makes it log requests. LogRequests uses
// whmon's ResponseWriter to keep track of activity. whfatal.Catch should be
// placed *inside* if applicable. whlog.Default makes a good default logger.
func LogRequests(logger Loggerf, h http.Handler) http.Handler {
	return whroute.HandlerFunc(h,
		func(w http.ResponseWriter, r *http.Request) {
			method, requestURI := r.Method, r.RequestURI
			rw := whmon.WrapResponseWriter(w)
			start := time.Now()

			defer func() {
				rec := recover()
				if rec != nil {
					log.Printf("Panic: %v", rec)
					panic(rec)
				}
			}()
			h.ServeHTTP(rw, r)

			if !rw.WroteHeader() {
				rw.WriteHeader(http.StatusOK)
			}

			code := rw.StatusCode()

			logger(`%s %#v %d %d %d %v`, method, requestURI, code,
				r.ContentLength, rw.Written(), time.Since(start))
		})
}
<commit_msg>whlog: separate LogRequests and LogResponses<commit_after>// Copyright (C) 2016 JT Olds
// See LICENSE for copying information

// Package whlog provides functionality to log incoming requests and results.
package whlog // import "gopkg.in/webhelp.v1/whlog"

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

	"gopkg.in/webhelp.v1/whmon"
	"gopkg.in/webhelp.v1/whroute"
)

type Loggerf func(format string, arg ...interface{})

var (
	Default Loggerf = log.Printf
)

// LogResponses takes a Handler and makes it log responses. LogResponses uses
// whmon's ResponseWriter to keep track of activity. whfatal.Catch should be
// placed *inside* if applicable. whlog.Default makes a good default logger.
func LogResponses(logger Loggerf, h http.Handler) http.Handler {
	return whroute.HandlerFunc(h,
		func(w http.ResponseWriter, r *http.Request) {
			method, requestURI := r.Method, r.RequestURI
			rw := whmon.WrapResponseWriter(w)
			start := time.Now()

			defer func() {
				rec := recover()
				if rec != nil {
					log.Printf("Panic: %v", rec)
					panic(rec)
				}
			}()
			h.ServeHTTP(rw, r)

			if !rw.WroteHeader() {
				rw.WriteHeader(http.StatusOK)
			}

			code := rw.StatusCode()

			logger(`%s %#v %d %d %d %v`, method, requestURI, code,
				r.ContentLength, rw.Written(), time.Since(start))
		})
}

// LogRequests takes a Handler and makes it log requests (prior to request
// handling). whlog.Default makes a good default logger.
func LogRequests(logger Loggerf, h http.Handler) http.Handler {
	return whroute.HandlerFunc(h,
		func(w http.ResponseWriter, r *http.Request) {
			logger(`%s %#v %d`, r.Method, r.RequestURI, r.ContentLength)
			h.ServeHTTP(w, r)
		})
}
<|endoftext|>


<commit_before>// +build windows

package host

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"strings"
	"sync/atomic"
	"syscall"
	"time"
	"unsafe"

	"github.com/shirou/gopsutil/internal/common"
	process "github.com/shirou/gopsutil/process"
	"golang.org/x/sys/windows"
	"golang.org/x/sys/windows/registry"
)

var (
	procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
	procGetTickCount32          = common.Modkernel32.NewProc("GetTickCount")
	procGetTickCount64          = common.Modkernel32.NewProc("GetTickCount64")
	procRtlGetVersion           = common.ModNt.NewProc("RtlGetVersion")
)

// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
type osVersionInfoExW struct {
	dwOSVersionInfoSize uint32
	dwMajorVersion      uint32
	dwMinorVersion      uint32
	dwBuildNumber       uint32
	dwPlatformId        uint32
	szCSDVersion        [128]uint16
	wServicePackMajor   uint16
	wServicePackMinor   uint16
	wSuiteMask          uint16
	wProductType        uint8
	wReserved           uint8
}

func Info() (*InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) (*InfoStat, error) {
	ret := &InfoStat{
		OS: runtime.GOOS,
	}

	{
		hostname, err := os.Hostname()
		if err == nil {
			ret.Hostname = hostname
		}
	}

	{
		platform, family, version, err := PlatformInformation()
		if err == nil {
			ret.Platform = platform
			ret.PlatformFamily = family
			ret.PlatformVersion = version
		} else {
			return ret, err
		}
	}

	{
		boot, err := BootTime()
		if err == nil {
			ret.BootTime = boot
			ret.Uptime, _ = Uptime()
		}
	}

	{
		hostID, err := getMachineGuid()
		if err == nil {
			ret.HostID = strings.ToLower(hostID)
		}
	}

	{
		procs, err := process.Pids()
		if err == nil {
			ret.Procs = uint64(len(procs))
		}
	}

	return ret, nil
}

func getMachineGuid() (string, error) {
	var h windows.Handle
	err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Cryptography`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
	if err != nil {
		return "", err
	}
	defer windows.RegCloseKey(h)

	const windowsRegBufLen = 74 // len(`{`) + len(`abcdefgh-1234-456789012-123345456671` * 2) + len(`}`) // 2 == bytes/UTF16
	const uuidLen = 36

	var regBuf [windowsRegBufLen]uint16
	bufLen := uint32(windowsRegBufLen)
	var valType uint32
	err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`MachineGuid`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
	if err != nil {
		return "", err
	}

	hostID := windows.UTF16ToString(regBuf[:])
	hostIDLen := len(hostID)
	if hostIDLen != uuidLen {
		return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
	}

	return hostID, nil
}

func Uptime() (uint64, error) {
	return UptimeWithContext(context.Background())
}

func UptimeWithContext(ctx context.Context) (uint64, error) {
	procGetTickCount := procGetTickCount64
	err := procGetTickCount64.Find()
	if err != nil {
		procGetTickCount = procGetTickCount32 // handle WinXP, but keep in mind that "the time will wrap around to zero if the system is run continuously for 49.7 days." from MSDN
	}
	r1, _, lastErr := syscall.Syscall(procGetTickCount.Addr(), 0, 0, 0, 0)
	if lastErr != 0 {
		return 0, lastErr
	}
	return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
}

func bootTimeFromUptime(up uint64) uint64 {
	return uint64(time.Now().Unix()) - up
}

// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64

func BootTime() (uint64, error) {
	return BootTimeWithContext(context.Background())
}

func BootTimeWithContext(ctx context.Context) (uint64, error) {
	t := atomic.LoadUint64(&cachedBootTime)
	if t != 0 {
		return t, nil
	}
	up, err := Uptime()
	if err != nil {
		return 0, err
	}
	t = bootTimeFromUptime(up)
	atomic.StoreUint64(&cachedBootTime, t)
	return t, nil
}

func PlatformInformation() (platform string, family string, version string, err error) {
	return PlatformInformationWithContext(context.Background())
}

func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
	// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
	// RtlGetVersion bypasses this lying layer and returns the true Windows version
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
	var osInfo osVersionInfoExW
	osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
	ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
	if ret != 0 {
		return
	}

	// Platform
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
	if err != nil {
		return
	}
	defer k.Close()
	platform, _, err = k.GetStringValue("ProductName")
	if err != nil {
		return
	}
	if !strings.HasPrefix(platform, "Microsoft") {
		platform = "Microsoft " + platform
	}
	csd, _, err := k.GetStringValue("CSDVersion")
	if err == nil {
		platform += " " + csd
	}

	// PlatformFamily
	switch osInfo.wProductType {
	case 1:
		family = "Standalone Workstation"
	case 2:
		family = "Server (Domain Controller)"
	case 3:
		family = "Server"
	}

	// Platform Version
	version = fmt.Sprintf("%d.%d.%d Build %d", osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.dwBuildNumber)

	return
}

func Users() ([]UserStat, error) {
	return UsersWithContext(context.Background())
}

func UsersWithContext(ctx context.Context) ([]UserStat, error) {
	var ret []UserStat

	return ret, nil
}

func SensorsTemperatures() ([]TemperatureStat, error) {
	return SensorsTemperaturesWithContext(context.Background())
}

func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
	return []TemperatureStat{}, common.ErrNotImplementedError
}

func Virtualization() (string, string, error) {
	return VirtualizationWithContext(context.Background())
}

func VirtualizationWithContext(ctx context.Context) (string, string, error) {
	return "", "", common.ErrNotImplementedError
}

func KernelVersion() (string, error) {
	return KernelVersionWithContext(context.Background())
}

func KernelVersionWithContext(ctx context.Context) (string, error) {
	_, _, version, err := PlatformInformation()
	return version, err
}
<commit_msg>[host][windows] Refactor code to query registry via golang.org/x/sys/windows/registry<commit_after>// +build windows

package host

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"strings"
	"sync/atomic"
	"syscall"
	"time"
	"unsafe"

	"github.com/shirou/gopsutil/internal/common"
	process "github.com/shirou/gopsutil/process"
	"golang.org/x/sys/windows/registry"
)

var (
	procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
	procGetTickCount32          = common.Modkernel32.NewProc("GetTickCount")
	procGetTickCount64          = common.Modkernel32.NewProc("GetTickCount64")
	procRtlGetVersion           = common.ModNt.NewProc("RtlGetVersion")
)

// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
type osVersionInfoExW struct {
	dwOSVersionInfoSize uint32
	dwMajorVersion      uint32
	dwMinorVersion      uint32
	dwBuildNumber       uint32
	dwPlatformId        uint32
	szCSDVersion        [128]uint16
	wServicePackMajor   uint16
	wServicePackMinor   uint16
	wSuiteMask          uint16
	wProductType        uint8
	wReserved           uint8
}

func Info() (*InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) (*InfoStat, error) {
	ret := &InfoStat{
		OS: runtime.GOOS,
	}

	{
		hostname, err := os.Hostname()
		if err == nil {
			ret.Hostname = hostname
		}
	}

	{
		platform, family, version, err := PlatformInformation()
		if err == nil {
			ret.Platform = platform
			ret.PlatformFamily = family
			ret.PlatformVersion = version
		} else {
			return ret, err
		}
	}

	{
		boot, err := BootTime()
		if err == nil {
			ret.BootTime = boot
			ret.Uptime, _ = Uptime()
		}
	}

	{
		hostID, err := getMachineGuid()
		if err == nil {
			ret.HostID = strings.ToLower(hostID)
		}
	}

	{
		procs, err := process.Pids()
		if err == nil {
			ret.Procs = uint64(len(procs))
		}
	}

	return ret, nil
}

func getMachineGuid() (string, error) {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.QUERY_VALUE)
	if err != nil {
		return "", err
	}
	defer k.Close()
	hostID, _, err := k.GetStringValue("MachineGuid")
	if err != nil {
		return "", err
	}
	return hostID, nil
}

func Uptime() (uint64, error) {
	return UptimeWithContext(context.Background())
}

func UptimeWithContext(ctx context.Context) (uint64, error) {
	procGetTickCount := procGetTickCount64
	err := procGetTickCount64.Find()
	if err != nil {
		procGetTickCount = procGetTickCount32 // handle WinXP, but keep in mind that "the time will wrap around to zero if the system is run continuously for 49.7 days." from MSDN
	}
	r1, _, lastErr := syscall.Syscall(procGetTickCount.Addr(), 0, 0, 0, 0)
	if lastErr != 0 {
		return 0, lastErr
	}
	return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
}

func bootTimeFromUptime(up uint64) uint64 {
	return uint64(time.Now().Unix()) - up
}

// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64

func BootTime() (uint64, error) {
	return BootTimeWithContext(context.Background())
}

func BootTimeWithContext(ctx context.Context) (uint64, error) {
	t := atomic.LoadUint64(&cachedBootTime)
	if t != 0 {
		return t, nil
	}
	up, err := Uptime()
	if err != nil {
		return 0, err
	}
	t = bootTimeFromUptime(up)
	atomic.StoreUint64(&cachedBootTime, t)
	return t, nil
}

func PlatformInformation() (platform string, family string, version string, err error) {
	return PlatformInformationWithContext(context.Background())
}

func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
	// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
	// RtlGetVersion bypasses this lying layer and returns the true Windows version
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
	var osInfo osVersionInfoExW
	osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
	ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
	if ret != 0 {
		return
	}

	// Platform
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
	if err != nil {
		return
	}
	defer k.Close()
	platform, _, err = k.GetStringValue("ProductName")
	if err != nil {
		return
	}
	if !strings.HasPrefix(platform, "Microsoft") {
		platform = "Microsoft " + platform
	}
	csd, _, err := k.GetStringValue("CSDVersion")
	if err == nil {
		platform += " " + csd
	}

	// PlatformFamily
	switch osInfo.wProductType {
	case 1:
		family = "Standalone Workstation"
	case 2:
		family = "Server (Domain Controller)"
	case 3:
		family = "Server"
	}

	// Platform Version
	version = fmt.Sprintf("%d.%d.%d Build %d", osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.dwBuildNumber)

	return
}

func Users() ([]UserStat, error) {
	return UsersWithContext(context.Background())
}

func UsersWithContext(ctx context.Context) ([]UserStat, error) {
	var ret []UserStat

	return ret, nil
}

func SensorsTemperatures() ([]TemperatureStat, error) {
	return SensorsTemperaturesWithContext(context.Background())
}

func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
	return []TemperatureStat{}, common.ErrNotImplementedError
}

func Virtualization() (string, string, error) {
	return VirtualizationWithContext(context.Background())
}

func VirtualizationWithContext(ctx context.Context) (string, string, error) {
	return "", "", common.ErrNotImplementedError
}

func KernelVersion() (string, error) {
	return KernelVersionWithContext(context.Background())
}

func KernelVersionWithContext(ctx context.Context) (string, error) {
	_, _, version, err := PlatformInformation()
	return version, err
}
<|endoftext|>


<commit_before>package rule

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"sync/atomic"
	"time"

	"github.com/asciimoo/filtron/action"
	"github.com/asciimoo/filtron/selector"
	"github.com/asciimoo/filtron/types"
)

type Rule struct {
	Interval        uint64 `json:"interval"`
	Limit           uint64 `json:"limit"`
	Name            string `json:"name"`
	lastTick        uint64
	matchedRequests uint64
	Filters         []*selector.Selector `json:-`
	RawFilters      []string             `json:"filters"`
	Aggregations    []*Aggregation       `json:-`
	RawAggregations []string             `json:"aggregations"`
	Actions         []action.Action      `json:-`
	RawActions      []action.ActionJSON  `json:"actions"`
}

type Aggregation struct {
	sync.RWMutex
	Values   map[string]uint64
	Selector *selector.Selector
}

func New(name string, interval, limit uint64, filters []string) (*Rule, error) {
	r := &Rule{
		Interval: interval,
		Limit:    limit,
		Name:     name,
	}
	r.Init()
	if err := r.ParseFilters(filters); err != nil {
		return nil, err
	}
	return r, nil
}

func ParseJSON(filename string) ([]*Rule, error) {
	var rules []*Rule
	fileContent, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(fileContent, &rules)
	if err != nil {
		return nil, err
	}
	for _, r := range rules {
		if len(r.RawActions) == 0 {
			return nil, errors.New(fmt.Sprintf("Missing actions in rule: %v", r.Name))
		}
		r.Init()
		if err := r.ParseFilters(r.RawFilters); err != nil {
			return nil, err
		}
		if err := r.ParseAggregations(r.RawAggregations); err != nil {
			return nil, err
		}
		r.Actions = make([]action.Action, 0, len(r.RawActions))
		for _, actionJSON := range r.RawActions {
			a, err := action.Create(actionJSON)
			if err != nil {
				return nil, err
			}
			r.Actions = append(r.Actions, a)
		}
	}
	return rules, nil
}

func (r *Rule) Init() {
	r.matchedRequests = 0
	r.lastTick = uint64(time.Now().Unix())
}

func (r *Rule) ParseAggregations(aggregations []string) error {
	r.Aggregations = make([]*Aggregation, 0, len(aggregations))
	for _, t := range aggregations {
		s, err := selector.Parse(t)
		if err != nil {
			return errors.New(fmt.Sprintf("Cannot parse selector '%v': %v", t, err))
		}
		a := &Aggregation{
			Values:   make(map[string]uint64),
			Selector: s,
		}
		r.Aggregations = append(r.Aggregations, a)
	}
	return nil
}

func (r *Rule) ParseFilters(filters []string) error {
	r.Filters = make([]*selector.Selector, 0, len(filters))
	for _, t := range filters {
		s, err := selector.Parse(t)
		if err != nil {
			return errors.New(fmt.Sprintf("Cannot parse selector '%v': %v", t, err))
		}
		r.Filters = append(r.Filters, s)
	}
	return nil
}

func (r *Rule) Validate(req *http.Request, resp http.ResponseWriter) types.ResponseState {
	curTime := uint64(time.Now().Unix())
	if curTime-r.lastTick >= r.Interval {
		r.matchedRequests = 0
		r.lastTick = curTime
		for _, a := range r.Aggregations {
			a.Lock()
			a.Values = make(map[string]uint64)
			a.Unlock()
		}
	}
	for _, t := range r.Filters {
		if _, found := t.Match(req); !found {
			return types.UNTOUCHED
		}
	}
	matched := false
	state := types.UNTOUCHED
	if len(r.Aggregations) == 0 {
		atomic.AddUint64(&r.matchedRequests, 1)
		if r.matchedRequests > r.Limit {
			matched = true
		}
	} else {
		for _, a := range r.Aggregations {
			if a.Get(req) > r.Limit {
				matched = true
			}
		}
	}
	if matched {
		for _, a := range r.Actions {
			s, err := a.Act(req, resp)
			// TODO error handling
			if err != nil {
				fmt.Println("meh", err)
			}
			if s == types.SERVED {
				state = types.SERVED
			}
		}
	}
	return state
}

func (a *Aggregation) Get(req *http.Request) uint64 {
	if val, found := a.Selector.Match(req); found {
		a.Lock()
		a.Values[val] += 1
		v := a.Values[val]
		a.Unlock()
		return v
	}
	return 0
}
<commit_msg>[enh] do not reset rule counter if limit == 0<commit_after>package rule

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"sync/atomic"
	"time"

	"github.com/asciimoo/filtron/action"
	"github.com/asciimoo/filtron/selector"
	"github.com/asciimoo/filtron/types"
)

type Rule struct {
	Interval        uint64 `json:"interval"`
	Limit           uint64 `json:"limit"`
	Name            string `json:"name"`
	lastTick        uint64
	matchedRequests uint64
	Filters         []*selector.Selector `json:-`
	RawFilters      []string             `json:"filters"`
	Aggregations    []*Aggregation       `json:-`
	RawAggregations []string             `json:"aggregations"`
	Actions         []action.Action      `json:-`
	RawActions      []action.ActionJSON  `json:"actions"`
}

type Aggregation struct {
	sync.RWMutex
	Values   map[string]uint64
	Selector *selector.Selector
}

func New(name string, interval, limit uint64, filters []string) (*Rule, error) {
	r := &Rule{
		Interval: interval,
		Limit:    limit,
		Name:     name,
	}
	r.Init()
	if err := r.ParseFilters(filters); err != nil {
		return nil, err
	}
	return r, nil
}

func ParseJSON(filename string) ([]*Rule, error) {
	var rules []*Rule
	fileContent, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(fileContent, &rules)
	if err != nil {
		return nil, err
	}
	for _, r := range rules {
		if len(r.RawActions) == 0 {
			return nil, errors.New(fmt.Sprintf("Missing actions in rule: %v", r.Name))
		}
		r.Init()
		if err := r.ParseFilters(r.RawFilters); err != nil {
			return nil, err
		}
		if err := r.ParseAggregations(r.RawAggregations); err != nil {
			return nil, err
		}
		r.Actions = make([]action.Action, 0, len(r.RawActions))
		for _, actionJSON := range r.RawActions {
			a, err := action.Create(actionJSON)
			if err != nil {
				return nil, err
			}
			r.Actions = append(r.Actions, a)
		}
	}
	return rules, nil
}

func (r *Rule) Init() {
	r.matchedRequests = 0
	r.lastTick = uint64(time.Now().Unix())
}

func (r *Rule) ParseAggregations(aggregations []string) error {
	r.Aggregations = make([]*Aggregation, 0, len(aggregations))
	for _, t := range aggregations {
		s, err := selector.Parse(t)
		if err != nil {
			return errors.New(fmt.Sprintf("Cannot parse selector '%v': %v", t, err))
		}
		a := &Aggregation{
			Values:   make(map[string]uint64),
			Selector: s,
		}
		r.Aggregations = append(r.Aggregations, a)
	}
	return nil
}

func (r *Rule) ParseFilters(filters []string) error {
	r.Filters = make([]*selector.Selector, 0, len(filters))
	for _, t := range filters {
		s, err := selector.Parse(t)
		if err != nil {
			return errors.New(fmt.Sprintf("Cannot parse selector '%v': %v", t, err))
		}
		r.Filters = append(r.Filters, s)
	}
	return nil
}

func (r *Rule) Validate(req *http.Request, resp http.ResponseWriter) types.ResponseState {
	curTime := uint64(time.Now().Unix())
	if r.Limit != 0 && curTime-r.lastTick >= r.Interval {
		r.matchedRequests = 0
		r.lastTick = curTime
		for _, a := range r.Aggregations {
			a.Lock()
			a.Values = make(map[string]uint64)
			a.Unlock()
		}
	}
	for _, t := range r.Filters {
		if _, found := t.Match(req); !found {
			return types.UNTOUCHED
		}
	}
	matched := false
	state := types.UNTOUCHED
	if len(r.Aggregations) == 0 {
		atomic.AddUint64(&r.matchedRequests, 1)
		if r.matchedRequests > r.Limit {
			matched = true
		}
	} else {
		for _, a := range r.Aggregations {
			if a.Get(req) > r.Limit {
				matched = true
			}
		}
	}
	if matched {
		for _, a := range r.Actions {
			s, err := a.Act(req, resp)
			// TODO error handling
			if err != nil {
				fmt.Println("meh", err)
			}
			if s == types.SERVED {
				state = types.SERVED
			}
		}
	}
	return state
}

func (a *Aggregation) Get(req *http.Request) uint64 {
	if val, found := a.Selector.Match(req); found {
		a.Lock()
		a.Values[val] += 1
		v := a.Values[val]
		a.Unlock()
		return v
	}
	return 0
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

// go mod graph

package modcmd

import (
	"bufio"
	"os"
	"sort"

	"cmd/go/internal/base"
	"cmd/go/internal/modload"
	"cmd/go/internal/module"
	"cmd/go/internal/par"
)

var cmdGraph = &base.Command{
	UsageLine: "go mod graph",
	Short:     "print module requirement graph",
	Long: `
Graph prints the module requirement graph (with replacements applied)
in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix.
	`,
	Run: runGraph,
}

func runGraph(cmd *base.Command, args []string) {
	if len(args) > 0 {
		base.Fatalf("go mod graph: graph takes no arguments")
	}
	modload.LoadBuildList()

	reqs := modload.MinReqs()
	format := func(m module.Version) string {
		if m.Version == "" {
			return m.Path
		}
		return m.Path + "@" + m.Version
	}

	// Note: using par.Work only to manage work queue.
	// No parallelism here, so no locking.
	var out []string
	var deps int // index in out where deps start
	var work par.Work
	work.Add(modload.Target)
	work.Do(1, func(item interface{}) {
		m := item.(module.Version)
		list, _ := reqs.Required(m)
		for _, r := range list {
			work.Add(r)
			out = append(out, format(m)+" "+format(r)+"\n")
		}
		if m == modload.Target {
			deps = len(out)
		}
	})

	sort.Slice(out[deps:], func(i, j int) bool {
		return out[deps+i][0] < out[deps+j][0]
	})

	w := bufio.NewWriter(os.Stdout)
	for _, line := range out {
		w.WriteString(line)
	}
	w.Flush()
}
<commit_msg>cmd/go: add graphviz output to graph command<commit_after>// Copyright 2018 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.

// go mod graph

package modcmd

import (
	"bufio"
	"os"
	"sort"

	"cmd/go/internal/base"
	"cmd/go/internal/modload"
	"cmd/go/internal/module"
	"cmd/go/internal/par"
)

var cmdGraph = &base.Command{
	UsageLine: "go mod graph [-dot]",
	Short:     "print module requirement graph",
	Long: `
Graph prints the module requirement graph (with replacements applied)
in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix.

The -dot flag generates the output in graphviz format that can be used
with a tool like dot to visually render the dependency graph.
	`,
}

var (
	graphDot = cmdGraph.Flag.Bool("dot", false, "")
)

func init() {
	cmdGraph.Run = runGraph // break init cycle
}

func runGraph(cmd *base.Command, args []string) {
	if len(args) > 0 {
		base.Fatalf("go mod graph: graph takes no arguments")
	}
	modload.LoadBuildList()

	reqs := modload.MinReqs()
	format := func(m module.Version) string {
		if m.Version == "" {
			return m.Path
		}
		return m.Path + "@" + m.Version
	}

	// Note: using par.Work only to manage work queue.
	// No parallelism here, so no locking.
	var out []string
	var deps int // index in out where deps start
	var work par.Work
	work.Add(modload.Target)
	work.Do(1, func(item interface{}) {
		m := item.(module.Version)
		if *graphDot {
			if m.Version == "" {
				out = append(out, "\""+m.Path+"\" [label=<"+m.Path+">]\n")
			} else {
				out = append(out, "\""+m.Path+"\" [label=<"+m.Path+"
"+m.Version+">]\n")
			}
		}
		list, _ := reqs.Required(m)
		for _, r := range list {
			work.Add(r)
			if *graphDot {
				out = append(out, "\""+m.Path+"\" -> \""+r.Path+"\"\n")
			} else {
				out = append(out, format(m)+" "+format(r)+"\n")
			}
		}
		if m == modload.Target {
			deps = len(out)
		}
	})

	sort.Slice(out[deps:], func(i, j int) bool {
		return out[deps+i][0] < out[deps+j][0]
	})

	w := bufio.NewWriter(os.Stdout)
	if *graphDot {
		w.WriteString("digraph deps {\nrankdir=LR\n")
	}
	for _, line := range out {
		w.WriteString(line)
	}
	if *graphDot {
		w.WriteString("}\n")
	}
	w.Flush()
}
<|endoftext|>


<commit_before>package stackit

import (
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws"
	"time"
)

type StackitUpInput struct {
	StackName        *string
	RoleARN          *string
	StackPolicyBody  *string
	TemplateBody     *string
	PreviousTemplate *bool
	Parameters       []*cloudformation.Parameter
	Tags             []*cloudformation.Tag
	NotificationARNs []*string
	Capabilities     []*string
	PopulateMissing  bool
}

type StackUpOutput struct {
	Channel *chan TailStackEvent
	StackId string
	NoOp    bool
}

func populateMissing(input *StackitUpInput, stack *cloudformation.Stack) {
	paramExists := func(name string) bool {
		for _, param := range input.Parameters {
			if *param.ParameterKey == name {
				return true
			}
		}
		return false
	}

	for _, param := range stack.Parameters {
		if !paramExists(*param.ParameterKey) {
			input.Parameters = append(input.Parameters, &cloudformation.Parameter{
				ParameterKey:     param.ParameterKey,
				UsePreviousValue: aws.Bool(true),
			})
		}
	}

	if input.TemplateBody == nil || len(*input.TemplateBody) == 0 {
		input.PreviousTemplate = aws.Bool(true)
	}
}

func CleanStackExists(sess *session.Session, name string) (bool, *cloudformation.Stack) {
	cfn := cloudformation.New(sess)

	resp, err := cfn.DescribeStacks(&cloudformation.DescribeStacksInput{StackName: &name})
	stackExists := err == nil

	if resp != nil && len(resp.Stacks) > 0 {
		stack := resp.Stacks[0]
		if *stack.StackStatus == "CREATE_FAILED" || *stack.StackStatus == "ROLLBACK_COMPLETE" {
			cfn.DeleteStack(&cloudformation.DeleteStackInput{StackName: &name})
			stackExists = false
			time.Sleep(time.Duration(3) * time.Second) // wait for cloudformation to register stack deletion
		}
	}

	if stackExists {
		return true, resp.Stacks[0]
	} else {
		return false, nil
	}
}

func Up(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	stackExists, stack := CleanStackExists(sess, *input.StackName)

	if stackExists {
		if input.PopulateMissing { populateMissing(&input, stack) }
		return updateStack(sess, input)
	} else {
		return createStack(sess, input)
	}
}

func updateStack(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	cfn := cloudformation.New(sess)

	describeResp, err := cfn.DescribeStackEvents(&cloudformation.DescribeStackEventsInput{
		StackName: input.StackName,
	})

	if err != nil {
		return nil, err
	}
	_, err = cfn.UpdateStack(&cloudformation.UpdateStackInput{
		StackName:                   input.StackName,
		Capabilities:                input.Capabilities,
		RoleARN:                     input.RoleARN,
		StackPolicyDuringUpdateBody: input.StackPolicyBody,
		TemplateBody:                input.TemplateBody,
		UsePreviousTemplate:         input.PreviousTemplate,
		Parameters:                  input.Parameters,
		Tags:                        input.Tags,
		NotificationARNs:            input.NotificationARNs,
	})

	event := describeResp.StackEvents[0]
	eventIdToTail := event.EventId
	stackId := *event.StackId

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "ValidationError" && awsErr.Message() == "No updates are to be performed." {
				return &StackUpOutput{
					Channel: nil,
					StackId: stackId,
					NoOp:    true,
				}, nil
			}
		}
		return nil, err
	}

	channel := DoTailStack(sess, &stackId, eventIdToTail)

	return &StackUpOutput{
		Channel: &channel,
		StackId: stackId,
		NoOp:    false,
	}, nil
}

func createStack(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	cfn := cloudformation.New(sess)

	resp, err := cfn.CreateStack(&cloudformation.CreateStackInput{
		StackName:    input.StackName,
		Capabilities: input.Capabilities,
		RoleARN:      input.RoleARN,
		//StackPolicyBody: input.StackPolicyBody,
		TemplateBody:     input.TemplateBody,
		Parameters:       input.Parameters,
		Tags:             input.Tags,
		NotificationARNs: input.NotificationARNs,
	})

	if err != nil {
		return nil, err
	} else {
		eventId := ""
		channel := DoTailStack(sess, resp.StackId, aws.String(eventId))

		return &StackUpOutput{
			Channel: &channel,
			StackId: *resp.StackId,
			NoOp:    false,
		}, nil
	}
}
<commit_msg>Don't populate missing parameters that aren't relevant for the new template (closes #15)<commit_after>package stackit

import (
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws"
	"time"
	"github.com/pkg/errors"
)

type StackitUpInput struct {
	StackName        *string
	RoleARN          *string
	StackPolicyBody  *string
	TemplateBody     *string
	PreviousTemplate *bool
	Parameters       []*cloudformation.Parameter
	Tags             []*cloudformation.Tag
	NotificationARNs []*string
	Capabilities     []*string
	PopulateMissing  bool
}

type StackUpOutput struct {
	Channel *chan TailStackEvent
	StackId string
	NoOp    bool
}

func populateMissing(sess *session.Session, input *StackitUpInput, stack *cloudformation.Stack) error {
	maybeAddParam := func(name string) {
		for _, param := range input.Parameters {
			if *param.ParameterKey == name {
				return
			}
		}
		input.Parameters = append(input.Parameters, &cloudformation.Parameter{
			ParameterKey:     &name,
			UsePreviousValue: aws.Bool(true),
		})
	}

	if input.TemplateBody == nil || len(*input.TemplateBody) == 0 {
		input.PreviousTemplate = aws.Bool(true)

		for _, param := range stack.Parameters {
			maybeAddParam(*param.ParameterKey)
		}
	} else {
		api := cloudformation.New(sess)
		resp, err := api.ValidateTemplate(&cloudformation.ValidateTemplateInput{TemplateBody: input.TemplateBody})
		if err != nil {
			return err
		}

		for _, param := range resp.Parameters {
			maybeAddParam(*param.ParameterKey)
		}
	}

	return nil
}

func CleanStackExists(sess *session.Session, name string) (bool, *cloudformation.Stack) {
	cfn := cloudformation.New(sess)

	resp, err := cfn.DescribeStacks(&cloudformation.DescribeStacksInput{StackName: &name})
	stackExists := err == nil

	if resp != nil && len(resp.Stacks) > 0 {
		stack := resp.Stacks[0]
		if *stack.StackStatus == "CREATE_FAILED" || *stack.StackStatus == "ROLLBACK_COMPLETE" {
			cfn.DeleteStack(&cloudformation.DeleteStackInput{StackName: &name})
			stackExists = false
			time.Sleep(time.Duration(3) * time.Second) // wait for cloudformation to register stack deletion
		}
	}

	if stackExists {
		return true, resp.Stacks[0]
	} else {
		return false, nil
	}
}

func Up(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	stackExists, stack := CleanStackExists(sess, *input.StackName)

	if stackExists {
		if input.PopulateMissing {
			err := populateMissing(sess, &input, stack)
			if err != nil {
				return nil, errors.Wrap(err, "populating missing parameters")
			}
		}
		return updateStack(sess, input)
	} else {
		return createStack(sess, input)
	}
}

func updateStack(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	cfn := cloudformation.New(sess)

	describeResp, err := cfn.DescribeStackEvents(&cloudformation.DescribeStackEventsInput{
		StackName: input.StackName,
	})

	if err != nil {
		return nil, err
	}
	_, err = cfn.UpdateStack(&cloudformation.UpdateStackInput{
		StackName:                   input.StackName,
		Capabilities:                input.Capabilities,
		RoleARN:                     input.RoleARN,
		StackPolicyDuringUpdateBody: input.StackPolicyBody,
		TemplateBody:                input.TemplateBody,
		UsePreviousTemplate:         input.PreviousTemplate,
		Parameters:                  input.Parameters,
		Tags:                        input.Tags,
		NotificationARNs:            input.NotificationARNs,
	})

	event := describeResp.StackEvents[0]
	eventIdToTail := event.EventId
	stackId := *event.StackId

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "ValidationError" && awsErr.Message() == "No updates are to be performed." {
				return &StackUpOutput{
					Channel: nil,
					StackId: stackId,
					NoOp:    true,
				}, nil
			}
		}
		return nil, err
	}

	channel := DoTailStack(sess, &stackId, eventIdToTail)

	return &StackUpOutput{
		Channel: &channel,
		StackId: stackId,
		NoOp:    false,
	}, nil
}

func createStack(sess *session.Session, input StackitUpInput) (*StackUpOutput, error) {
	cfn := cloudformation.New(sess)

	resp, err := cfn.CreateStack(&cloudformation.CreateStackInput{
		StackName:    input.StackName,
		Capabilities: input.Capabilities,
		RoleARN:      input.RoleARN,
		//StackPolicyBody: input.StackPolicyBody,
		TemplateBody:     input.TemplateBody,
		Parameters:       input.Parameters,
		Tags:             input.Tags,
		NotificationARNs: input.NotificationARNs,
	})

	if err != nil {
		return nil, err
	} else {
		eventId := ""
		channel := DoTailStack(sess, resp.StackId, aws.String(eventId))

		return &StackUpOutput{
			Channel: &channel,
			StackId: *resp.StackId,
			NoOp:    false,
		}, nil
	}
}
<|endoftext|>


<commit_before>package main

import (
    "encoding/json"
    "github.com/garyburd/redigo/redis"
)

type User struct {
    Name     string `json:"name"`
    Password string `json:"password"`
    Method   string `json:"method"`
    Limit    int64  `json:"limit"`
}

type Storage struct {
    pool *redis.Pool
}

func NewStorage(server string) *Storage {
    pool := redis.NewPool(func() (conn redis.Conn, err error) {
        conn, err = redis.Dial("tcp", server)
        return
    }, 3)
    return &Storage{pool}
}

func (s *Storage) Get(key string) (user User, err error) {
    var data []byte
    var conn = s.pool.Get()
    defer conn.Close()
    data, err = redis.Bytes(conn.Do("GET", key))
    if err != nil {
        return
    }
    err = json.Unmarshal(data, &user)
    return
}

func (s *Storage) Set(key string, user User) (err error) {
    data, err := json.Marshal(user)
    if err != nil {
        return err
    }
    conn := s.pool.Get()
    defer conn.Close()
    _, err = conn.Do("SET", key, data)
    return
}

func (s *Storage) IncrSize(key string, incr int) (score int64, err error) {
    var conn = s.pool.Get()
    defer conn.Close()
    score, err = redis.Int64(conn.Do("INCRBY", key, incr))
    return
}

func (s *Storage) GetSize(key string) (score int64, err error) {
    var conn = s.pool.Get()
    defer conn.Close()
    score, err = redis.Int64(conn.Do("GET", key))
    return
}
<commit_msg>Add SS_PREFIX<commit_after>package main

import (
    "encoding/json"
    "github.com/garyburd/redigo/redis"
)

const SS_PREFIX = "ss:"

type User struct {
    Name     string `json:"name"`
    Password string `json:"password"`
    Method   string `json:"method"`
    Limit    int64  `json:"limit"`
}

type Storage struct {
    pool *redis.Pool
}

func NewStorage(server string) *Storage {
    pool := redis.NewPool(func() (conn redis.Conn, err error) {
        conn, err = redis.Dial("tcp", server)
        return
    }, 3)
    return &Storage{pool}
}

func (s *Storage) Get(key string) (user User, err error) {
    var data []byte
    var conn = s.pool.Get()
    defer conn.Close()
    data, err = redis.Bytes(conn.Do("GET", SS_PREFIX + key))
    if err != nil {
        return
    }
    err = json.Unmarshal(data, &user)
    return
}

func (s *Storage) Set(key string, user User) (err error) {
    data, err := json.Marshal(user)
    if err != nil {
        return err
    }
    conn := s.pool.Get()
    defer conn.Close()
    _, err = conn.Do("SET", SS_PREFIX + key, data)
    return
}

func (s *Storage) IncrSize(key string, incr int) (score int64, err error) {
    var conn = s.pool.Get()
    defer conn.Close()
    score, err = redis.Int64(conn.Do("INCRBY", SS_PREFIX + key, incr))
    return
}

func (s *Storage) GetSize(key string) (score int64, err error) {
    var conn = s.pool.Get()
    defer conn.Close()
    score, err = redis.Int64(conn.Do("GET", SS_PREFIX + key))
    return
}
<|endoftext|>


<commit_before>/*
Copyright 2018, Cossack Labs Limited

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 filesystem

import (
	"path/filepath"

	"github.com/cossacklabs/acra/keystore"
	"github.com/cossacklabs/themis/gothemis/keys"
)

// TranslatorFileSystemKeyStore stores AcraTranslator keys configuration
type TranslatorFileSystemKeyStore struct {
	*KeyStore
	directory string
	encryptor keystore.KeyEncryptor
}

// TranslatorFileSystemKeyStoreBuilder allows to build a custom key store.
type TranslatorFileSystemKeyStoreBuilder struct {
	keyStoreBuilder *KeyStoreBuilder
	directory       string
	encryptor       keystore.KeyEncryptor
}

// NewCustomTranslatorFileSystemKeyStore allows to customize a translator key store.
func NewCustomTranslatorFileSystemKeyStore() *TranslatorFileSystemKeyStoreBuilder {
	return &TranslatorFileSystemKeyStoreBuilder{
		keyStoreBuilder: NewCustomFilesystemKeyStore(),
	}
}

// KeyDirectory sets key directory.
func (b *TranslatorFileSystemKeyStoreBuilder) KeyDirectory(directory string) *TranslatorFileSystemKeyStoreBuilder {
	b.keyStoreBuilder.KeyDirectory(directory)
	b.directory = directory
	return b
}

// Encryptor sets key encryptor.
func (b *TranslatorFileSystemKeyStoreBuilder) Encryptor(encryptor keystore.KeyEncryptor) *TranslatorFileSystemKeyStoreBuilder {
	b.keyStoreBuilder.Encryptor(encryptor)
	b.encryptor = encryptor
	return b
}

// Build a key store.
func (b *TranslatorFileSystemKeyStoreBuilder) Build() (*TranslatorFileSystemKeyStore, error) {
	if b.directory == "" {
		return nil, errNoPrivateKeyDir
	}
	if b.encryptor == nil {
		return nil, errNoEncryptor
	}
	fsKeystore, err := b.keyStoreBuilder.Build()
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{
		KeyStore:  fsKeystore,
		directory: b.directory,
		encryptor: b.encryptor,
	}, nil
}

// NewTranslatorFileSystemKeyStoreFromServerStore create TranslatorKeyStore which inherit KeyStore
func NewTranslatorFileSystemKeyStoreFromServerStore(directory string, encryptor keystore.KeyEncryptor, store *KeyStore) (*TranslatorFileSystemKeyStore, error) {
	return &TranslatorFileSystemKeyStore{KeyStore: store, directory: directory, encryptor: encryptor}, nil
}

// NewTranslatorFileSystemKeyStore creates new TranslatorFileSystemKeyStore
func NewTranslatorFileSystemKeyStore(directory string, encryptor keystore.KeyEncryptor, cacheSize int) (*TranslatorFileSystemKeyStore, error) {
	fsKeystore, err := NewFileSystemKeyStoreWithCacheSize(directory, encryptor, cacheSize)
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{KeyStore: fsKeystore, directory: directory, encryptor: encryptor}, nil
}

// CheckIfPrivateKeyExists checks if Keystore has Translator transport private key for establishing Secure Session connection,
// returns true if key exists in fs.
func (store *TranslatorFileSystemKeyStore) CheckIfPrivateKeyExists(id []byte) (bool, error) {
	return store.fs.Exists(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
}

// GetPrivateKey reads and decrypts Translator transport private key for establishing Secure Session connection.
func (store *TranslatorFileSystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	keyData, err := store.fs.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return nil, err
	}

	var privateKey []byte
	if privateKey, err = store.encryptor.Decrypt(keyData, id); err != nil {
		return nil, err
	}
	return &keys.PrivateKey{Value: privateKey}, nil
}
<commit_msg>Add one more missing method to TranslatorKeyStore builder<commit_after>/*
Copyright 2018, Cossack Labs Limited

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 filesystem

import (
	"path/filepath"

	"github.com/cossacklabs/acra/keystore"
	"github.com/cossacklabs/themis/gothemis/keys"
)

// TranslatorFileSystemKeyStore stores AcraTranslator keys configuration
type TranslatorFileSystemKeyStore struct {
	*KeyStore
	directory string
	encryptor keystore.KeyEncryptor
}

// TranslatorFileSystemKeyStoreBuilder allows to build a custom key store.
type TranslatorFileSystemKeyStoreBuilder struct {
	keyStoreBuilder *KeyStoreBuilder
	directory       string
	encryptor       keystore.KeyEncryptor
}

// NewCustomTranslatorFileSystemKeyStore allows to customize a translator key store.
func NewCustomTranslatorFileSystemKeyStore() *TranslatorFileSystemKeyStoreBuilder {
	return &TranslatorFileSystemKeyStoreBuilder{
		keyStoreBuilder: NewCustomFilesystemKeyStore(),
	}
}

// KeyDirectory sets key directory.
func (b *TranslatorFileSystemKeyStoreBuilder) KeyDirectory(directory string) *TranslatorFileSystemKeyStoreBuilder {
	b.keyStoreBuilder.KeyDirectory(directory)
	b.directory = directory
	return b
}

// Encryptor sets key encryptor.
func (b *TranslatorFileSystemKeyStoreBuilder) Encryptor(encryptor keystore.KeyEncryptor) *TranslatorFileSystemKeyStoreBuilder {
	b.keyStoreBuilder.Encryptor(encryptor)
	b.encryptor = encryptor
	return b
}

// Storage sets custom storage.
func (b *TranslatorFileSystemKeyStoreBuilder) Storage(storage Storage) *TranslatorFileSystemKeyStoreBuilder {
	b.keyStoreBuilder.Storage(storage)
	return b
}

// Build a key store.
func (b *TranslatorFileSystemKeyStoreBuilder) Build() (*TranslatorFileSystemKeyStore, error) {
	if b.directory == "" {
		return nil, errNoPrivateKeyDir
	}
	if b.encryptor == nil {
		return nil, errNoEncryptor
	}
	fsKeystore, err := b.keyStoreBuilder.Build()
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{
		KeyStore:  fsKeystore,
		directory: b.directory,
		encryptor: b.encryptor,
	}, nil
}

// NewTranslatorFileSystemKeyStoreFromServerStore create TranslatorKeyStore which inherit KeyStore
func NewTranslatorFileSystemKeyStoreFromServerStore(directory string, encryptor keystore.KeyEncryptor, store *KeyStore) (*TranslatorFileSystemKeyStore, error) {
	return &TranslatorFileSystemKeyStore{KeyStore: store, directory: directory, encryptor: encryptor}, nil
}

// NewTranslatorFileSystemKeyStore creates new TranslatorFileSystemKeyStore
func NewTranslatorFileSystemKeyStore(directory string, encryptor keystore.KeyEncryptor, cacheSize int) (*TranslatorFileSystemKeyStore, error) {
	fsKeystore, err := NewFileSystemKeyStoreWithCacheSize(directory, encryptor, cacheSize)
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{KeyStore: fsKeystore, directory: directory, encryptor: encryptor}, nil
}

// CheckIfPrivateKeyExists checks if Keystore has Translator transport private key for establishing Secure Session connection,
// returns true if key exists in fs.
func (store *TranslatorFileSystemKeyStore) CheckIfPrivateKeyExists(id []byte) (bool, error) {
	return store.fs.Exists(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
}

// GetPrivateKey reads and decrypts Translator transport private key for establishing Secure Session connection.
func (store *TranslatorFileSystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	keyData, err := store.fs.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return nil, err
	}

	var privateKey []byte
	if privateKey, err = store.encryptor.Decrypt(keyData, id); err != nil {
		return nil, err
	}
	return &keys.PrivateKey{Value: privateKey}, nil
}
<|endoftext|>


<commit_before>package gohtml

import (
	"bytes"
	"strconv"
	"strings"
)

// Format parses the input HTML string, formats it and returns the result.
func Format(s string) string {
	return parse(s).html()
}

// Format parses the input HTML string, formats it and returns the result with line no.
func FormatWithLineNo(s string) string {
	lines := strings.Split(Format(s), "\n")
	maxLineNoStrLen := len(strconv.Itoa(len(lines)))
	bf := &bytes.Buffer{}
	for i, line := range lines {
		lineNoStr := strconv.Itoa(i + 1)
		if i > 0 {
			bf.WriteString("\n")
		}
		bf.WriteString(strings.Repeat(" ", maxLineNoStrLen-len(lineNoStr)) + lineNoStr + "  " + line)
	}
	return bf.String()
}
<commit_msg>Updated formatter.go.<commit_after>package gohtml

import (
	"bytes"
	"strconv"
	"strings"
)

// Format parses the input HTML string, formats it and returns the result.
func Format(s string) string {
	return parse(s).html()
}

// Format parses the input HTML string, formats it and returns the result with line no.
func FormatWithLineNo(s string) string {
	return AddLineNo(Format(s))
}

func AddLineNo(s string) string {
	lines := strings.Split(s, "\n")
	maxLineNoStrLen := len(strconv.Itoa(len(lines)))
	bf := &bytes.Buffer{}
	for i, line := range lines {
		lineNoStr := strconv.Itoa(i + 1)
		if i > 0 {
			bf.WriteString("\n")
		}
		bf.WriteString(strings.Repeat(" ", maxLineNoStrLen-len(lineNoStr)) + lineNoStr + "  " + line)
	}
	return bf.String()

}
<|endoftext|>


<commit_before>package iglo

import (
	"bitbucket.org/pkg/inflect"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize": inflect.Dasherize,
		"trim":      strings.Trim,
		"labelize":  labelize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Headers"}}

Headers

	{{range $index, $element := .}}

			{{$index}}
			{{.Value}}

	{{end}}

{{end}}

{{define "Responses"}}
	{{range .}}
		{{if .Body}}

{{.Body}}

		{{end}}
		{{if .Headers}}

				{{template "Headers" .Headers}}

		{{end}}
	{{end}}
{{end}}

{{define "Examples"}}
	{{range .}}
		{{template "Responses" .Responses}}
	{{end}}
{{end}}

{{define "Parameters"}}

Parameters

	{{range $index, $element := .}}

			{{$index}}
			{{.Type}}
			{{.Description}}

	{{end}}

{{end}}

{{define "Resources"}}
	{{range .Resources}}
		{{$UriTemplate := .UriTemplate}}
		{{$Parameters := .Parameters}}

{{.Name}}

{{trim .Description "\n"}}

		{{range .Actions}}

				{{.Method}}
				{{$UriTemplate}}

				{{.Description}}

				{{if .Examples}}{{template "Examples" .Examples}}{{end}}
				{{if $Parameters}}

{{template "Parameters" $Parameters}}

				{{end}}

		{{end}}
	{{end}}
{{end}}

{{define "ResourceGroups"}}
	{{range .}}

{{.Name}}

		{{template "Resources" .}}
	{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}

		{{.Name}}

			{{range .Resources}}

{{.Name}}

			{{end}}

	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">

					{{template "NavResourceGroups" .ResourceGroups}}

					{{template "ResourceGroups" .ResourceGroups}}

`
<commit_msg>much nicer now :)<commit_after>package iglo

import (
	"bitbucket.org/pkg/inflect"
	bf "github.com/russross/blackfriday"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func markdownize(str string) template.HTML {
	b := bf.MarkdownCommon([]byte(str))
	return template.HTML(string(b))
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize":   inflect.Dasherize,
		"trim":        strings.Trim,
		"labelize":    labelize,
		"markdownize": markdownize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Headers"}}

	{{range $index, $element := .}}

{{$index}}

{{.Value}}

	{{end}}

{{end}}

{{define "Responses"}}
	{{range .}}
		{{if .Body}}

				Response
				SHOW

{{.Body}}

		{{end}}
		{{if .Headers}}

Headers

				{{template "Headers" .Headers}}

		{{end}}
	{{end}}
{{end}}

{{define "Examples"}}
	{{range .}}
		{{template "Responses" .Responses}}
	{{end}}
{{end}}

{{define "Parameters"}}

			Name
			Required
			Type
			Description

	{{range $index, $element := .}}

			{{$index}}
			{{.Required}}
			{{.Type}}
			{{.Description}}

	{{end}}

{{end}}

{{define "Resources"}}
	{{range .Resources}}
		{{$UriTemplate := .UriTemplate}}
		{{$Parameters := .Parameters}}

{{.Name}}

{{trim .Description "\n"}}

		{{range .Actions}}

				{{.Method}}
				{{$UriTemplate}}

				{{.Description}}

				{{if .Examples}}{{template "Examples" .Examples}}{{end}}
				{{if $Parameters}}

Parameters

{{template "Parameters" $Parameters}}

				{{end}}

		{{end}}
	{{end}}
{{end}}

{{define "ResourceGroups"}}
	{{range .}}
		{{template "Resources" .}}
	{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}
		{{.Name}}
		{{range .Resources}}
			{{.Name}}
		{{end}}
	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
		<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>

							{{.Name}}

{{markdownize .Description}}

					{{template "NavResourceGroups" .ResourceGroups}}

					{{template "ResourceGroups" .ResourceGroups}}

`
<|endoftext|>


<commit_before>package calls

type RecentCalls struct {
	calls []int
}

func Constructor() *RecentCalls {
	return &RecentCalls{}
}

func (rc *RecentCalls) Ping(t int) int {
	return -1
}
<commit_msg>solve 933 use lower_bound<commit_after>package calls

import "github.com/catorpilor/leetcode/utils"

type RecentCalls struct {
	calls []int
}

func Constructor() *RecentCalls {
	return &RecentCalls{}
}

// Ping time complexity O(lgN), space complexity O(1)
func (rc *RecentCalls) Ping(t int) int {
	rc.calls = append(rc.calls, t)
	l := utils.LowerBound(rc.calls, t-3000)
	return len(rc.calls) - l
}
<|endoftext|>