<commit_before>package log

import (
	"os"

	"log"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type Meta struct {
	Key   string
	Value interface{}
}

func F(key string, value interface{}) *Meta {
	return &Meta{Key: key, Value: value}
}

func E(err error) *Meta {
	return F("error", err)
}

type MetaFields []*Meta

func (m *MetaFields) flat() []interface{} {
	result := make([]interface{}, 0)
	for _, item := range *m {
		result = append(result, item.Key, item.Value)
	}
	return result
}

type Logger interface {
	Debug(format string, args ...interface{})
	DebugWith(meta MetaFields, format string, args ...interface{})
	Info(format string, args ...interface{})
	InfoWith(meta MetaFields, format string, args ...interface{})
	Warning(format string, args ...interface{})
	WarningWith(meta MetaFields, format string, args ...interface{})
	Error(format string, args ...interface{})
	ErrorWith(meta MetaFields, format string, args ...interface{})

	Get(name string) Logger
}

type logger struct {
	*zap.SugaredLogger
}

func (l *logger) Debug(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Debug(format)
	} else {
		l.SugaredLogger.Debugf(format, args...)
	}
}

func (l *logger) DebugWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Debug(format)
	} else {
		s.Debugf(format, args)
	}
}

func (l *logger) Info(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Info(format)
	} else {
		l.SugaredLogger.Infof(format, args...)
	}
}

func (l *logger) InfoWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Info(format)
	} else {
		s.Infof(format, args)
	}
}

func (l *logger) Warning(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Warn(format)
	} else {
		l.SugaredLogger.Warnf(format, args...)
	}
}

func (l *logger) WarningWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Warn(format)
	} else {
		s.Warnf(format, args)
	}
}

func (l *logger) Error(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Error(format)
	} else {
		l.SugaredLogger.Errorf(format, args...)
	}
}

func (l *logger) ErrorWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Error(format)
	} else {
		s.Errorf(format, args)
	}
}

func (l *logger) Get(name string) Logger {
	return &logger{SugaredLogger: l.Named(name)}
}

func Build() Logger {
	newLogger := &logger{}

	level := zap.InfoLevel
	if len(os.Getenv("RIVI_DEBUG")) > 0 {
		level = zap.DebugLevel
	}

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "name",
		CallerKey:      "caller",
		MessageKey:     "message",
		StacktraceKey:  "stack",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   func(zapcore.EntryCaller, zapcore.PrimitiveArrayEncoder) {},
	}

	config := zap.Config{
		Level:             zap.NewAtomicLevelAt(level),
		Development:       false,
		Encoding:          "console",
		EncoderConfig:     encoderConfig,
		OutputPaths:       []string{"stdout"},
		ErrorOutputPaths:  []string{"stdout"},
		DisableStacktrace: true,
	}

	zapLogger, err := config.Build()
	if err != nil {
		log.Printf("Unable to create logger. Using NoOpLogger. %s", err)
		return &NoOpLogger{}
	}

	newLogger.SugaredLogger = zapLogger.Sugar().Named("rivi")

	return newLogger
}
<commit_msg>pass args as varargs<commit_after>package log

import (
	"os"

	"log"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type Meta struct {
	Key   string
	Value interface{}
}

func F(key string, value interface{}) *Meta {
	return &Meta{Key: key, Value: value}
}

func E(err error) *Meta {
	return F("error", err)
}

type MetaFields []*Meta

func (m *MetaFields) flat() []interface{} {
	result := make([]interface{}, 0)
	for _, item := range *m {
		result = append(result, item.Key, item.Value)
	}
	return result
}

type Logger interface {
	Debug(format string, args ...interface{})
	DebugWith(meta MetaFields, format string, args ...interface{})
	Info(format string, args ...interface{})
	InfoWith(meta MetaFields, format string, args ...interface{})
	Warning(format string, args ...interface{})
	WarningWith(meta MetaFields, format string, args ...interface{})
	Error(format string, args ...interface{})
	ErrorWith(meta MetaFields, format string, args ...interface{})

	Get(name string) Logger
}

type logger struct {
	*zap.SugaredLogger
}

func (l *logger) Debug(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Debug(format)
	} else {
		l.SugaredLogger.Debugf(format, args...)
	}
}

func (l *logger) DebugWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Debug(format)
	} else {
		s.Debugf(format, args...)
	}
}

func (l *logger) Info(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Info(format)
	} else {
		l.SugaredLogger.Infof(format, args...)
	}
}

func (l *logger) InfoWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Info(format)
	} else {
		s.Infof(format, args...)
	}
}

func (l *logger) Warning(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Warn(format)
	} else {
		l.SugaredLogger.Warnf(format, args...)
	}
}

func (l *logger) WarningWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Warn(format)
	} else {
		s.Warnf(format, args)
	}
}

func (l *logger) Error(format string, args ...interface{}) {
	if len(args) == 0 {
		l.SugaredLogger.Error(format)
	} else {
		l.SugaredLogger.Errorf(format, args...)
	}
}

func (l *logger) ErrorWith(meta MetaFields, format string, args ...interface{}) {
	s := l.SugaredLogger.With(meta.flat()...)
	if len(args) == 0 {
		s.Error(format)
	} else {
		s.Errorf(format, args...)
	}
}

func (l *logger) Get(name string) Logger {
	return &logger{SugaredLogger: l.Named(name)}
}

func Build() Logger {
	newLogger := &logger{}

	level := zap.InfoLevel
	if len(os.Getenv("RIVI_DEBUG")) > 0 {
		level = zap.DebugLevel
	}

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "name",
		CallerKey:      "caller",
		MessageKey:     "message",
		StacktraceKey:  "stack",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   func(zapcore.EntryCaller, zapcore.PrimitiveArrayEncoder) {},
	}

	config := zap.Config{
		Level:             zap.NewAtomicLevelAt(level),
		Development:       false,
		Encoding:          "console",
		EncoderConfig:     encoderConfig,
		OutputPaths:       []string{"stdout"},
		ErrorOutputPaths:  []string{"stdout"},
		DisableStacktrace: true,
	}

	zapLogger, err := config.Build()
	if err != nil {
		log.Printf("Unable to create logger. Using NoOpLogger. %s", err)
		return &NoOpLogger{}
	}

	newLogger.SugaredLogger = zapLogger.Sugar().Named("rivi")

	return newLogger
}
<|endoftext|>


<commit_before>package hstspreload

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"net"
	"net/http"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/publicsuffix"
)

const (
	// dialTimeout specifies the amount of time that TCP or TLS connections
	// can take to complete.
	dialTimeout = 10 * time.Second

	// The maximum number of redirects when you visit the root path of the
	// domain over HTTP or HTTPS.
	maxRedirects = 3
	httpsScheme  = "https"
)

// dialer is a global net.Dialer that's used whenever making TLS connections in
// order to enforce dialTimeout.
var dialer = net.Dialer{
	Timeout: dialTimeout,
}

var clientWithTimeout = http.Client{
	Timeout: dialTimeout,
}

// PreloadableDomain checks whether the domain passes HSTS preload
// requirements for Chromium. This includes:
//
// - Serving a single HSTS header that passes header requirements.
//
// - Using TLS settings that will not cause new problems for
// Chromium/Chrome users. (Example of a new problem: a missing intermediate certificate
// will turn an error page from overrideable to non-overridable on
// some mobile devices.)
//
// Iff a single HSTS header was received, `header` contains its value, else
// `header` is `nil`.
// To interpret `issues`, see the list of conventions in the
// documentation for Issues.
func PreloadableDomain(domain string) (header *string, issues Issues) {
	// Check domain format issues first, since we can report something
	// useful even if the other checks fail.
	issues = combineIssues(issues, checkDomainFormat(domain))
	if len(issues.Errors) > 0 {
		return header, issues
	}

	// We don't currently allow automatic submissions of subdomains.
	levelIssues := preloadableDomainLevel(domain)
	issues = combineIssues(issues, levelIssues)

	// Start with an initial probe, and don't do the follow-up checks if
	// we can't connect.
	resp, respIssues := getResponse(domain)
	issues = combineIssues(issues, respIssues)
	if len(respIssues.Errors) == 0 {
		issues = combineIssues(issues, checkSHA1(certChain(*resp.TLS)))

		preloadableResponse := make(chan Issues)
		httpRedirects := make(chan Issues)
		httpFirstRedirectsHSTS := make(chan Issues)
		httpsRedirects := make(chan Issues)
		www := make(chan Issues)

		// PreloadableResponse
		go func() {
			var preloadableIssues Issues
			header, preloadableIssues = PreloadableResponse(resp)
			preloadableResponse <- preloadableIssues
		}()

		// checkHTTPRedirects
		go func() {
			mainIssues, firstRedirectHSTSIssues := preloadableHTTPRedirects(domain)
			httpRedirects <- mainIssues
			httpFirstRedirectsHSTS <- firstRedirectHSTSIssues
		}()

		// checkHTTPSRedirects
		go func() {
			httpsRedirects <- preloadableHTTPSRedirects(domain)
		}()

		// checkWWW
		go func() {
			// Skip the WWW check if the domain is not eTLD+1.
			if len(levelIssues.Errors) == 0 {
				www <- checkWWW(domain)
			}
			www <- Issues{}
		}()

		// Combine the issues in deterministic order.
		preloadableResponseIssues := <-preloadableResponse
		issues = combineIssues(issues, preloadableResponseIssues)
		issues = combineIssues(issues, <-httpRedirects)
		// If there are issues with the HSTS header in the main
		// PreloadableResponse() check, it is redundant to report
		// them in the response after redirecting from HTTP.
		if len(preloadableResponseIssues.Errors) == 0 {
			issues = combineIssues(issues, <-httpFirstRedirectsHSTS)
		}
		issues = combineIssues(issues, <-httpsRedirects)
		issues = combineIssues(issues, <-www)
	}

	return header, issues
}

// PreloadableDomain checks whether the domain passes HSTS preload
// requirements for Chromium. This includes:
//
// - Serving a single valid HSTS header.
//
// - The header must not contain the `preload` directive..
//
// Iff a single HSTS header was received, `header` contains its value, else
// `header` is `nil`.
// To interpret `issues`, see the list of conventions in the
// documentation for Issues.
func RemovableDomain(domain string) (header *string, issues Issues) {
	resp, respIssues := getResponse(domain)
	issues = combineIssues(issues, respIssues)
	if len(respIssues.Errors) == 0 {
		var removableIssues Issues
		header, removableIssues = RemovableResponse(resp)
		issues = combineIssues(issues, removableIssues)
	}

	return header, issues
}

func getResponse(domain string) (resp *http.Response, issues Issues) {
	redirectPrevented := errors.New("REDIRECT_PREVENTED")

	client := http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return redirectPrevented
		},
		Timeout: dialTimeout,
	}

	resp, err := client.Get("https://" + domain)
	if err != nil {
		if urlError, ok := err.(*url.Error); !ok || urlError.Err != redirectPrevented {
			return resp, issues.addErrorf(
				IssueCode("domain.tls.cannot_connect"),
				"Cannot connect using TLS",
				"We cannot connect to https://%s using TLS (%q). This "+
					"might be caused by an incomplete certificate chain, which causes "+
					"issues on mobile devices. Check out your site at "+
					"https://www.ssllabs.com/ssltest/",
				domain,
				err,
			)
		}
	}

	return resp, issues
}

func checkDomainFormat(domain string) (issues Issues) {
	if strings.HasPrefix(domain, ".") {
		return issues.addErrorf(
			IssueCode("domain.format.begins_with_dot"),
			"Invalid domain name",
			"Please provide a domain that does not begin with `.`")
	}
	if strings.HasSuffix(domain, ".") {
		return issues.addErrorf(
			IssueCode("domain.format.ends_with_dot"),
			"Invalid domain name",
			"Please provide a domain that does not begin with `.`")
	}
	if strings.Index(domain, "..") != -1 {
		return issues.addErrorf(
			IssueCode("domain.format.contains_double_dot"),
			"Invalid domain name",
			"Please provide a domain that does not contain `..`")
	}
	if strings.Count(domain, ".") < 1 {
		return issues.addErrorf(
			IssueCode("domain.format.only_one_label"),
			"Invalid domain name",
			"Please provide a domain with least two labels "+
				"(e.g. `example.com` rather than `example` or `com`).")
	}

	domain = strings.ToLower(domain)
	for _, r := range domain {
		if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '.' {
			continue
		}

		return issues.addErrorf("domain.format.invalid_characters", "Invalid domain name", "Please provide a domain using valid characters (letters, numbers, dashes, dots).")
	}

	return issues
}

func preloadableDomainLevel(domain string) (issues Issues) {
	canon, err := publicsuffix.EffectiveTLDPlusOne(domain)
	if err != nil {
		return issues.addErrorf("internal.domain.name.cannot_compute_etld1", "Internal Error", "Could not compute eTLD+1.")
	}
	if canon != domain {
		return issues.addErrorf(
			IssueCode("domain.is_subdomain"),
			"Subdomain",
			"`%s` is a subdomain. Please preload `%s` instead. "+
				"(Due to the size of the preload list and the behaviour of "+
				"cookies across subdomains, we only accept automated preload list "+
				"submissions of whole registered domains.)",
			domain,
			canon,
		)
	}

	return issues
}

func checkSHA1(chain []*x509.Certificate) (issues Issues) {
	if firstSHA1, found := findPropertyInChain(isSHA1, chain); found {
		issues = issues.addErrorf(
			IssueCode("domain.tls.sha1"),
			"SHA-1 Certificate",
			"One or more of the certificates in your certificate chain "+
				"is signed using SHA-1. This needs to be replaced. "+
				"See https://security.googleblog.com/2015/12/an-update-on-sha-1-certificates-in.html. "+
				"(The first SHA-1 certificate found has a common-name of %q.)",
			firstSHA1.Subject.CommonName,
		)
	}

	return issues
}

func checkWWW(host string) (issues Issues) {
	hasWWW := false
	if conn, err := net.DialTimeout("tcp", "www."+host+":443", dialTimeout); err == nil {
		hasWWW = true
		conn.Close()
	}

	if hasWWW {
		wwwConn, err := tls.DialWithDialer(&dialer, "tcp", "www."+host+":443", nil)
		if err != nil {
			return issues.addErrorf(
				IssueCode("domain.www.no_tls"),
				"www subdomain does not support HTTPS",
				"Domain error: The www subdomain exists, but we couldn't connect to it using HTTPS (%q). "+
					"Since many people type this by habit, HSTS preloading would likely "+
					"cause issues for your site.",
				err,
			)
		}
		wwwConn.Close()
	}

	return issues
}

func certChain(connState tls.ConnectionState) []*x509.Certificate {
	chain := connState.VerifiedChains[0]
	return chain[:len(chain)-1]
}

func findPropertyInChain(pred func(*x509.Certificate) bool, chain []*x509.Certificate) (*x509.Certificate, bool) {
	for _, cert := range chain {
		if pred(cert) {
			return cert, true
		}
	}

	return nil, false
}

func isSHA1(cert *x509.Certificate) bool {
	switch cert.SignatureAlgorithm {
	case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
		return true
	default:
		return false
	}
}
<commit_msg>Use an explicit if-else to avoid leaking a goroutine.<commit_after>package hstspreload

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"net"
	"net/http"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/publicsuffix"
)

const (
	// dialTimeout specifies the amount of time that TCP or TLS connections
	// can take to complete.
	dialTimeout = 10 * time.Second

	// The maximum number of redirects when you visit the root path of the
	// domain over HTTP or HTTPS.
	maxRedirects = 3
	httpsScheme  = "https"
)

// dialer is a global net.Dialer that's used whenever making TLS connections in
// order to enforce dialTimeout.
var dialer = net.Dialer{
	Timeout: dialTimeout,
}

var clientWithTimeout = http.Client{
	Timeout: dialTimeout,
}

// PreloadableDomain checks whether the domain passes HSTS preload
// requirements for Chromium. This includes:
//
// - Serving a single HSTS header that passes header requirements.
//
// - Using TLS settings that will not cause new problems for
// Chromium/Chrome users. (Example of a new problem: a missing intermediate certificate
// will turn an error page from overrideable to non-overridable on
// some mobile devices.)
//
// Iff a single HSTS header was received, `header` contains its value, else
// `header` is `nil`.
// To interpret `issues`, see the list of conventions in the
// documentation for Issues.
func PreloadableDomain(domain string) (header *string, issues Issues) {
	// Check domain format issues first, since we can report something
	// useful even if the other checks fail.
	issues = combineIssues(issues, checkDomainFormat(domain))
	if len(issues.Errors) > 0 {
		return header, issues
	}

	// We don't currently allow automatic submissions of subdomains.
	levelIssues := preloadableDomainLevel(domain)
	issues = combineIssues(issues, levelIssues)

	// Start with an initial probe, and don't do the follow-up checks if
	// we can't connect.
	resp, respIssues := getResponse(domain)
	issues = combineIssues(issues, respIssues)
	if len(respIssues.Errors) == 0 {
		issues = combineIssues(issues, checkSHA1(certChain(*resp.TLS)))

		preloadableResponse := make(chan Issues)
		httpRedirects := make(chan Issues)
		httpFirstRedirectsHSTS := make(chan Issues)
		httpsRedirects := make(chan Issues)
		www := make(chan Issues)

		// PreloadableResponse
		go func() {
			var preloadableIssues Issues
			header, preloadableIssues = PreloadableResponse(resp)
			preloadableResponse <- preloadableIssues
		}()

		// checkHTTPRedirects
		go func() {
			mainIssues, firstRedirectHSTSIssues := preloadableHTTPRedirects(domain)
			httpRedirects <- mainIssues
			httpFirstRedirectsHSTS <- firstRedirectHSTSIssues
		}()

		// checkHTTPSRedirects
		go func() {
			httpsRedirects <- preloadableHTTPSRedirects(domain)
		}()

		// checkWWW
		go func() {
			// Skip the WWW check if the domain is not eTLD+1.
			if len(levelIssues.Errors) == 0 {
				www <- checkWWW(domain)
			} else {
				www <- Issues{}
			}
		}()

		// Combine the issues in deterministic order.
		preloadableResponseIssues := <-preloadableResponse
		issues = combineIssues(issues, preloadableResponseIssues)
		issues = combineIssues(issues, <-httpRedirects)
		// If there are issues with the HSTS header in the main
		// PreloadableResponse() check, it is redundant to report
		// them in the response after redirecting from HTTP.
		if len(preloadableResponseIssues.Errors) == 0 {
			issues = combineIssues(issues, <-httpFirstRedirectsHSTS)
		}
		issues = combineIssues(issues, <-httpsRedirects)
		issues = combineIssues(issues, <-www)
	}

	return header, issues
}

// PreloadableDomain checks whether the domain passes HSTS preload
// requirements for Chromium. This includes:
//
// - Serving a single valid HSTS header.
//
// - The header must not contain the `preload` directive..
//
// Iff a single HSTS header was received, `header` contains its value, else
// `header` is `nil`.
// To interpret `issues`, see the list of conventions in the
// documentation for Issues.
func RemovableDomain(domain string) (header *string, issues Issues) {
	resp, respIssues := getResponse(domain)
	issues = combineIssues(issues, respIssues)
	if len(respIssues.Errors) == 0 {
		var removableIssues Issues
		header, removableIssues = RemovableResponse(resp)
		issues = combineIssues(issues, removableIssues)
	}

	return header, issues
}

func getResponse(domain string) (resp *http.Response, issues Issues) {
	redirectPrevented := errors.New("REDIRECT_PREVENTED")

	client := http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return redirectPrevented
		},
		Timeout: dialTimeout,
	}

	resp, err := client.Get("https://" + domain)
	if err != nil {
		if urlError, ok := err.(*url.Error); !ok || urlError.Err != redirectPrevented {
			return resp, issues.addErrorf(
				IssueCode("domain.tls.cannot_connect"),
				"Cannot connect using TLS",
				"We cannot connect to https://%s using TLS (%q). This "+
					"might be caused by an incomplete certificate chain, which causes "+
					"issues on mobile devices. Check out your site at "+
					"https://www.ssllabs.com/ssltest/",
				domain,
				err,
			)
		}
	}

	return resp, issues
}

func checkDomainFormat(domain string) (issues Issues) {
	if strings.HasPrefix(domain, ".") {
		return issues.addErrorf(
			IssueCode("domain.format.begins_with_dot"),
			"Invalid domain name",
			"Please provide a domain that does not begin with `.`")
	}
	if strings.HasSuffix(domain, ".") {
		return issues.addErrorf(
			IssueCode("domain.format.ends_with_dot"),
			"Invalid domain name",
			"Please provide a domain that does not begin with `.`")
	}
	if strings.Index(domain, "..") != -1 {
		return issues.addErrorf(
			IssueCode("domain.format.contains_double_dot"),
			"Invalid domain name",
			"Please provide a domain that does not contain `..`")
	}
	if strings.Count(domain, ".") < 1 {
		return issues.addErrorf(
			IssueCode("domain.format.only_one_label"),
			"Invalid domain name",
			"Please provide a domain with least two labels "+
				"(e.g. `example.com` rather than `example` or `com`).")
	}

	domain = strings.ToLower(domain)
	for _, r := range domain {
		if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '.' {
			continue
		}

		return issues.addErrorf("domain.format.invalid_characters", "Invalid domain name", "Please provide a domain using valid characters (letters, numbers, dashes, dots).")
	}

	return issues
}

func preloadableDomainLevel(domain string) (issues Issues) {
	canon, err := publicsuffix.EffectiveTLDPlusOne(domain)
	if err != nil {
		return issues.addErrorf("internal.domain.name.cannot_compute_etld1", "Internal Error", "Could not compute eTLD+1.")
	}
	if canon != domain {
		return issues.addErrorf(
			IssueCode("domain.is_subdomain"),
			"Subdomain",
			"`%s` is a subdomain. Please preload `%s` instead. "+
				"(Due to the size of the preload list and the behaviour of "+
				"cookies across subdomains, we only accept automated preload list "+
				"submissions of whole registered domains.)",
			domain,
			canon,
		)
	}

	return issues
}

func checkSHA1(chain []*x509.Certificate) (issues Issues) {
	if firstSHA1, found := findPropertyInChain(isSHA1, chain); found {
		issues = issues.addErrorf(
			IssueCode("domain.tls.sha1"),
			"SHA-1 Certificate",
			"One or more of the certificates in your certificate chain "+
				"is signed using SHA-1. This needs to be replaced. "+
				"See https://security.googleblog.com/2015/12/an-update-on-sha-1-certificates-in.html. "+
				"(The first SHA-1 certificate found has a common-name of %q.)",
			firstSHA1.Subject.CommonName,
		)
	}

	return issues
}

func checkWWW(host string) (issues Issues) {
	hasWWW := false
	if conn, err := net.DialTimeout("tcp", "www."+host+":443", dialTimeout); err == nil {
		hasWWW = true
		conn.Close()
	}

	if hasWWW {
		wwwConn, err := tls.DialWithDialer(&dialer, "tcp", "www."+host+":443", nil)
		if err != nil {
			return issues.addErrorf(
				IssueCode("domain.www.no_tls"),
				"www subdomain does not support HTTPS",
				"Domain error: The www subdomain exists, but we couldn't connect to it using HTTPS (%q). "+
					"Since many people type this by habit, HSTS preloading would likely "+
					"cause issues for your site.",
				err,
			)
		}
		wwwConn.Close()
	}

	return issues
}

func certChain(connState tls.ConnectionState) []*x509.Certificate {
	chain := connState.VerifiedChains[0]
	return chain[:len(chain)-1]
}

func findPropertyInChain(pred func(*x509.Certificate) bool, chain []*x509.Certificate) (*x509.Certificate, bool) {
	for _, cert := range chain {
		if pred(cert) {
			return cert, true
		}
	}

	return nil, false
}

func isSHA1(cert *x509.Certificate) bool {
	switch cert.SignatureAlgorithm {
	case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package service

import (
	"reflect"

	"github.com/hyperledger/fabric/common/channelconfig"

	"github.com/hyperledger/fabric/protos/peer"
)

// Config enumerates the configuration methods required by gossip
type Config interface {
	// ChainID returns the chainID for this channel
	ChainID() string

	// Organizations returns a map of org ID to ApplicationOrgConfig
	Organizations() map[string]channelconfig.ApplicationOrg

	// Sequence should return the sequence number of the current configuration
	Sequence() uint64

	// OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
	OrdererAddresses() []string
}

// ConfigProcessor receives config updates
type ConfigProcessor interface {
	// ProcessConfig should be invoked whenever a channel's configuration is initialized or updated
	ProcessConfigUpdate(config Config)
}

type configStore struct {
	anchorPeers []*peer.AnchorPeer
	orgMap      map[string]channelconfig.ApplicationOrg
}

type configEventReceiver interface {
	updateAnchors(config Config)
	updateEndpoints(chainID string, endpoints []string)
}

type configEventer struct {
	lastConfig *configStore
	receiver   configEventReceiver
}

func newConfigEventer(receiver configEventReceiver) *configEventer {
	return &configEventer{
		receiver: receiver,
	}
}

// ProcessConfigUpdate should be invoked whenever a channel's configuration is intialized or updated
// it invokes the associated method in configEventReceiver when configuration is updated
// but only if the configuration value actually changed
// Note, that a changing sequence number is ignored as changing configuration
func (ce *configEventer) ProcessConfigUpdate(config Config) {
	logger.Debugf("Processing new config for channel %s", config.ChainID())
	orgMap := cloneOrgConfig(config.Organizations())
	if ce.lastConfig != nil && reflect.DeepEqual(ce.lastConfig.orgMap, orgMap) {
		logger.Debugf("Ignoring new config for channel %s because it contained no anchor peer updates", config.ChainID())
	} else {

		var newAnchorPeers []*peer.AnchorPeer
		for _, group := range config.Organizations() {
			newAnchorPeers = append(newAnchorPeers, group.AnchorPeers()...)
		}

		newConfig := &configStore{
			orgMap:      orgMap,
			anchorPeers: newAnchorPeers,
		}
		ce.lastConfig = newConfig

		logger.Debugf("Calling out because config was updated for channel %s", config.ChainID())
		ce.receiver.updateAnchors(config)
	}
	ce.receiver.updateEndpoints(config.ChainID(), config.OrdererAddresses())
}

func cloneOrgConfig(src map[string]channelconfig.ApplicationOrg) map[string]channelconfig.ApplicationOrg {
	clone := make(map[string]channelconfig.ApplicationOrg)
	for k, v := range src {
		clone[k] = &appGrp{
			name:        v.Name(),
			mspID:       v.MSPID(),
			anchorPeers: v.AnchorPeers(),
		}
	}
	return clone
}

type appGrp struct {
	name        string
	mspID       string
	anchorPeers []*peer.AnchorPeer
}

func (ag *appGrp) Name() string {
	return ag.name
}

func (ag *appGrp) MSPID() string {
	return ag.mspID
}

func (ag *appGrp) AnchorPeers() []*peer.AnchorPeer {
	return ag.anchorPeers
}
<commit_msg>[FAB-7453] Fix spell error in comment<commit_after>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package service

import (
	"reflect"

	"github.com/hyperledger/fabric/common/channelconfig"

	"github.com/hyperledger/fabric/protos/peer"
)

// Config enumerates the configuration methods required by gossip
type Config interface {
	// ChainID returns the chainID for this channel
	ChainID() string

	// Organizations returns a map of org ID to ApplicationOrgConfig
	Organizations() map[string]channelconfig.ApplicationOrg

	// Sequence should return the sequence number of the current configuration
	Sequence() uint64

	// OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
	OrdererAddresses() []string
}

// ConfigProcessor receives config updates
type ConfigProcessor interface {
	// ProcessConfig should be invoked whenever a channel's configuration is initialized or updated
	ProcessConfigUpdate(config Config)
}

type configStore struct {
	anchorPeers []*peer.AnchorPeer
	orgMap      map[string]channelconfig.ApplicationOrg
}

type configEventReceiver interface {
	updateAnchors(config Config)
	updateEndpoints(chainID string, endpoints []string)
}

type configEventer struct {
	lastConfig *configStore
	receiver   configEventReceiver
}

func newConfigEventer(receiver configEventReceiver) *configEventer {
	return &configEventer{
		receiver: receiver,
	}
}

// ProcessConfigUpdate should be invoked whenever a channel's configuration is initialized or updated
// it invokes the associated method in configEventReceiver when configuration is updated
// but only if the configuration value actually changed
// Note, that a changing sequence number is ignored as changing configuration
func (ce *configEventer) ProcessConfigUpdate(config Config) {
	logger.Debugf("Processing new config for channel %s", config.ChainID())
	orgMap := cloneOrgConfig(config.Organizations())
	if ce.lastConfig != nil && reflect.DeepEqual(ce.lastConfig.orgMap, orgMap) {
		logger.Debugf("Ignoring new config for channel %s because it contained no anchor peer updates", config.ChainID())
	} else {

		var newAnchorPeers []*peer.AnchorPeer
		for _, group := range config.Organizations() {
			newAnchorPeers = append(newAnchorPeers, group.AnchorPeers()...)
		}

		newConfig := &configStore{
			orgMap:      orgMap,
			anchorPeers: newAnchorPeers,
		}
		ce.lastConfig = newConfig

		logger.Debugf("Calling out because config was updated for channel %s", config.ChainID())
		ce.receiver.updateAnchors(config)
	}
	ce.receiver.updateEndpoints(config.ChainID(), config.OrdererAddresses())
}

func cloneOrgConfig(src map[string]channelconfig.ApplicationOrg) map[string]channelconfig.ApplicationOrg {
	clone := make(map[string]channelconfig.ApplicationOrg)
	for k, v := range src {
		clone[k] = &appGrp{
			name:        v.Name(),
			mspID:       v.MSPID(),
			anchorPeers: v.AnchorPeers(),
		}
	}
	return clone
}

type appGrp struct {
	name        string
	mspID       string
	anchorPeers []*peer.AnchorPeer
}

func (ag *appGrp) Name() string {
	return ag.name
}

func (ag *appGrp) MSPID() string {
	return ag.mspID
}

func (ag *appGrp) AnchorPeers() []*peer.AnchorPeer {
	return ag.anchorPeers
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"regexp"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/devices"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go.wemo"
	"golang.org/x/net/context"
	"strings"
)

const (
	switchDesignator  = "controllee"
	insightDesignator = "insight"
	motionDesignator  = "sensor"
)

var info = ninja.LoadModuleInfo("./package.json")
var log = logger.GetLogger(info.ID)

type WemoDeviceContext struct {
	devices.BaseDevice
	Info   *wemo.DeviceInfo
	Device *wemo.Device
}

type WemoDriver struct {
	conn      *ninja.Connection
	sendEvent func(event string, payload interface{}) error
}

func NewWemoDriver() (*WemoDriver, error) {
	conn, err := ninja.Connect(info.ID)
	if err != nil {
		log.HandleError(err, "Could not connect to MQTT")
		return nil, err
	}

	driver := &WemoDriver{
		conn: conn,
	}

	err = conn.ExportDriver(driver)
	if err != nil {
		log.Fatalf("Failed to export Wemo driver: %s", err)
	}

	return driver, nil
}

func (d *WemoDriver) Start(x interface{}) error {
	log.Infof("Start method on Wemo driver called")

	return d.startDiscovery()
}

func (d *WemoDriver) startDiscovery() error {

	ipAddr, err := ninja.GetNetAddress()
	if err != nil {
		log.Fatalf("Could not get local address: %s", err)
	}

	log.Infof("Starting discovery of new Wemos with ip interface %s", ipAddr)
	api := wemo.NewByIp(ipAddr)
	//api.Debug = true

	seen := make(map[string]*WemoDeviceContext)

	go func() {
		for {

			devices, _ := api.DiscoverAll(5 * time.Second) //TODO: this needs to be evented

			ctx := context.Background()
			for _, device := range devices {

				deviceInfo, err := device.FetchDeviceInfo(ctx)
				if err != nil {
					log.HandleError(err, "Unable to fetch device info")
					continue
				}

				if existing, ok := seen[deviceInfo.SerialNumber]; ok {
					// We've already seen this device, update its info
					existing.Info = deviceInfo
					existing.Device = device

				} else {

					deviceStr := strings.ToLower(deviceInfo.DeviceType)

					detectedSwitch, _ := regexp.MatchString(switchDesignator, deviceStr)
					detectedInsight, _ := regexp.MatchString(insightDesignator, deviceStr)
					detectedMotion, _ := regexp.MatchString(motionDesignator, deviceStr)

					if (detectedSwitch || detectedInsight) && detectedMotion {
						log.Errorf("contradictory device type: %s", deviceStr)
						spew.Dump(deviceInfo)
						continue
					}

					if detectedSwitch || detectedInsight || detectedMotion {
						log.Infof("Creating new device (%v, %v, %v)", detectedSwitch, detectedInsight, detectedMotion)
						wemoDevice, err := d.NewSwitch(d, d.conn, device, deviceInfo, detectedSwitch || detectedInsight, detectedInsight, detectedMotion)
						if err != nil {
							log.Warningf("Failed to create (front-end) device: %s", err)
							continue
						}
						seen[deviceInfo.SerialNumber] = wemoDevice
					}

					if !detectedSwitch && !detectedInsight && !detectedMotion {
						log.Errorf("Unknown device type: %s", deviceStr)
						spew.Dump(deviceInfo)
					}
				}

			}

		}
	}()

	return nil
}

func (wsd *WemoDeviceContext) SetOnOff(state bool) error {
	var err error
	if state {
		wsd.Device.On()
	} else {
		wsd.Device.Off()
	}
	if err != nil {
		return fmt.Errorf("Failed to set on-off state: %s", err)
	}
	return nil
}

func (wsd *WemoDeviceContext) ToggleOnOff() error {
	curState := wsd.Device.GetBinaryState()
	if curState != 0 {
		return wsd.SetOnOff(false)
	} else {
		return wsd.SetOnOff(true)
	}
}

func (d *WemoDriver) NewSwitch(driver ninja.Driver, conn *ninja.Connection, device *wemo.Device, info *wemo.DeviceInfo, hasSwitch bool, hasPower bool, hasMotion bool) (*WemoDeviceContext, error) {
	sigs := map[string]string{
		"ninja:thingType":    "socket",
		"ninja:manufacturer": "Belkin",
	}

	ws := &WemoDeviceContext{
		BaseDevice: devices.BaseDevice{
			Driver: driver,
			Info: &model.Device{
				NaturalID:     info.MacAddress,
				Name:          &info.FriendlyName,
				NaturalIDType: info.DeviceType,
				Signatures:    &sigs,
			},
			Conn: conn,
			Log_: log,
		},
		Info:   info,
		Device: device,
	}

	if err := conn.ExportDevice(ws); err != nil {
		log.Fatalf("failed to export device: %v", err)
	}

	var onOffChannel *channels.OnOffChannel
	var powerChannel *channels.PowerChannel
	var motionChannel *channels.MotionChannel

	onOffChannel = channels.NewOnOffChannel(ws)
	err := conn.ExportChannel(ws, onOffChannel, "on-off")
	if err != nil {
		log.Fatalf("failed to export on-off channel: %v", err)
	}

	if hasMotion {
		motionChannel = channels.NewMotionChannel()
		err = conn.ExportChannel(ws, motionChannel, "motion")
		if err != nil {
			return nil, err
		}
	}

	if hasPower {
		powerChannel = channels.NewPowerChannel(ws)
		err = conn.ExportChannel(ws, powerChannel, "power")
		if err != nil {
			log.Fatalf("failed to export power channel: %v", err)
		}
	}

	ticker := time.NewTicker(time.Second * 5)
	go func() {
		for _ = range ticker.C {
			curState := device.GetBinaryState()
			onOffChannel.SendState(curState != 0) //curstate needs bool, but get state returns int
			if powerChannel != nil {
				if insightState := device.GetInsightParams(); insightState != nil {
					powerChannel.SendState(float64(insightState.Power) / 1000.0) //curstate needs bool, but get state returns int
				} else {
					log.Infof("power reporting failed")
				}
			}

			if motionChannel != nil {
				curState := ws.Device.GetBinaryState()
				if curState != 0 {
					motionChannel.SendMotion()
				}
			}
		}
	}()

	return ws, nil
}

func (d *WemoDriver) GetModuleInfo() *model.Module {
	return info
}

func (d *WemoDriver) SetEventHandler(sendEvent func(event string, payload interface{}) error) {
	d.sendEvent = sendEvent
}
<commit_msg>Improve diagnostics of underlying API.<commit_after>package main

import (
	"fmt"
	"regexp"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/devices"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go.wemo"
	"golang.org/x/net/context"
	"strings"
)

const (
	switchDesignator  = "controllee"
	insightDesignator = "insight"
	motionDesignator  = "sensor"
)

var info = ninja.LoadModuleInfo("./package.json")
var log = logger.GetLogger(info.ID)

type WemoDeviceContext struct {
	devices.BaseDevice
	Info   *wemo.DeviceInfo
	Device *wemo.Device
}

type WemoDriver struct {
	conn      *ninja.Connection
	sendEvent func(event string, payload interface{}) error
}

func NewWemoDriver() (*WemoDriver, error) {
	conn, err := ninja.Connect(info.ID)
	if err != nil {
		log.HandleError(err, "Could not connect to MQTT")
		return nil, err
	}

	driver := &WemoDriver{
		conn: conn,
	}

	err = conn.ExportDriver(driver)
	if err != nil {
		log.Fatalf("Failed to export Wemo driver: %s", err)
	}

	return driver, nil
}

func (d *WemoDriver) Start(x interface{}) error {
	log.Infof("Start method on Wemo driver called")

	return d.startDiscovery()
}

func (d *WemoDriver) startDiscovery() error {

	ipAddr, err := ninja.GetNetAddress()
	if err != nil {
		log.Fatalf("Could not get local address: %s", err)
	}

	log.Infof("Starting discovery of new Wemos with ip interface %s", ipAddr)
	api := wemo.NewByIp(ipAddr)
	//api.Debug = true

	seen := make(map[string]*WemoDeviceContext)

	go func() {
		for {

			devices, _ := api.DiscoverAll(5 * time.Second) //TODO: this needs to be evented

			ctx := context.Background()
			for _, device := range devices {

				device.Logger = func(fmt string, rest ...interface{}) (int, error) {
					log.Infof(fmt, rest...)
					return 0, nil
				}

				deviceInfo, err := device.FetchDeviceInfo(ctx)
				if err != nil {
					log.HandleError(err, "Unable to fetch device info")
					continue
				}

				if existing, ok := seen[deviceInfo.SerialNumber]; ok {
					// We've already seen this device, update its info
					existing.Info = deviceInfo
					existing.Device = device

				} else {

					deviceStr := strings.ToLower(deviceInfo.DeviceType)

					detectedSwitch, _ := regexp.MatchString(switchDesignator, deviceStr)
					detectedInsight, _ := regexp.MatchString(insightDesignator, deviceStr)
					detectedMotion, _ := regexp.MatchString(motionDesignator, deviceStr)

					if (detectedSwitch || detectedInsight) && detectedMotion {
						log.Errorf("contradictory device type: %s", deviceStr)
						spew.Dump(deviceInfo)
						continue
					}

					if detectedSwitch || detectedInsight || detectedMotion {
						log.Infof("Creating new device (%v, %v, %v)", detectedSwitch, detectedInsight, detectedMotion)
						wemoDevice, err := d.NewSwitch(d, d.conn, device, deviceInfo, detectedSwitch || detectedInsight, detectedInsight, detectedMotion)
						if err != nil {
							log.Warningf("Failed to create (front-end) device: %s", err)
							continue
						}
						seen[deviceInfo.SerialNumber] = wemoDevice
					}

					if !detectedSwitch && !detectedInsight && !detectedMotion {
						log.Errorf("Unknown device type: %s", deviceStr)
						spew.Dump(deviceInfo)
					}
				}

			}

		}
	}()

	return nil
}

func (wsd *WemoDeviceContext) SetOnOff(state bool) error {
	var err error
	if state {
		wsd.Device.On()
	} else {
		wsd.Device.Off()
	}
	if err != nil {
		return fmt.Errorf("Failed to set on-off state: %s", err)
	}
	return nil
}

func (wsd *WemoDeviceContext) ToggleOnOff() error {
	curState := wsd.Device.GetBinaryState()
	if curState != 0 {
		return wsd.SetOnOff(false)
	} else {
		return wsd.SetOnOff(true)
	}
}

func (d *WemoDriver) NewSwitch(driver ninja.Driver, conn *ninja.Connection, device *wemo.Device, info *wemo.DeviceInfo, hasSwitch bool, hasPower bool, hasMotion bool) (*WemoDeviceContext, error) {
	sigs := map[string]string{
		"ninja:thingType":    "socket",
		"ninja:manufacturer": "Belkin",
	}

	ws := &WemoDeviceContext{
		BaseDevice: devices.BaseDevice{
			Driver: driver,
			Info: &model.Device{
				NaturalID:     info.MacAddress,
				Name:          &info.FriendlyName,
				NaturalIDType: info.DeviceType,
				Signatures:    &sigs,
			},
			Conn: conn,
			Log_: log,
		},
		Info:   info,
		Device: device,
	}

	if err := conn.ExportDevice(ws); err != nil {
		log.Fatalf("failed to export device: %v", err)
	}

	var onOffChannel *channels.OnOffChannel
	var powerChannel *channels.PowerChannel
	var motionChannel *channels.MotionChannel

	onOffChannel = channels.NewOnOffChannel(ws)
	err := conn.ExportChannel(ws, onOffChannel, "on-off")
	if err != nil {
		log.Fatalf("failed to export on-off channel: %v", err)
	}

	if hasMotion {
		motionChannel = channels.NewMotionChannel()
		err = conn.ExportChannel(ws, motionChannel, "motion")
		if err != nil {
			return nil, err
		}
	}

	if hasPower {
		powerChannel = channels.NewPowerChannel(ws)
		err = conn.ExportChannel(ws, powerChannel, "power")
		if err != nil {
			log.Fatalf("failed to export power channel: %v", err)
		}
	}

	ticker := time.NewTicker(time.Second * 5)
	go func() {
		for _ = range ticker.C {
			curState := device.GetBinaryState()
			onOffChannel.SendState(curState != 0) //curstate needs bool, but get state returns int
			if powerChannel != nil {
				if insightState := device.GetInsightParams(); insightState != nil {
					powerChannel.SendState(float64(insightState.Power) / 1000.0) //curstate needs bool, but get state returns int
				} else {
					log.Infof("power reporting failed")
				}
			}

			if motionChannel != nil {
				curState := ws.Device.GetBinaryState()
				if curState != 0 {
					motionChannel.SendMotion()
				}
			}
		}
	}()

	return ws, nil
}

func (d *WemoDriver) GetModuleInfo() *model.Module {
	return info
}

func (d *WemoDriver) SetEventHandler(sendEvent func(event string, payload interface{}) error) {
	d.sendEvent = sendEvent
}
<|endoftext|>


<commit_before>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package util

// VERSION identifies Khan's current version
var VERSION = "4.3.7"
<commit_msg>Bump API version to 4.3.8<commit_after>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package util

// VERSION identifies Khan's current version
var VERSION = "4.3.8"
<|endoftext|>


<commit_before><commit_msg>Adjust rate limiter value.<commit_after><|endoftext|>


<commit_before>package utils

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
)

// Connection configuration
type Connection struct {
	APIEndpoint string
	CACert      string
	Cert        string
	Key         string
	Insecure    bool
}

// Config for kdeploy
type Config struct {
	Connection Connection
	Path       string
}

var cachedConfig *Config

// GetConfig returns cached config
func GetConfig() (*Config, error) {

	if cachedConfig != nil {
		return cachedConfig, nil
	}

	return nil, errors.New("Configuration must be initialized")
	//return fmt.Errorf("Configuration must be initialized", nil)
}

// PreReadConfig reads configuration before full arguments
func PreReadConfig() *Config {

	config, _ := ReadConfig()

	// if config is nil fill an structure with empty values
	if config == nil {
		config = &Config{
			Connection: Connection{},
		}
	}

	if os.Getenv("KUBERNETES_CA_CERT") != "" {
		config.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
	}
	if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
		config.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
	}
	if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
		config.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
	}
	if os.Getenv("KUBERNETES_ENDPOINT") != "" {
		config.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
	}

	return config
}

// func CachedConfig() (*Config, error) {
// 	count := 0
// 	var config Config
//
// 	if os.Getenv("KUBERNETES_CA_CERT") != "" {
// 		config.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
// 		config.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
// 		config.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_ENDPOINT") != "" {
// 		config.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
// 		count = count + 1
// 	}
// 	// TODO delete
// 	// if os.Getenv("KDEPLOY_CONFIG") != "" {
// 	// 	config.Path = os.Getenv("KDEPLOY_CONFIG")
// 	// 	count = count + 1
// 	// }
// 	if os.Getenv("KUBECONFIG") != "" {
// 		config.Path = os.Getenv("KUBECONFIG")
// 		count = count + 1
// 	}
//
// 	if count == 5 {
// 		return &config, nil
// 	}
// 	return nil, errors.New("Please check that all parameters are set in your configuration")
//
// }

func ReadConfig() (*Config, error) {

	if os.Getenv("KUBECONFIG") != "" {
		cfg, err := readKubeConfigFrom(os.Getenv("KUBECONFIG"))
		if err != nil {
			return cfg, nil
		}
	}

	home, err := homedir.Dir()
	if err != nil {
		return nil, fmt.Errorf("Couldn't get home dir for current user: %s", err.Error())
	}

	cfg, err := readKubeConfigFrom(filepath.Join(home, ".kube/config"))
	if err == nil {
		return cfg, nil
	}

	return nil, nil
}

// readKubeConfigFrom reads kubeconfig and use it to fill a kdeploy config
func readKubeConfigFrom(path string) (*Config, error) {
	log.Debugf("readKubeConfigFrom %s", path)
	// Read kubeconfig
	if !FileExists(path) {
		return nil, fmt.Errorf("Could not locate file %s", path)
	}

	configBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	var kc KubeConfig

	err = yaml.Unmarshal(configBytes, &kc)
	if err != nil {
		return nil, err
	}

	// Create kdeploy config
	config := readConfigFromKubeConfig(&kc)

	// add path
	config.Path = path

	log.Debugf("returning config from kubeconfig: %+v", config)
	return config, nil
}

// readConfigFromKubeConfig extract Kubeconfig fields to build a Kdeploy config structure
func readConfigFromKubeConfig(kc *KubeConfig) *Config {
	log.Debugf("readConfigFromKubeConfig %+v", kc)
	// currentContext := kc.CurrentContext
	var userID, clusterID string
	config := &Config{}

	for _, context := range kc.Contexts {
		if context.Name == kc.CurrentContext {
			userID = context.Context.User
			clusterID = context.Context.Cluster
			break
		}
	}

	if userID != "" {
		for _, user := range kc.Users {
			if user.Name == userID {
				config.Connection.Cert = user.User.ClientCertificate
				config.Connection.Key = user.User.ClientKey
				break
			}

		}
	}

	if clusterID != "" {
		for _, cluster := range kc.Clusters {
			if cluster.Name == clusterID {
				config.Connection.APIEndpoint = cluster.Cluster.Server
				config.Connection.CACert = cluster.Cluster.CertificateAuthority
			}
		}
	}

	return config
}

func ReadConfigFrom(path string) (*Config, error) {

	cfgFile, err := filepath.Abs(path)
	if err != nil {
		return nil, err
	}

	if FileExists(cfgFile) {
		configBytes, err := ioutil.ReadFile(cfgFile)
		if err != nil {
			return nil, err
		}
		var cfg Config
		err = yaml.Unmarshal(configBytes, &cfg)
		if err != nil {
			return nil, err
		}

		if os.Getenv("KUBERNETES_CA_CERT") != "" {
			cfg.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
		}
		if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
			cfg.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
		}
		if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
			cfg.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
		}
		if os.Getenv("KUBERNETES_ENDPOINT") != "" {
			cfg.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
		}

		cfg.Path = cfgFile
		return &cfg, nil
	}
	return nil, errors.New(fmt.Sprintf("Could not locate file %s", path))
}

func InitializeConfig(c *cli.Context) error {
	log.Debug("InitializeConfig")
	// overwrite with environment/arguments vars
	if overwKdeployConfig := c.String("kdeploy-config"); overwKdeployConfig != "" {
		cachedConfig.Path = overwKdeployConfig
		cachedConfig, _ = ReadConfigFrom(overwKdeployConfig)
	} else {
		// read from path
		cachedConfig, _ = ReadConfig()
	}

	// if config is nil fill an structure with empty values
	if cachedConfig == nil {
		cachedConfig = &Config{
			Connection: Connection{},
		}
	}

	parameters := false

	// overwrite with environment/arguments vars
	if overwCaCert := c.String("ca-cert"); overwCaCert != "" {
		cachedConfig.Connection.CACert = overwCaCert
	}

	// overwrite with environment/arguments vars
	if overwClientCert := c.String("client-cert"); overwClientCert != "" {
		cachedConfig.Connection.Cert = overwClientCert
	}

	// overwrite with environment/arguments vars
	if overwClientKey := c.String("client-key"); overwClientKey != "" {
		cachedConfig.Connection.Key = overwClientKey
	}

	// overwrite with environment/arguments vars
	if overwKubernetesEndpoint := c.String("kubernetes-endpoint"); overwKubernetesEndpoint != "" {
		cachedConfig.Connection.APIEndpoint = overwKubernetesEndpoint
	}

	// insecure connection flag
	cachedConfig.Connection.Insecure = c.Bool("insecure")

	if cachedConfig.Connection.APIEndpoint == "" {
		log.Warn("Please use parameter --kubernetes-endpoint")
		parameters = true
	}
	if cachedConfig.Connection.Cert == "" {
		log.Warn("Please use parameter --client-cert")
		parameters = true
	}
	if cachedConfig.Connection.Key == "" {
		log.Warn("Please use parameter --client-key")
		parameters = true
	}

	if parameters {
		fmt.Printf("\n")
		cli.ShowCommandHelp(c, c.Command.Name)
		os.Exit(2)
	}

	os.Setenv("KUBERNETES_CA_CERT", cachedConfig.Connection.CACert)
	os.Setenv("KUBERNETES_CLIENT_CERT", cachedConfig.Connection.Cert)
	os.Setenv("KUBERNETES_CLIENT_KEY", cachedConfig.Connection.Key)
	os.Setenv("KUBERNETES_ENDPOINT", cachedConfig.Connection.APIEndpoint)
	os.Setenv("KUBECONFIG", cachedConfig.Path)

	// TODO delete
	// os.Setenv("KDEPLOY_CONFIG", config.Path)

	return nil
}
<commit_msg>Support configuring insecure connection from kubeconfig file<commit_after>package utils

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
)

// Connection configuration
type Connection struct {
	APIEndpoint string
	CACert      string
	Cert        string
	Key         string
	Insecure    bool
}

// Config for kdeploy
type Config struct {
	Connection Connection
	Path       string
}

var cachedConfig *Config

// GetConfig returns cached config
func GetConfig() (*Config, error) {

	if cachedConfig != nil {
		return cachedConfig, nil
	}

	return nil, errors.New("Configuration must be initialized")
	//return fmt.Errorf("Configuration must be initialized", nil)
}

// PreReadConfig reads configuration before full arguments
func PreReadConfig() *Config {

	config, _ := ReadConfig()

	// if config is nil fill an structure with empty values
	if config == nil {
		config = &Config{
			Connection: Connection{},
		}
	}

	if os.Getenv("KUBERNETES_CA_CERT") != "" {
		config.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
	}
	if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
		config.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
	}
	if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
		config.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
	}
	if os.Getenv("KUBERNETES_ENDPOINT") != "" {
		config.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
	}

	return config
}

// func CachedConfig() (*Config, error) {
// 	count := 0
// 	var config Config
//
// 	if os.Getenv("KUBERNETES_CA_CERT") != "" {
// 		config.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
// 		config.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
// 		config.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
// 		count = count + 1
// 	}
// 	if os.Getenv("KUBERNETES_ENDPOINT") != "" {
// 		config.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
// 		count = count + 1
// 	}
// 	// TODO delete
// 	// if os.Getenv("KDEPLOY_CONFIG") != "" {
// 	// 	config.Path = os.Getenv("KDEPLOY_CONFIG")
// 	// 	count = count + 1
// 	// }
// 	if os.Getenv("KUBECONFIG") != "" {
// 		config.Path = os.Getenv("KUBECONFIG")
// 		count = count + 1
// 	}
//
// 	if count == 5 {
// 		return &config, nil
// 	}
// 	return nil, errors.New("Please check that all parameters are set in your configuration")
//
// }

func ReadConfig() (*Config, error) {

	if os.Getenv("KUBECONFIG") != "" {
		cfg, err := readKubeConfigFrom(os.Getenv("KUBECONFIG"))
		if err != nil {
			return cfg, nil
		}
	}

	home, err := homedir.Dir()
	if err != nil {
		return nil, fmt.Errorf("Couldn't get home dir for current user: %s", err.Error())
	}

	cfg, err := readKubeConfigFrom(filepath.Join(home, ".kube/config"))
	if err == nil {
		return cfg, nil
	}

	return nil, nil
}

// readKubeConfigFrom reads kubeconfig and use it to fill a kdeploy config
func readKubeConfigFrom(path string) (*Config, error) {
	log.Debugf("readKubeConfigFrom %s", path)
	// Read kubeconfig
	if !FileExists(path) {
		return nil, fmt.Errorf("Could not locate file %s", path)
	}

	configBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	var kc KubeConfig

	err = yaml.Unmarshal(configBytes, &kc)
	if err != nil {
		return nil, err
	}

	// Create kdeploy config
	config := readConfigFromKubeConfig(&kc)

	// add path
	config.Path = path

	log.Debugf("returning config from kubeconfig: %+v", config)
	return config, nil
}

// readConfigFromKubeConfig extract Kubeconfig fields to build a Kdeploy config structure
func readConfigFromKubeConfig(kc *KubeConfig) *Config {
	log.Debugf("readConfigFromKubeConfig %+v", kc)
	// currentContext := kc.CurrentContext
	var userID, clusterID string
	config := &Config{}

	for _, context := range kc.Contexts {
		if context.Name == kc.CurrentContext {
			userID = context.Context.User
			clusterID = context.Context.Cluster
			break
		}
	}

	if userID != "" {
		for _, user := range kc.Users {
			if user.Name == userID {
				config.Connection.Cert = user.User.ClientCertificate
				config.Connection.Key = user.User.ClientKey
				break
			}

		}
	}

	if clusterID != "" {
		for _, cluster := range kc.Clusters {
			if cluster.Name == clusterID {
				config.Connection.APIEndpoint = cluster.Cluster.Server
				config.Connection.CACert = cluster.Cluster.CertificateAuthority
				config.Connection.Insecure = cluster.Cluster.InsecureSkipTLSVerify
			}
		}
	}

	return config
}

func ReadConfigFrom(path string) (*Config, error) {

	cfgFile, err := filepath.Abs(path)
	if err != nil {
		return nil, err
	}

	if FileExists(cfgFile) {
		configBytes, err := ioutil.ReadFile(cfgFile)
		if err != nil {
			return nil, err
		}
		var cfg Config
		err = yaml.Unmarshal(configBytes, &cfg)
		if err != nil {
			return nil, err
		}

		if os.Getenv("KUBERNETES_CA_CERT") != "" {
			cfg.Connection.CACert = os.Getenv("KUBERNETES_CA_CERT")
		}
		if os.Getenv("KUBERNETES_CLIENT_CERT") != "" {
			cfg.Connection.Cert = os.Getenv("KUBERNETES_CLIENT_CERT")
		}
		if os.Getenv("KUBERNETES_CLIENT_KEY") != "" {
			cfg.Connection.Key = os.Getenv("KUBERNETES_CLIENT_KEY")
		}
		if os.Getenv("KUBERNETES_ENDPOINT") != "" {
			cfg.Connection.APIEndpoint = os.Getenv("KUBERNETES_ENDPOINT")
		}

		cfg.Path = cfgFile
		return &cfg, nil
	}
	return nil, errors.New(fmt.Sprintf("Could not locate file %s", path))
}

func InitializeConfig(c *cli.Context) error {
	log.Debug("InitializeConfig")
	// overwrite with environment/arguments vars
	if overwKdeployConfig := c.String("kdeploy-config"); overwKdeployConfig != "" {
		cachedConfig.Path = overwKdeployConfig
		cachedConfig, _ = ReadConfigFrom(overwKdeployConfig)
	} else {
		// read from path
		cachedConfig, _ = ReadConfig()
	}

	// if config is nil fill an structure with empty values
	if cachedConfig == nil {
		cachedConfig = &Config{
			Connection: Connection{},
		}
	}

	parameters := false

	// overwrite with environment/arguments vars
	if overwCaCert := c.String("ca-cert"); overwCaCert != "" {
		cachedConfig.Connection.CACert = overwCaCert
	}

	// overwrite with environment/arguments vars
	if overwClientCert := c.String("client-cert"); overwClientCert != "" {
		cachedConfig.Connection.Cert = overwClientCert
	}

	// overwrite with environment/arguments vars
	if overwClientKey := c.String("client-key"); overwClientKey != "" {
		cachedConfig.Connection.Key = overwClientKey
	}

	// overwrite with environment/arguments vars
	if overwKubernetesEndpoint := c.String("kubernetes-endpoint"); overwKubernetesEndpoint != "" {
		cachedConfig.Connection.APIEndpoint = overwKubernetesEndpoint
	}

	// insecure connection flag
	cachedConfig.Connection.Insecure = cachedConfig.Connection.Insecure || c.Bool("insecure")

	if cachedConfig.Connection.APIEndpoint == "" {
		log.Warn("Please use parameter --kubernetes-endpoint")
		parameters = true
	}
	if cachedConfig.Connection.Cert == "" {
		log.Warn("Please use parameter --client-cert")
		parameters = true
	}
	if cachedConfig.Connection.Key == "" {
		log.Warn("Please use parameter --client-key")
		parameters = true
	}

	if parameters {
		fmt.Printf("\n")
		cli.ShowCommandHelp(c, c.Command.Name)
		os.Exit(2)
	}

	os.Setenv("KUBERNETES_CA_CERT", cachedConfig.Connection.CACert)
	os.Setenv("KUBERNETES_CLIENT_CERT", cachedConfig.Connection.Cert)
	os.Setenv("KUBERNETES_CLIENT_KEY", cachedConfig.Connection.Key)
	os.Setenv("KUBERNETES_ENDPOINT", cachedConfig.Connection.APIEndpoint)
	os.Setenv("KUBECONFIG", cachedConfig.Path)

	// TODO delete
	// os.Setenv("KDEPLOY_CONFIG", config.Path)

	return nil
}
<|endoftext|>


<commit_before><commit_msg>minor formatting change for godoc<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed bug causing special characters to break select all functionality. -SJA<commit_after><|endoftext|>


<commit_before><commit_msg>Cleaning Admin list before load, to avoid duplications<commit_after><|endoftext|>


<commit_before><commit_msg>auto-indented<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package apiserver_test

import (
	"github.com/juju/errors"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/apiserver"
	"github.com/juju/juju/rpc"
	"github.com/juju/juju/testing"
)

type restrictModelSuite struct {
	testing.BaseSuite
	root rpc.Root
}

var _ = gc.Suite(&restrictModelSuite{})

func (s *restrictModelSuite) SetUpSuite(c *gc.C) {
	s.BaseSuite.SetUpSuite(c)
	s.root = apiserver.TestingModelOnlyRoot()
}

func (s *restrictModelSuite) TestAllowed(c *gc.C) {
	caller, err := s.root.FindMethod("Client", 1, "FullStatus")
	c.Check(err, jc.ErrorIsNil)
	c.Check(caller, gc.NotNil)
}

func (s *restrictModelSuite) TestBlocked(c *gc.C) {
	caller, err := s.root.FindMethod("ModelManager", 2, "ListModels")
	c.Assert(err, gc.ErrorMatches, `facade "ModelManager" not supported for model API connection`)
	c.Assert(errors.IsNotSupported(err), jc.IsTrue)
	c.Assert(caller, gc.IsNil)
}
<commit_msg>apiserver: Test common facades with model login<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package apiserver_test

import (
	"github.com/juju/errors"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/apiserver"
	"github.com/juju/juju/rpc"
	"github.com/juju/juju/testing"
)

type restrictModelSuite struct {
	testing.BaseSuite
	root rpc.Root
}

var _ = gc.Suite(&restrictModelSuite{})

func (s *restrictModelSuite) SetUpSuite(c *gc.C) {
	s.BaseSuite.SetUpSuite(c)
	s.root = apiserver.TestingModelOnlyRoot()
}

func (s *restrictModelSuite) TestAllowed(c *gc.C) {
	s.assertMethod(c, "Client", 1, "FullStatus")
	s.assertMethod(c, "Pinger", 1, "Ping")
}

func (s *restrictModelSuite) TestBlocked(c *gc.C) {
	caller, err := s.root.FindMethod("ModelManager", 2, "ListModels")
	c.Assert(err, gc.ErrorMatches, `facade "ModelManager" not supported for model API connection`)
	c.Assert(errors.IsNotSupported(err), jc.IsTrue)
	c.Assert(caller, gc.IsNil)
}

func (s *restrictModelSuite) assertMethod(c *gc.C, facadeName string, version int, method string) {
	caller, err := s.root.FindMethod(facadeName, version, method)
	c.Check(err, jc.ErrorIsNil)
	c.Check(caller, gc.NotNil)
}
<|endoftext|>


<commit_before><commit_msg>Changed queue to use nodes<commit_after><|endoftext|>


<commit_before><commit_msg>rados: naming conventions: disable revive naming check on old struct<commit_after><|endoftext|>


<commit_before>package notifier

import (
	"bytes"
	"encoding/json"
	"fmt"
	"k8s.io/api/core/v1"
	"net/http"
	"time"
)

const NotifierSlack = "slack"

var DefaultTimeout time.Duration = 15 * time.Second

type Slack struct {
	Webhook string
	Client  *http.Client
}

type request struct {
	Message string `json:"text"`
}

func NewSlackNotifier(webhook string) *Slack {
	return &Slack{
		Webhook: webhook,
		Client: &http.Client{
			Timeout: DefaultTimeout,
		},
	}
}

func (s Slack) NotifyTermination(victim v1.Pod) error {
	message := request{
		Message: fmt.Sprintf("pod %s/%s is begin terminated.", victim.Namespace, victim.Name),
	}
	messageBody, err := json.Marshal(message)

	if err != nil {
		return err
	}

	req, err := http.NewRequest(http.MethodPost, s.Webhook, bytes.NewBuffer(messageBody))

	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")

	res, err := s.Client.Do(req)

	if err != nil {
		return err
	}

	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code %d from slack webhook %s", res.StatusCode, s.Webhook)
	}

	return nil
}
<commit_msg>Added attachment to slack notification<commit_after>package notifier

import (
	"bytes"
	"encoding/json"
	"fmt"
	"k8s.io/api/core/v1"
	"net/http"
	"time"
)

const NotifierSlack = "slack"

var DefaultTimeout time.Duration = 15 * time.Second

type Slack struct {
	Webhook string
	Client  *http.Client
}

type request struct {
	Message     string       `json:"text"`
	Attachments []attachment `json:"attachments"`
}
type SlackField struct {
	Title string `yaml:"title,omitempty" json:"title,omitempty"`
	Value string `yaml:"value,omitempty" json:"value,omitempty"`
	Short *bool  `yaml:"short,omitempty" json:"short,omitempty"`
}

type attachment struct {
	Title      string       `json:"title,omitempty"`
	TitleLink  string       `json:"title_link,omitempty"`
	Pretext    string       `json:"pretext,omitempty"`
	Text       string       `json:"text"`
	Fallback   string       `json:"fallback"`
	CallbackID string       `json:"callback_id"`
	Fields     []SlackField `json:"fields,omitempty"`
	ImageURL   string       `json:"image_url,omitempty"`
	ThumbURL   string       `json:"thumb_url,omitempty"`
	Footer     string       `json:"footer"`
	Color      string       `json:"color,omitempty"`
	MrkdwnIn   []string     `json:"mrkdwn_in,omitempty"`
}

func NewSlackNotifier(webhook string) *Slack {
	return &Slack{
		Webhook: webhook,
		Client: &http.Client{
			Timeout: DefaultTimeout,
		},
	}
}

func createSlackRequest(victim v1.Pod) request {
	attach := attachment{
		Title:  "Chaos event - Pod termination",
		Text:   fmt.Sprintf("pod %s has been selected by chaos-kube for termination", victim.Name),
		Footer: "chaos-kube",
		Color:  "#F35A00",
	}

	short := len(victim.Namespace) < 20 && len(victim.Name) < 20

	attach.Fields = []SlackField{
		{
			Title: "namespace",
			Value: victim.Namespace,
			Short: &short,
		},
		{
			Title: "pod",
			Value: victim.Name,
			Short: &short,
		},
	}

	return request{
		Attachments: []attachment{attach},
	}
}
func (s Slack) NotifyTermination(victim v1.Pod) error {
	message := createSlackRequest(victim)

	messageBody, err := json.Marshal(message)

	if err != nil {
		return err
	}

	req, err := http.NewRequest(http.MethodPost, s.Webhook, bytes.NewBuffer(messageBody))

	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")

	res, err := s.Client.Do(req)

	if err != nil {
		return err
	}

	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code %d from slack webhook %s", res.StatusCode, s.Webhook)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"runtime"
	"sort"
	"strings"
	"time"

	"github.com/bradfitz/http2"
	"github.com/myfreeweb/443d/demux"
	"github.com/myfreeweb/443d/unixsock"
	"github.com/myfreeweb/443d/util"
	"github.com/ryanuber/go-glob"
	"gopkg.in/yaml.v2"
)

type HttpBackend struct {
	Hostnames []string
	Paths     map[string][]struct {
		Net     string
		Address string
		CutPath bool
	}
	PathOrder []string
}

type Config struct {
	Tls struct {
		Listen string
		Cert   string
		Key    string
		Ssh    string
	}
	Http struct {
		Listen string
	}
	Hosts       []HttpBackend
	DefaultHost string
}

var confpath = flag.String("config", "/usr/local/etc/443d.yaml", "path to the configuration file")
var config Config

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	readConfig()
	srv := &http.Server{
		Addr:    config.Tls.Listen,
		Handler: httpHandler(),
	}
	http2.ConfigureServer(srv, &http2.Server{})
	srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
	srv.TLSConfig.Certificates[0], _ = tls.LoadX509KeyPair(config.Tls.Cert, config.Tls.Key)
	go func() {
		tcpl, err := net.Listen("tcp", config.Http.Listen)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		serve("HTTP server", config.Http.Listen, srv, tcpl)
	}()
	go func() {
		tcpl, err := net.Listen("tcp", config.Tls.Listen)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		sshh := demux.SshHandler(config.Tls.Ssh)
		dl := &demux.DemultiplexingListener{tcpl.(*net.TCPListener), sshh}
		tlsl := tls.NewListener(dl, srv.TLSConfig)
		serve("TLS server", config.Tls.Listen, srv, tlsl)
	}()
	for {
		time.Sleep(500 * time.Millisecond)
	}
}

func serve(name string, addr string, srv *http.Server, listener net.Listener) {
	if addr == "" {
		log.Printf("No listen address for " + name + " \n")
		return
	}
	for {
		log.Printf("Starting "+name+" on tcp %v\n", config.Tls.Listen)
		if err := srv.Serve(listener); err != nil {
			log.Printf(name+" error: %v :-(\n", err)
		}
		time.Sleep(200 * time.Millisecond)
		log.Printf("Restarting " + name + "\n")
	}
}

func httpHandler() *httputil.ReverseProxy {
	transp := &http.Transport{MaxIdleConnsPerHost: 100}
	transp.RegisterProtocol("unix", unixsock.NewUnixTransport())
	return &httputil.ReverseProxy{
		Transport: transp,
		Director: func(r *http.Request) {
			if r.Host == "" {
				r.Host = config.DefaultHost
			}
			for hostid := range config.Hosts {
				hostcnf := config.Hosts[hostid]
				for hostnid := range hostcnf.Hostnames {
					hostn := hostcnf.Hostnames[hostnid]
					if glob.Glob(hostn, r.Host) {
						applyHost(&hostcnf, r)
						return
					}
				}
			}
		},
	}
}

func applyHost(hostcnf *HttpBackend, r *http.Request) {
	for _, pathprefix := range hostcnf.PathOrder {
		if strings.HasPrefix(r.URL.Path, pathprefix) {
			backends := hostcnf.Paths[pathprefix]
			backend := backends[rand.Intn(len(backends))]
			if backend.Net == "" {
				r.URL.Scheme = "http"
			} else {
				r.URL.Scheme = backend.Net
			}
			r.URL.Host = backend.Address
			if backend.CutPath {
				r.URL.Path = strings.TrimPrefix(r.URL.Path, pathprefix)
			}
			return
		}
	}
}

func readConfig() {
	flag.Parse()
	f, err := os.Open(*confpath)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	defer f.Close()
	buf, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	if err := yaml.Unmarshal(buf, &config); err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	for ib := range config.Hosts {
		var order []string
		for path := range config.Hosts[ib].Paths {
			order = append(order, path)
		}
		sort.Sort(util.ByLengthDesc(order))
		config.Hosts[ib].PathOrder = order
	}
	if config.DefaultHost == "" {
		config.DefaultHost = "localhost"
	}
}
<commit_msg>fix cut_path yaml<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"runtime"
	"sort"
	"strings"
	"time"

	"github.com/bradfitz/http2"
	"github.com/myfreeweb/443d/demux"
	"github.com/myfreeweb/443d/unixsock"
	"github.com/myfreeweb/443d/util"
	"github.com/ryanuber/go-glob"
	"gopkg.in/yaml.v2"
)

type HttpBackend struct {
	Hostnames []string
	Paths     map[string][]struct {
		Net     string
		Address string
		CutPath bool `yaml:"cut_path"`
	}
	PathOrder []string
}

type Config struct {
	Tls struct {
		Listen string
		Cert   string
		Key    string
		Ssh    string
	}
	Http struct {
		Listen string
	}
	Hosts       []HttpBackend
	DefaultHost string
}

var confpath = flag.String("config", "/usr/local/etc/443d.yaml", "path to the configuration file")
var config Config

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	readConfig()
	srv := &http.Server{
		Addr:    config.Tls.Listen,
		Handler: httpHandler(),
	}
	http2.ConfigureServer(srv, &http2.Server{})
	srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
	srv.TLSConfig.Certificates[0], _ = tls.LoadX509KeyPair(config.Tls.Cert, config.Tls.Key)
	go func() {
		tcpl, err := net.Listen("tcp", config.Http.Listen)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		serve("HTTP server", config.Http.Listen, srv, tcpl)
	}()
	go func() {
		tcpl, err := net.Listen("tcp", config.Tls.Listen)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		sshh := demux.SshHandler(config.Tls.Ssh)
		dl := &demux.DemultiplexingListener{tcpl.(*net.TCPListener), sshh}
		tlsl := tls.NewListener(dl, srv.TLSConfig)
		serve("TLS server", config.Tls.Listen, srv, tlsl)
	}()
	for {
		time.Sleep(500 * time.Millisecond)
	}
}

func serve(name string, addr string, srv *http.Server, listener net.Listener) {
	if addr == "" {
		log.Printf("No listen address for " + name + " \n")
		return
	}
	for {
		log.Printf("Starting "+name+" on tcp %v\n", config.Tls.Listen)
		if err := srv.Serve(listener); err != nil {
			log.Printf(name+" error: %v :-(\n", err)
		}
		time.Sleep(200 * time.Millisecond)
		log.Printf("Restarting " + name + "\n")
	}
}

func httpHandler() *httputil.ReverseProxy {
	transp := &http.Transport{MaxIdleConnsPerHost: 100}
	transp.RegisterProtocol("unix", unixsock.NewUnixTransport())
	return &httputil.ReverseProxy{
		Transport: transp,
		Director: func(r *http.Request) {
			if r.Host == "" {
				r.Host = config.DefaultHost
			}
			for hostid := range config.Hosts {
				hostcnf := config.Hosts[hostid]
				for hostnid := range hostcnf.Hostnames {
					hostn := hostcnf.Hostnames[hostnid]
					if glob.Glob(hostn, r.Host) {
						applyHost(&hostcnf, r)
						return
					}
				}
			}
		},
	}
}

func applyHost(hostcnf *HttpBackend, r *http.Request) {
	for _, pathprefix := range hostcnf.PathOrder {
		if strings.HasPrefix(r.URL.Path, pathprefix) {
			backends := hostcnf.Paths[pathprefix]
			backend := backends[rand.Intn(len(backends))]
			if backend.Net == "" {
				r.URL.Scheme = "http"
			} else {
				r.URL.Scheme = backend.Net
			}
			r.URL.Host = backend.Address
			if backend.CutPath {
				r.URL.Path = strings.TrimPrefix(r.URL.Path, pathprefix)
			}
			return
		}
	}
}

func readConfig() {
	flag.Parse()
	f, err := os.Open(*confpath)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	defer f.Close()
	buf, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	if err := yaml.Unmarshal(buf, &config); err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	for ib := range config.Hosts {
		var order []string
		for path := range config.Hosts[ib].Paths {
			order = append(order, path)
		}
		sort.Sort(util.ByLengthDesc(order))
		config.Hosts[ib].PathOrder = order
	}
	if config.DefaultHost == "" {
		config.DefaultHost = "localhost"
	}
}
<|endoftext|>


<commit_before>package govpr

import (
	"fmt"
	"github.com/liuxp0827/govpr/constant"
	"github.com/liuxp0827/govpr/feature"
	"github.com/liuxp0827/govpr/gmm"
	"github.com/liuxp0827/govpr/log"
	"github.com/liuxp0827/govpr/waveIO"
	"os"
	"path"
)

type VPREngine struct {
	trainBuf  []int16
	verifyBuf []int16

	score float64

	ubmFile       string
	userModelFile string

	deleteSil   bool
	delSilRange int

	ubm *gmm.GMM

	_minTrainLen int64
	_minVerLen   int64
}

func NewVPREngine(sampleRate, delSilRange int, deleteSil bool, ubmFile, userModelFile string) (*VPREngine, error) {
	engine := VPREngine{
		ubmFile:       ubmFile,
		userModelFile: userModelFile,
		verifyBuf:     make([]int16, 0),
		trainBuf:      make([]int16, 0),
		deleteSil:     deleteSil,
		delSilRange:   delSilRange,
		ubm:           gmm.NewGMM(),
		_minTrainLen:  int64(sampleRate * 2),
		_minVerLen:    int64(float64(sampleRate) * 0.25),
	}

	err := engine.init()
	if err != nil {
		return nil, err
	}

	return &engine, nil
}

func (this *VPREngine) init() error {
	if this.ubm == nil {
		return fmt.Errorf("ubm model is nil")
	}

	if err := this.ubm.LoadModel(this.ubmFile); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MODEL_LOAD_FAILED, err.Error())
	}
	return nil
}

func (this *VPREngine) TrainModel() error {
	if this.trainBuf == nil || int64(len(this.trainBuf)) < this._minTrainLen {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	tmpubm := gmm.NewGMM()
	tmpubm.Copy(this.ubm)

	client := gmm.NewGMM()
	client.DupModel(this.ubm)
	if err := feature.Extract(this.trainBuf, tmpubm); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	for k := 0; k < constant.MAXLOP; k++ {
		if ret, err := tmpubm.EM(tmpubm.Mixtures); ret == 0 || err != nil {
			log.Error(err)
			return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
		}

		for i := 0; i < tmpubm.Mixtures; i++ {
			for j := 0; j < tmpubm.VectorSize; j++ {
				client.Mean[i][j] = (float64(tmpubm.Frames)*tmpubm.MixtureWeight[i])*
					tmpubm.Mean[i][j] + constant.REL_FACTOR*client.Mean[i][j]

				client.Mean[i][j] /= (float64(tmpubm.Frames)*tmpubm.MixtureWeight[i] + constant.REL_FACTOR)
			}
		}
	}

	userModelPath := path.Dir(this.userModelFile)
	err := os.MkdirAll(userModelPath, 0755)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
	}

	if err = client.SaveModel(this.userModelFile); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
	}
	return nil
}

func (this *VPREngine) VerifyModel() error {
	if this.verifyBuf == nil || len(this.verifyBuf) <= 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	var buf []int16 = this.verifyBuf
	var length int64

	//buf = waveIO.DelSilence(this.verifyBuf, this.delSilRange)

	length = int64(len(buf))
	if length < this._minVerLen {
		return LSV_ERR_NEED_MORE_SAMPLE
	}

	var client *gmm.GMM = gmm.NewGMM()
	err := client.LoadModel(this.userModelFile)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MODEL_LOAD_FAILED, err.Error())
	}

	tmpubm := gmm.NewGMM()
	tmpubm.Copy(this.ubm)

	err = feature.Extract(buf, client)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	err = tmpubm.CopyFeatureData(client)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	var logClient, logWorld float64
	logClient = client.LProb(client.FeatureData, 0, int64(client.Frames))
	logWorld = tmpubm.LProb(tmpubm.FeatureData, 0, int64(tmpubm.Frames))
	this.score = (logClient - logWorld) / float64(client.Frames)
	return nil
}

func (this *VPREngine) AddTrainBuffer(buf []byte) error {
	if buf == nil || len(buf) == 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	sBuff := make([]int16, 0)
	length := len(buf)
	for ii := 0; ii < length; ii += 2 {
		cBuff16 := int16(buf[ii])
		cBuff16 |= int16(buf[ii+1]) << 8
		sBuff = append(sBuff, cBuff16)
	}

	if this.deleteSil {
		sBuff = waveIO.DelSilence(sBuff, this.delSilRange)
	}

	this.trainBuf = append(this.trainBuf, sBuff...)
	return nil
}

func (this *VPREngine) AddVerifyBuffer(buf []byte) error {
	if buf == nil || len(buf) == 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	sBuff := make([]int16, 0)
	length := len(buf)
	for ii := 0; ii < length; ii += 2 {
		cBuff16 := int16(buf[ii])
		cBuff16 |= int16(buf[ii+1]) << 8
		sBuff = append(sBuff, cBuff16)
	}

	if this.deleteSil {
		sBuff = waveIO.DelSilence(sBuff, this.delSilRange)
	}

	this.verifyBuf = sBuff
	return nil
}

func (this *VPREngine) ClearTrainBuffer() {
	this.trainBuf = this.trainBuf[:0]
}

func (this *VPREngine) ClearVerifyBuffer() {
	this.verifyBuf = this.verifyBuf[:0]
}

func (this *VPREngine) ClearAllBuffer() {
	this.ClearTrainBuffer()
	this.ClearVerifyBuffer()
}

func (this *VPREngine) GetScore() float64 {
	return this.score
}
<commit_msg>Fixes #5: index out of range<commit_after>package govpr

import (
	"fmt"
	"github.com/liuxp0827/govpr/constant"
	"github.com/liuxp0827/govpr/feature"
	"github.com/liuxp0827/govpr/gmm"
	"github.com/liuxp0827/govpr/log"
	"github.com/liuxp0827/govpr/waveIO"
	"os"
	"path"
)

type VPREngine struct {
	trainBuf  []int16
	verifyBuf []int16

	score float64

	ubmFile       string
	userModelFile string

	deleteSil   bool
	delSilRange int

	ubm *gmm.GMM

	_minTrainLen int64
	_minVerLen   int64
}

func NewVPREngine(sampleRate, delSilRange int, deleteSil bool, ubmFile, userModelFile string) (*VPREngine, error) {
	engine := VPREngine{
		ubmFile:       ubmFile,
		userModelFile: userModelFile,
		verifyBuf:     make([]int16, 0),
		trainBuf:      make([]int16, 0),
		deleteSil:     deleteSil,
		delSilRange:   delSilRange,
		ubm:           gmm.NewGMM(),
		_minTrainLen:  int64(sampleRate * 2),
		_minVerLen:    int64(float64(sampleRate) * 0.25),
	}

	err := engine.init()
	if err != nil {
		return nil, err
	}

	return &engine, nil
}

func (this *VPREngine) init() error {
	if this.ubm == nil {
		return fmt.Errorf("ubm model is nil")
	}

	if err := this.ubm.LoadModel(this.ubmFile); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MODEL_LOAD_FAILED, err.Error())
	}
	return nil
}

func (this *VPREngine) TrainModel() error {
	if this.trainBuf == nil || int64(len(this.trainBuf)) < this._minTrainLen {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	tmpubm := gmm.NewGMM()
	tmpubm.Copy(this.ubm)

	client := gmm.NewGMM()
	client.DupModel(this.ubm)
	if err := feature.Extract(this.trainBuf, tmpubm); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	for k := 0; k < constant.MAXLOP; k++ {
		if ret, err := tmpubm.EM(tmpubm.Mixtures); ret == 0 || err != nil {
			log.Error(err)
			return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
		}

		for i := 0; i < tmpubm.Mixtures; i++ {
			for j := 0; j < tmpubm.VectorSize; j++ {
				client.Mean[i][j] = (float64(tmpubm.Frames)*tmpubm.MixtureWeight[i])*
					tmpubm.Mean[i][j] + constant.REL_FACTOR*client.Mean[i][j]

				client.Mean[i][j] /= (float64(tmpubm.Frames)*tmpubm.MixtureWeight[i] + constant.REL_FACTOR)
			}
		}
	}

	userModelPath := path.Dir(this.userModelFile)
	err := os.MkdirAll(userModelPath, 0755)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
	}

	if err = client.SaveModel(this.userModelFile); err != nil {
		log.Error(err)
		return NewError(LSV_ERR_TRAINING_FAILED, err.Error())
	}
	return nil
}

func (this *VPREngine) VerifyModel() error {
	if this.verifyBuf == nil || len(this.verifyBuf) <= 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	var buf []int16 = this.verifyBuf
	var length int64

	//buf = waveIO.DelSilence(this.verifyBuf, this.delSilRange)

	length = int64(len(buf))
	if length < this._minVerLen {
		return LSV_ERR_NEED_MORE_SAMPLE
	}

	var client *gmm.GMM = gmm.NewGMM()
	err := client.LoadModel(this.userModelFile)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MODEL_LOAD_FAILED, err.Error())
	}

	tmpubm := gmm.NewGMM()
	tmpubm.Copy(this.ubm)

	err = feature.Extract(buf, client)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	err = tmpubm.CopyFeatureData(client)
	if err != nil {
		log.Error(err)
		return NewError(LSV_ERR_MEM_INSUFFICIENT, err.Error())
	}

	var logClient, logWorld float64
	logClient = client.LProb(client.FeatureData, 0, int64(client.Frames))
	logWorld = tmpubm.LProb(tmpubm.FeatureData, 0, int64(tmpubm.Frames))
	this.score = (logClient - logWorld) / float64(client.Frames)
	return nil
}

func (this *VPREngine) AddTrainBuffer(buf []byte) error {
	if buf == nil || len(buf) == 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	sBuff := make([]int16, 0)
	length := len(buf)
	for ii := 0; ii < length-1; ii += 2 {
		cBuff16 := int16(buf[ii])
		cBuff16 |= int16(buf[ii+1]) << 8
		sBuff = append(sBuff, cBuff16)
	}

	if this.deleteSil {
		sBuff = waveIO.DelSilence(sBuff, this.delSilRange)
	}

	this.trainBuf = append(this.trainBuf, sBuff...)
	return nil
}

func (this *VPREngine) AddVerifyBuffer(buf []byte) error {
	if buf == nil || len(buf) == 0 {
		return LSV_ERR_NO_AVAILABLE_DATA
	}

	sBuff := make([]int16, 0)
	length := len(buf)
	for ii := 0; ii < length; ii += 2 {
		cBuff16 := int16(buf[ii])
		cBuff16 |= int16(buf[ii+1]) << 8
		sBuff = append(sBuff, cBuff16)
	}

	if this.deleteSil {
		sBuff = waveIO.DelSilence(sBuff, this.delSilRange)
	}

	this.verifyBuf = sBuff
	return nil
}

func (this *VPREngine) ClearTrainBuffer() {
	this.trainBuf = this.trainBuf[:0]
}

func (this *VPREngine) ClearVerifyBuffer() {
	this.verifyBuf = this.verifyBuf[:0]
}

func (this *VPREngine) ClearAllBuffer() {
	this.ClearTrainBuffer()
	this.ClearVerifyBuffer()
}

func (this *VPREngine) GetScore() float64 {
	return this.score
}
<|endoftext|>


<commit_before>package render

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"html/template"
	"net/http"
)

// Engine is the generic interface for all responses.
type Engine interface {
	Render(http.ResponseWriter, interface{}) error
}

// Head defines the basic ContentType and Status fields.
type Head struct {
	ContentType string
	Status      int
}

// XML built-in renderer.
type XML struct {
	Head
	Indent bool
	Prefix []byte
}

// JSON built-in renderer.
type JSON struct {
	Head
	Indent bool
	Prefix []byte
}

// JSON built-in renderer.
type JSONP struct {
	Head
	Indent bool
	Callback string
}

// HTML built-in renderer.
type HTML struct {
	Head
	Name      string
	Templates *template.Template
}

// Data built-in renderer.
type Data struct {
	Head
}

// Write outputs the header content.
func (h Head) Write(w http.ResponseWriter) {
	w.Header().Set(ContentType, h.ContentType)
	w.WriteHeader(h.Status)
}

// Render a data response.
func (d Data) Render(w http.ResponseWriter, v interface{}) error {
	c := w.Header().Get(ContentType)
	if c != "" {
		d.Head.ContentType = c
	}

	d.Head.Write(w)
	w.Write(v.([]byte))
	return nil
}

// Render a JSON response.
func (j JSON) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if j.Indent {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		return err
	}

	// JSON marshaled fine, write out the result.
	j.Head.Write(w)
	if len(j.Prefix) > 0 {
		w.Write(j.Prefix)
	}
	w.Write(result)
	return nil
}

// Render a JSONP response.
func (j JSONP) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if j.Indent {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		return err
	}

	// JSON marshaled fine, write out the result.
	j.Head.Write(w)
	w.Write([]byte(j.Callback + "("))
	w.Write(result)
	w.Write([]byte(");"))
	return nil
}

// Render an XML response.
func (x XML) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if x.Indent {
		result, err = xml.MarshalIndent(v, "", "  ")
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		return err
	}

	// XML marshaled fine, write out the result.
	x.Head.Write(w)
	if len(x.Prefix) > 0 {
		w.Write(x.Prefix)
	}
	w.Write(result)
	return nil
}

// Render a HTML response.
func (h HTML) Render(w http.ResponseWriter, binding interface{}) error {
	out := new(bytes.Buffer)
	err := h.Templates.ExecuteTemplate(out, h.Name, binding)
	if err != nil {
		return err
	}

	h.Head.Write(w)
	w.Write(out.Bytes())
	return nil
}
<commit_msg>fixing quick typo in comment 'JSON' -> 'JSONP'<commit_after>package render

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"html/template"
	"net/http"
)

// Engine is the generic interface for all responses.
type Engine interface {
	Render(http.ResponseWriter, interface{}) error
}

// Head defines the basic ContentType and Status fields.
type Head struct {
	ContentType string
	Status      int
}

// XML built-in renderer.
type XML struct {
	Head
	Indent bool
	Prefix []byte
}

// JSON built-in renderer.
type JSON struct {
	Head
	Indent bool
	Prefix []byte
}

// JSONP built-in renderer.
type JSONP struct {
	Head
	Indent bool
	Callback string
}

// HTML built-in renderer.
type HTML struct {
	Head
	Name      string
	Templates *template.Template
}

// Data built-in renderer.
type Data struct {
	Head
}

// Write outputs the header content.
func (h Head) Write(w http.ResponseWriter) {
	w.Header().Set(ContentType, h.ContentType)
	w.WriteHeader(h.Status)
}

// Render a data response.
func (d Data) Render(w http.ResponseWriter, v interface{}) error {
	c := w.Header().Get(ContentType)
	if c != "" {
		d.Head.ContentType = c
	}

	d.Head.Write(w)
	w.Write(v.([]byte))
	return nil
}

// Render a JSON response.
func (j JSON) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if j.Indent {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		return err
	}

	// JSON marshaled fine, write out the result.
	j.Head.Write(w)
	if len(j.Prefix) > 0 {
		w.Write(j.Prefix)
	}
	w.Write(result)
	return nil
}

// Render a JSONP response.
func (j JSONP) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if j.Indent {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		return err
	}

	// JSON marshaled fine, write out the result.
	j.Head.Write(w)
	w.Write([]byte(j.Callback + "("))
	w.Write(result)
	w.Write([]byte(");"))
	return nil
}

// Render an XML response.
func (x XML) Render(w http.ResponseWriter, v interface{}) error {
	var result []byte
	var err error

	if x.Indent {
		result, err = xml.MarshalIndent(v, "", "  ")
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		return err
	}

	// XML marshaled fine, write out the result.
	x.Head.Write(w)
	if len(x.Prefix) > 0 {
		w.Write(x.Prefix)
	}
	w.Write(result)
	return nil
}

// Render a HTML response.
func (h HTML) Render(w http.ResponseWriter, binding interface{}) error {
	out := new(bytes.Buffer)
	err := h.Templates.ExecuteTemplate(out, h.Name, binding)
	if err != nil {
		return err
	}

	h.Head.Write(w)
	w.Write(out.Bytes())
	return nil
}
<|endoftext|>


<commit_before>// Package dynamoBrain is a simple AWS DynamoDB implementation of the bot.SimpleBrain
// interface, which gives the robot a place to permanently store it's memories.
package dynamoBrain

import (
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
	"github.com/lnxjedi/gopherbot/bot"
)

var robot bot.Handler
var svc *dynamodb.DynamoDB

type brainConfig struct {
	TableName, Region, AccessKeyID, SecretAccessKey string
}

type dynaMemory struct {
	Memory  string
	Content []byte
}

var dynamocfg brainConfig

func (db *brainConfig) Store(k string, b *[]byte) error {
	input := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"Memory": {
				S: aws.String(k),
			},
			"Content": {
				B: *b,
			},
		},
		TableName: aws.String(dynamocfg.TableName),
	}

	_, err := svc.PutItem(input)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeConditionalCheckFailedException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error())
			case dynamodb.ErrCodeProvisionedThroughputExceededException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeItemCollectionSizeLimitExceededException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Error, "Error storing memory: %v", aerr.Error())
			}
			return aerr
		}
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		robot.Log(bot.Error, "Error storing memory: %v", err.Error())
		return err
	}

	return nil
}

func (db *brainConfig) Retrieve(k string) (datum *[]byte, exists bool, err error) {
	consistent := true
	result, err := svc.GetItem(&dynamodb.GetItemInput{
		TableName: aws.String(dynamocfg.TableName),
		Key: map[string]*dynamodb.AttributeValue{
			"Memory": {
				S: aws.String(k),
			},
		},
		ConsistentRead: &consistent,
	})

	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeProvisionedThroughputExceededException:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Error, "Error retrieving memory: %v", aerr.Error())
			}
			return nil, false, aerr
		}
		robot.Log(bot.Error, "Error retrieving memory: %v", err.Error())
		return nil, false, err
	}

	m := dynaMemory{}

	err = dynamodbattribute.UnmarshalMap(result.Item, &m)

	if err != nil {
		robot.Log(bot.Error, "Failed to unmarshal Record, %v", err)
		return nil, false, err
	}

	if m.Memory == "" {
		return nil, false, nil
	}

	return &m.Content, true, nil
}

func provider(r bot.Handler, _ *log.Logger) bot.SimpleBrain {
	robot = r
	robot.GetBrainConfig(&dynamocfg)
	var sess *session.Session
	var err error
	AccessKeyID := dynamocfg.AccessKeyID
	SecretAccessKey := dynamocfg.SecretAccessKey
	// ec2 provided credentials
	if len(AccessKeyID) == 0 {
		sess, err = session.NewSession(&aws.Config{
			Region: aws.String(dynamocfg.Region),
		})
		if err != nil {
			robot.Log(bot.Fatal, "Unable to establish AWS session: %v", err)
		}
	} else {
		sess, err = session.NewSession(&aws.Config{
			Region:      aws.String(dynamocfg.Region),
			Credentials: credentials.NewStaticCredentials(AccessKeyID, SecretAccessKey, ""),
		})
		if err != nil {
			robot.Log(bot.Fatal, "Unable to establish AWS session: %v", err)
		}
	}
	// Create DynamoDB client
	svc = dynamodb.New(sess)
	input := &dynamodb.DescribeTableInput{
		TableName: aws.String(dynamocfg.TableName),
	}
	_, err = svc.DescribeTable(input)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Fatal, "Error describing table '%s': %v, %v", dynamocfg.TableName, dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Fatal, "Error describing table '%s': %v, %v", dynamocfg.TableName, dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Fatal, "Error describing table '%s': %v", dynamocfg.TableName, aerr.Error())
			}
		} else {
			robot.Log(bot.Fatal, "Error describing table '%s': %v", dynamocfg.TableName, err.Error())
		}
	}

	return &dynamocfg
}

func init() {
	bot.RegisterSimpleBrain("dynamo", provider)
}
<commit_msg>No mixed-case package names (linting)<commit_after>// Package dynamobrain is a simple AWS DynamoDB implementation of the bot.SimpleBrain
// interface, which gives the robot a place to permanently store it's memories.
package dynamobrain

import (
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
	"github.com/lnxjedi/gopherbot/bot"
)

var robot bot.Handler
var svc *dynamodb.DynamoDB

type brainConfig struct {
	TableName, Region, AccessKeyID, SecretAccessKey string
}

type dynaMemory struct {
	Memory  string
	Content []byte
}

var dynamocfg brainConfig

func (db *brainConfig) Store(k string, b *[]byte) error {
	input := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"Memory": {
				S: aws.String(k),
			},
			"Content": {
				B: *b,
			},
		},
		TableName: aws.String(dynamocfg.TableName),
	}

	_, err := svc.PutItem(input)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeConditionalCheckFailedException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error())
			case dynamodb.ErrCodeProvisionedThroughputExceededException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeItemCollectionSizeLimitExceededException:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Error, "Error storing memory: %v, %v", dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Error, "Error storing memory: %v", aerr.Error())
			}
			return aerr
		}
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		robot.Log(bot.Error, "Error storing memory: %v", err.Error())
		return err
	}

	return nil
}

func (db *brainConfig) Retrieve(k string) (datum *[]byte, exists bool, err error) {
	consistent := true
	result, err := svc.GetItem(&dynamodb.GetItemInput{
		TableName: aws.String(dynamocfg.TableName),
		Key: map[string]*dynamodb.AttributeValue{
			"Memory": {
				S: aws.String(k),
			},
		},
		ConsistentRead: &consistent,
	})

	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeProvisionedThroughputExceededException:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Error, "Error retrieving memory: %v, %v", dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Error, "Error retrieving memory: %v", aerr.Error())
			}
			return nil, false, aerr
		}
		robot.Log(bot.Error, "Error retrieving memory: %v", err.Error())
		return nil, false, err
	}

	m := dynaMemory{}

	err = dynamodbattribute.UnmarshalMap(result.Item, &m)

	if err != nil {
		robot.Log(bot.Error, "Failed to unmarshal Record, %v", err)
		return nil, false, err
	}

	if m.Memory == "" {
		return nil, false, nil
	}

	return &m.Content, true, nil
}

func provider(r bot.Handler, _ *log.Logger) bot.SimpleBrain {
	robot = r
	robot.GetBrainConfig(&dynamocfg)
	var sess *session.Session
	var err error
	AccessKeyID := dynamocfg.AccessKeyID
	SecretAccessKey := dynamocfg.SecretAccessKey
	// ec2 provided credentials
	if len(AccessKeyID) == 0 {
		sess, err = session.NewSession(&aws.Config{
			Region: aws.String(dynamocfg.Region),
		})
		if err != nil {
			robot.Log(bot.Fatal, "Unable to establish AWS session: %v", err)
		}
	} else {
		sess, err = session.NewSession(&aws.Config{
			Region:      aws.String(dynamocfg.Region),
			Credentials: credentials.NewStaticCredentials(AccessKeyID, SecretAccessKey, ""),
		})
		if err != nil {
			robot.Log(bot.Fatal, "Unable to establish AWS session: %v", err)
		}
	}
	// Create DynamoDB client
	svc = dynamodb.New(sess)
	input := &dynamodb.DescribeTableInput{
		TableName: aws.String(dynamocfg.TableName),
	}
	_, err = svc.DescribeTable(input)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case dynamodb.ErrCodeResourceNotFoundException:
				robot.Log(bot.Fatal, "Error describing table '%s': %v, %v", dynamocfg.TableName, dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
			case dynamodb.ErrCodeInternalServerError:
				robot.Log(bot.Fatal, "Error describing table '%s': %v, %v", dynamocfg.TableName, dynamodb.ErrCodeInternalServerError, aerr.Error())
			default:
				robot.Log(bot.Fatal, "Error describing table '%s': %v", dynamocfg.TableName, aerr.Error())
			}
		} else {
			robot.Log(bot.Fatal, "Error describing table '%s': %v", dynamocfg.TableName, err.Error())
		}
	}

	return &dynamocfg
}

func init() {
	bot.RegisterSimpleBrain("dynamo", provider)
}
<|endoftext|>