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

package attribute

import (
	"bytes"
	"fmt"
	"sync"
	"time"

	"github.com/golang/glog"
	me "github.com/hashicorp/go-multierror"

	mixerpb "istio.io/api/mixer/v1"
	"istio.io/mixer/pkg/pool"
)

// MutableBag is a generic mechanism to read and write a set of attributes.
//
// Bags can be chained together in a parent/child relationship. A child bag
// represents a delta over a parent. By default a child looks identical to
// the parent. But as mutations occur to the child, the two start to diverge.
// Resetting a child makes it look identical to its parent again.
type MutableBag struct {
	parent Bag
	values map[string]interface{}
}

var mutableBags = sync.Pool{
	New: func() interface{} {
		return &MutableBag{
			values: make(map[string]interface{}),
		}
	},
}

// GetMutableBag returns an initialized bag.
//
// Bags can be chained in a parent/child relationship. You can pass nil if the
// bag has no parent.
//
// When you are done using the mutable bag, call the Done method to recycle it.
func GetMutableBag(parent Bag) *MutableBag {
	mb := mutableBags.Get().(*MutableBag)

	if parent == nil {
		mb.parent = empty
	} else {
		mb.parent = parent
	}

	return mb
}

// CopyBag makes a deep copy of a bag.
func CopyBag(b Bag) *MutableBag {
	mb := GetMutableBag(nil)
	for _, k := range b.Names() {
		v, _ := b.Get(k)
		mb.Set(k, copyValue(v))
	}

	return mb
}

// Given an attribute value, create a deep copy of it
func copyValue(v interface{}) interface{} {
	switch t := v.(type) {
	case []byte:
		c := make([]byte, len(t))
		copy(c, t)
		return c

	case map[string]string:
		c := make(map[string]string, len(t))
		for k2, v2 := range t {
			c[k2] = v2
		}
		return c
	}

	return v
}

// Done indicates the bag can be reclaimed.
func (mb *MutableBag) Done() {
	// prevent use of a bag that's in the pool
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	mb.parent = nil
	mb.Reset()
	mutableBags.Put(mb)
}

// Get returns an attribute value.
func (mb *MutableBag) Get(name string) (interface{}, bool) {
	// prevent use of a bag that's in the pool
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	var r interface{}
	var b bool
	if r, b = mb.values[name]; !b {
		r, b = mb.parent.Get(name)
	}
	return r, b
}

// Names returns the names of all the attributes known to this bag.
func (mb *MutableBag) Names() []string {
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	parentNames := mb.parent.Names()

	m := make(map[string]bool, len(parentNames)+len(mb.values))
	for _, name := range parentNames {
		m[name] = true
	}

	for name := range mb.values {
		m[name] = true
	}

	i := 0
	names := make([]string, len(m))
	for name := range m {
		names[i] = name
		i++
	}

	return names
}

// Set creates an override for a named attribute.
func (mb *MutableBag) Set(name string, value interface{}) {
	mb.values[name] = value
}

// Reset removes all local state.
func (mb *MutableBag) Reset() {
	// my kingdom for a clear method on maps!
	for k := range mb.values {
		delete(mb.values, k)
	}
}

// Merge combines an array of bags into the current bag.
//
// The individual bags may not contain any conflicting attribute
// values. If that happens, then the merge fails and no mutation
// will have occurred to the current bag.
func (mb *MutableBag) Merge(bags ...*MutableBag) error {
	// first step is to make sure there are no redundant definitions of the same attribute
	keys := make(map[string]bool)
	for _, bag := range bags {
		if bag == nil {
			continue
		}
		for k := range bag.values {
			if keys[k] {
				return fmt.Errorf("conflicting value for attribute %s", k)
			}
			keys[k] = true
		}
	}

	// now that we know there are no conflicting definitions, do the actual merging...
	for _, bag := range bags {
		if bag == nil {
			continue
		}
		for k, v := range bag.values {
			mb.values[k] = copyValue(v)
		}
	}

	return nil
}

// ToProto fills-in an Attributes proto based on the content of the bag.
func (mb *MutableBag) ToProto(output *mixerpb.Attributes, globalDict map[string]int32, globalWordCount int) {
	ds := newDictState(globalDict, globalWordCount)

	for k, v := range mb.values {
		index := ds.assignDictIndex(k)

		switch t := v.(type) {
		case string:
			if output.Strings == nil {
				output.Strings = make(map[int32]int32)
			}
			output.Strings[index] = ds.assignDictIndex(t)

		case int64:
			if output.Int64S == nil {
				output.Int64S = make(map[int32]int64)
			}
			output.Int64S[index] = t

		case float64:
			if output.Doubles == nil {
				output.Doubles = make(map[int32]float64)
			}
			output.Doubles[index] = t

		case bool:
			if output.Bools == nil {
				output.Bools = make(map[int32]bool)
			}
			output.Bools[index] = t

		case time.Time:
			if output.Timestamps == nil {
				output.Timestamps = make(map[int32]time.Time)
			}
			output.Timestamps[index] = t

		case time.Duration:
			if output.Durations == nil {
				output.Durations = make(map[int32]time.Duration)
			}
			output.Durations[index] = t

		case []byte:
			if output.Bytes == nil {
				output.Bytes = make(map[int32][]byte)
			}
			output.Bytes[index] = t

		case map[string]string:
			sm := make(map[int32]int32, len(t))
			for smk, smv := range t {
				sm[ds.assignDictIndex(smk)] = ds.assignDictIndex(smv)
			}

			if output.StringMaps == nil {
				output.StringMaps = make(map[int32]mixerpb.StringMap)
			}
			output.StringMaps[index] = mixerpb.StringMap{Entries: sm}
		}
	}

	output.Words = ds.getMessageWordList()
}

// GetBagFromProto returns an initialized bag from an Attribute proto.
func GetBagFromProto(attrs *mixerpb.Attributes, globalWordList []string) (*MutableBag, error) {
	mb := GetMutableBag(nil)
	err := mb.UpdateBagFromProto(attrs, globalWordList)
	if err != nil {
		mb.Done()
		return nil, err
	}

	return mb, nil
}

// UpdateBagFromProto refreshes the bag based on the content of the attribute proto.
//
// Note that in the case of semantic errors in the supplied proto which leads to
// an error return, it's likely that the bag will have been partially updated.
func (mb *MutableBag) UpdateBagFromProto(attrs *mixerpb.Attributes, globalWordList []string) error {
	messageWordList := attrs.Words
	var e error
	var name string
	var value string

	// TODO: fail if the proto carries multiple attributes by the same name (but different types)

	var buf *bytes.Buffer
	log := func(format string, args ...interface{}) {}

	if glog.V(2) {
		buf = pool.GetBuffer()
		log = func(format string, args ...interface{}) {
			fmt.Fprintf(buf, format, args...)
			buf.WriteString("\n")
		}
	}

	log("Updating bag from wire attributes:")

	log("  setting string attributes:")
	for k, v := range attrs.Strings {
		name, e = lookup(k, e, globalWordList, messageWordList)
		value, e = lookup(v, e, globalWordList, messageWordList)
		log("    %s -> '%s'", name, value)
		mb.values[name] = value
	}

	log("  setting int64 attributes:")
	for k, v := range attrs.Int64S {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%d'", name, v)
		mb.values[name] = v
	}

	log("  setting double attributes:")
	for k, v := range attrs.Doubles {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%f'", name, v)
		mb.values[name] = v
	}

	log("  setting bool attributes:")
	for k, v := range attrs.Bools {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%t'", name, v)
		mb.values[name] = v
	}

	log("  setting timestamp attributes:")
	for k, v := range attrs.Timestamps {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%v'", name, v)
		mb.values[name] = v
	}

	log("  setting duration attributes:")
	for k, v := range attrs.Durations {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%v'", name, v)
		mb.values[name] = v
	}

	log("  setting bytes attributes:")
	for k, v := range attrs.Bytes {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%s'", name, v)
		mb.values[name] = v
	}

	log("  setting string map attributes:")
	for k, v := range attrs.StringMaps {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("  %s", name)

		sm := make(map[string]string, len(v.Entries))
		for k2, v2 := range v.Entries {
			var name2 string
			var value2 string
			name2, e = lookup(k2, e, globalWordList, messageWordList)
			value2, e = lookup(v2, e, globalWordList, messageWordList)
			log("    %s -> '%v'", name2, value2)
			sm[name2] = value2
		}
		mb.values[name] = sm
	}

	if buf != nil {
		glog.Info(buf.String())
		pool.PutBuffer(buf)
	}

	return e
}

func lookup(index int32, err error, globalWordList []string, messageWordList []string) (string, error) {
	if index < 0 {
		slot := indexToSlot(index)
		if slot < len(messageWordList) {
			return messageWordList[slot], err
		}
	} else if index < int32(len(globalWordList)) {
		return globalWordList[index], err
	}

	return "", me.Append(err, fmt.Errorf("attribute index %d is not defined in the available dictionaries", index))
}
<commit_msg>Adapter 2 dispatch: Resolver (#1109)<commit_after>// Copyright 2016 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package attribute

import (
	"bytes"
	"fmt"
	"sync"
	"time"

	"github.com/golang/glog"
	me "github.com/hashicorp/go-multierror"

	mixerpb "istio.io/api/mixer/v1"
	"istio.io/mixer/pkg/pool"
)

// MutableBag is a generic mechanism to read and write a set of attributes.
//
// Bags can be chained together in a parent/child relationship. A child bag
// represents a delta over a parent. By default a child looks identical to
// the parent. But as mutations occur to the child, the two start to diverge.
// Resetting a child makes it look identical to its parent again.
type MutableBag struct {
	parent Bag
	values map[string]interface{}
}

var mutableBags = sync.Pool{
	New: func() interface{} {
		return &MutableBag{
			values: make(map[string]interface{}),
		}
	},
}

// GetMutableBag returns an initialized bag.
//
// Bags can be chained in a parent/child relationship. You can pass nil if the
// bag has no parent.
//
// When you are done using the mutable bag, call the Done method to recycle it.
func GetMutableBag(parent Bag) *MutableBag {
	mb := mutableBags.Get().(*MutableBag)

	if parent == nil {
		mb.parent = empty
	} else {
		mb.parent = parent
	}

	return mb
}

// GetFakeMutableBagForTesting returns a Mutable bag based on the specified map
// Use this function only for testing purposes.
func GetFakeMutableBagForTesting(v map[string]interface{}) *MutableBag {
	m := GetMutableBag(nil)
	m.values = v
	return m
}

// CopyBag makes a deep copy of a bag.
func CopyBag(b Bag) *MutableBag {
	mb := GetMutableBag(nil)
	for _, k := range b.Names() {
		v, _ := b.Get(k)
		mb.Set(k, copyValue(v))
	}

	return mb
}

// Given an attribute value, create a deep copy of it
func copyValue(v interface{}) interface{} {
	switch t := v.(type) {
	case []byte:
		c := make([]byte, len(t))
		copy(c, t)
		return c

	case map[string]string:
		c := make(map[string]string, len(t))
		for k2, v2 := range t {
			c[k2] = v2
		}
		return c
	}

	return v
}

// Done indicates the bag can be reclaimed.
func (mb *MutableBag) Done() {
	// prevent use of a bag that's in the pool
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	mb.parent = nil
	mb.Reset()
	mutableBags.Put(mb)
}

// Get returns an attribute value.
func (mb *MutableBag) Get(name string) (interface{}, bool) {
	// prevent use of a bag that's in the pool
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	var r interface{}
	var b bool
	if r, b = mb.values[name]; !b {
		r, b = mb.parent.Get(name)
	}
	return r, b
}

// Names returns the names of all the attributes known to this bag.
func (mb *MutableBag) Names() []string {
	if mb.parent == nil {
		panic(fmt.Errorf("attempt to use a bag after its Done method has been called"))
	}

	parentNames := mb.parent.Names()

	m := make(map[string]bool, len(parentNames)+len(mb.values))
	for _, name := range parentNames {
		m[name] = true
	}

	for name := range mb.values {
		m[name] = true
	}

	i := 0
	names := make([]string, len(m))
	for name := range m {
		names[i] = name
		i++
	}

	return names
}

// Set creates an override for a named attribute.
func (mb *MutableBag) Set(name string, value interface{}) {
	mb.values[name] = value
}

// Reset removes all local state.
func (mb *MutableBag) Reset() {
	// my kingdom for a clear method on maps!
	for k := range mb.values {
		delete(mb.values, k)
	}
}

// Merge combines an array of bags into the current bag.
//
// The individual bags may not contain any conflicting attribute
// values. If that happens, then the merge fails and no mutation
// will have occurred to the current bag.
func (mb *MutableBag) Merge(bags ...*MutableBag) error {
	// first step is to make sure there are no redundant definitions of the same attribute
	keys := make(map[string]bool)
	for _, bag := range bags {
		if bag == nil {
			continue
		}
		for k := range bag.values {
			if keys[k] {
				return fmt.Errorf("conflicting value for attribute %s", k)
			}
			keys[k] = true
		}
	}

	// now that we know there are no conflicting definitions, do the actual merging...
	for _, bag := range bags {
		if bag == nil {
			continue
		}
		for k, v := range bag.values {
			mb.values[k] = copyValue(v)
		}
	}

	return nil
}

// ToProto fills-in an Attributes proto based on the content of the bag.
func (mb *MutableBag) ToProto(output *mixerpb.Attributes, globalDict map[string]int32, globalWordCount int) {
	ds := newDictState(globalDict, globalWordCount)

	for k, v := range mb.values {
		index := ds.assignDictIndex(k)

		switch t := v.(type) {
		case string:
			if output.Strings == nil {
				output.Strings = make(map[int32]int32)
			}
			output.Strings[index] = ds.assignDictIndex(t)

		case int64:
			if output.Int64S == nil {
				output.Int64S = make(map[int32]int64)
			}
			output.Int64S[index] = t

		case float64:
			if output.Doubles == nil {
				output.Doubles = make(map[int32]float64)
			}
			output.Doubles[index] = t

		case bool:
			if output.Bools == nil {
				output.Bools = make(map[int32]bool)
			}
			output.Bools[index] = t

		case time.Time:
			if output.Timestamps == nil {
				output.Timestamps = make(map[int32]time.Time)
			}
			output.Timestamps[index] = t

		case time.Duration:
			if output.Durations == nil {
				output.Durations = make(map[int32]time.Duration)
			}
			output.Durations[index] = t

		case []byte:
			if output.Bytes == nil {
				output.Bytes = make(map[int32][]byte)
			}
			output.Bytes[index] = t

		case map[string]string:
			sm := make(map[int32]int32, len(t))
			for smk, smv := range t {
				sm[ds.assignDictIndex(smk)] = ds.assignDictIndex(smv)
			}

			if output.StringMaps == nil {
				output.StringMaps = make(map[int32]mixerpb.StringMap)
			}
			output.StringMaps[index] = mixerpb.StringMap{Entries: sm}
		}
	}

	output.Words = ds.getMessageWordList()
}

// GetBagFromProto returns an initialized bag from an Attribute proto.
func GetBagFromProto(attrs *mixerpb.Attributes, globalWordList []string) (*MutableBag, error) {
	mb := GetMutableBag(nil)
	err := mb.UpdateBagFromProto(attrs, globalWordList)
	if err != nil {
		mb.Done()
		return nil, err
	}

	return mb, nil
}

// UpdateBagFromProto refreshes the bag based on the content of the attribute proto.
//
// Note that in the case of semantic errors in the supplied proto which leads to
// an error return, it's likely that the bag will have been partially updated.
func (mb *MutableBag) UpdateBagFromProto(attrs *mixerpb.Attributes, globalWordList []string) error {
	messageWordList := attrs.Words
	var e error
	var name string
	var value string

	// TODO: fail if the proto carries multiple attributes by the same name (but different types)

	var buf *bytes.Buffer
	log := func(format string, args ...interface{}) {}

	if glog.V(2) {
		buf = pool.GetBuffer()
		log = func(format string, args ...interface{}) {
			fmt.Fprintf(buf, format, args...)
			buf.WriteString("\n")
		}
	}

	log("Updating bag from wire attributes:")

	log("  setting string attributes:")
	for k, v := range attrs.Strings {
		name, e = lookup(k, e, globalWordList, messageWordList)
		value, e = lookup(v, e, globalWordList, messageWordList)
		log("    %s -> '%s'", name, value)
		mb.values[name] = value
	}

	log("  setting int64 attributes:")
	for k, v := range attrs.Int64S {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%d'", name, v)
		mb.values[name] = v
	}

	log("  setting double attributes:")
	for k, v := range attrs.Doubles {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%f'", name, v)
		mb.values[name] = v
	}

	log("  setting bool attributes:")
	for k, v := range attrs.Bools {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%t'", name, v)
		mb.values[name] = v
	}

	log("  setting timestamp attributes:")
	for k, v := range attrs.Timestamps {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%v'", name, v)
		mb.values[name] = v
	}

	log("  setting duration attributes:")
	for k, v := range attrs.Durations {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%v'", name, v)
		mb.values[name] = v
	}

	log("  setting bytes attributes:")
	for k, v := range attrs.Bytes {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("    %s -> '%s'", name, v)
		mb.values[name] = v
	}

	log("  setting string map attributes:")
	for k, v := range attrs.StringMaps {
		name, e = lookup(k, e, globalWordList, messageWordList)
		log("  %s", name)

		sm := make(map[string]string, len(v.Entries))
		for k2, v2 := range v.Entries {
			var name2 string
			var value2 string
			name2, e = lookup(k2, e, globalWordList, messageWordList)
			value2, e = lookup(v2, e, globalWordList, messageWordList)
			log("    %s -> '%v'", name2, value2)
			sm[name2] = value2
		}
		mb.values[name] = sm
	}

	if buf != nil {
		glog.Info(buf.String())
		pool.PutBuffer(buf)
	}

	return e
}

func lookup(index int32, err error, globalWordList []string, messageWordList []string) (string, error) {
	if index < 0 {
		slot := indexToSlot(index)
		if slot < len(messageWordList) {
			return messageWordList[slot], err
		}
	} else if index < int32(len(globalWordList)) {
		return globalWordList[index], err
	}

	return "", me.Append(err, fmt.Errorf("attribute index %d is not defined in the available dictionaries", index))
}
<|endoftext|>


<commit_before>package main

import (
    "net/http"
    "github.com/apexskier/httpauth"
    "github.com/gorilla/mux"
    "fmt"
)

var (
    backend goauth.GobFileAuthBackend
    aaa goauth.Authorizer
)

func main() {
    backend = goauth.NewGobFileAuthBackend("auth.gob")
    aaa = goauth.NewAuthorizer(backend, []byte("cookie-encryption-key"))

    // set up routers and route handlers
    r := mux.NewRouter()
    r.HandleFunc("/login", getLogin).Methods("GET")
    r.HandleFunc("/register", postRegister).Methods("POST")
    r.HandleFunc("/login", postLogin).Methods("POST")
    r.HandleFunc("/change", postChange).Methods("POST")
    r.HandleFunc("/", handlePage).Methods("GET") // authorized page
    r.HandleFunc("/logout", handleLogout)

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

func getLogin(rw http.ResponseWriter, req *http.Request) {
    messages := aaa.Messages(rw, req)
    fmt.Fprintf(rw, `

        <title>Login</title>

Goauth example

Entry Page

Messages: %v

Login

        <form action="/login" method="post" id="login">
            <input type="text" name="username" placeholder="username">

            <input type="password" name="password" placeholder="password">

            <button type="submit">Login</button>
        </form>

Register

        <form action="/register" method="post" id="register">
            <input type="text" name="username" placeholder="username">

            <input type="password" name="password" placeholder="password">

            <input type="email" name="email" placeholder="email@example.com">

            <button type="submit">Register</button>
        </form>

        `, messages)
}

func postLogin(rw http.ResponseWriter, req *http.Request) {
    username := req.PostFormValue("username")
    password := req.PostFormValue("password")
    if err := aaa.Login(rw, req, username, password, "/"); err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
    }
}

func postRegister(rw http.ResponseWriter, req *http.Request) {
    username := req.PostFormValue("username")
    password := req.PostFormValue("password")
    email := req.PostFormValue("email")
    if err := aaa.Register(rw, req, username, password, email); err == nil {
        postLogin(rw, req)
    } else {
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
    }
}

func postChange(rw http.ResponseWriter, req *http.Request) {
    email := req.PostFormValue("new_email")
    aaa.Update(rw, req, "", email)
    http.Redirect(rw, req, "/", http.StatusSeeOther)
}

func handlePage(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.Authorize(rw, req, true); err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
        return
    }
    if user, ok := aaa.CurrentUser(rw, req); ok {
        fmt.Fprintf(rw, `

            <title>Secret page</title>

Goauth example

Hello %v

Your email is %v. Logout

                <form action="/change" method="post" id="change">

Change email

<input type="email" name="new_email" placeholder="new email">

                    <button type="submit">Submit</button>
                </form>

            `, user.Username, user.Email)
    }
}

func handleLogout(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.Logout(rw, req); err != nil {
        fmt.Println(err)
        // this shouldn't happen
        return
    }
    http.Redirect(rw, req, "/logout", http.StatusSeeOther)
}

<commit_msg>Update example code to use correct package name.<commit_after>package main

import (
    "net/http"
    "github.com/apexskier/httpauth"
    "github.com/gorilla/mux"
    "fmt"
)

var (
    backend httpauth.GobFileAuthBackend
    aaa httpauth.Authorizer
)

func main() {
    backend = httpauth.NewGobFileAuthBackend("auth.gob")
    aaa = httpauth.NewAuthorizer(backend, []byte("cookie-encryption-key"))

    // set up routers and route handlers
    r := mux.NewRouter()
    r.HandleFunc("/login", getLogin).Methods("GET")
    r.HandleFunc("/register", postRegister).Methods("POST")
    r.HandleFunc("/login", postLogin).Methods("POST")
    r.HandleFunc("/change", postChange).Methods("POST")
    r.HandleFunc("/", handlePage).Methods("GET") // authorized page
    r.HandleFunc("/logout", handleLogout)

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

func getLogin(rw http.ResponseWriter, req *http.Request) {
    messages := aaa.Messages(rw, req)
    fmt.Fprintf(rw, `

        <title>Login</title>

Httpauth example

Entry Page

Messages: %v

Login

        <form action="/login" method="post" id="login">
            <input type="text" name="username" placeholder="username">

            <input type="password" name="password" placeholder="password">

            <button type="submit">Login</button>
        </form>

Register

        <form action="/register" method="post" id="register">
            <input type="text" name="username" placeholder="username">

            <input type="password" name="password" placeholder="password">

            <input type="email" name="email" placeholder="email@example.com">

            <button type="submit">Register</button>
        </form>

        `, messages)
}

func postLogin(rw http.ResponseWriter, req *http.Request) {
    username := req.PostFormValue("username")
    password := req.PostFormValue("password")
    if err := aaa.Login(rw, req, username, password, "/"); err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
    }
}

func postRegister(rw http.ResponseWriter, req *http.Request) {
    username := req.PostFormValue("username")
    password := req.PostFormValue("password")
    email := req.PostFormValue("email")
    if err := aaa.Register(rw, req, username, password, email); err == nil {
        postLogin(rw, req)
    } else {
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
    }
}

func postChange(rw http.ResponseWriter, req *http.Request) {
    email := req.PostFormValue("new_email")
    aaa.Update(rw, req, "", email)
    http.Redirect(rw, req, "/", http.StatusSeeOther)
}

func handlePage(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.Authorize(rw, req, true); err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
        return
    }
    if user, ok := aaa.CurrentUser(rw, req); ok {
        fmt.Fprintf(rw, `

            <title>Secret page</title>

Httpauth example

Hello %v

Your email is %v. Logout

                <form action="/change" method="post" id="change">

Change email

<input type="email" name="new_email" placeholder="new email">

                    <button type="submit">Submit</button>
                </form>

            `, user.Username, user.Email)
    }
}

func handleLogout(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.Logout(rw, req); err != nil {
        fmt.Println(err)
        // this shouldn't happen
        return
    }
    http.Redirect(rw, req, "/logout", http.StatusSeeOther)
}

<|endoftext|>


<commit_before>package veneur

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"sync"

	"github.com/sirupsen/logrus"
	flock "github.com/theckman/go-flock"
)

// StartStatsd spawns a goroutine that listens for metrics in statsd
// format on the address a, and returns the concrete listening
// address. As this is a setup routine, if any error occurs, it
// panics.
func StartStatsd(s *Server, a net.Addr, packetPool *sync.Pool) net.Addr {
	switch addr := a.(type) {
	case *net.UDPAddr:
		return startStatsdUDP(s, addr, packetPool)
	case *net.TCPAddr:
		return startStatsdTCP(s, addr, packetPool)
	default:
		panic(fmt.Sprintf("Can't listen on %v: only TCP and UDP are supported", a))
	}
}

func startStatsdUDP(s *Server, addr *net.UDPAddr, packetPool *sync.Pool) net.Addr {
	reusePort := s.numReaders != 1
	// If we're reusing the port, make sure we're listening on the
	// exact same address always; this is mostly relevant for
	// tests, where port is typically 0 and the initial ListenUDP
	// call results in a contrete port.
	if reusePort {
		sock, err := NewSocket(addr, s.RcvbufBytes, reusePort)
		if err != nil {
			panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
		}
		addr = sock.LocalAddr().(*net.UDPAddr)
	}
	addrChan := make(chan net.Addr, 1)
	once := sync.Once{}
	for i := 0; i < s.numReaders; i++ {
		go func() {
			defer func() {
				ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
			}()
			// each goroutine gets its own socket
			// if the sockets support SO_REUSEPORT, then this will cause the
			// kernel to distribute datagrams across them, for better read
			// performance
			sock, err := NewSocket(addr, s.RcvbufBytes, s.numReaders != 1)
			if err != nil {
				// if any goroutine fails to create the socket, we can't really
				// recover, so we just blow up
				// this probably indicates a systemic issue, eg lack of
				// SO_REUSEPORT support
				panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
			}
			once.Do(func() {
				addrChan <- sock.LocalAddr()
				log.WithField("address", sock.LocalAddr()).
					Info("Listening for statsd metrics on UDP socket")
				close(addrChan)
			})

			s.ReadMetricSocket(sock, packetPool)
		}()
	}
	return <-addrChan
}

func startStatsdTCP(s *Server, addr *net.TCPAddr, packetPool *sync.Pool) net.Addr {
	var listener net.Listener
	var err error

	listener, err = net.ListenTCP("tcp", addr)
	if err != nil {
		panic(fmt.Sprintf("couldn't listen on TCP socket %v: %v", addr, err))
	}

	go func() {
		<-s.shutdown
		// TODO: the socket is in use until there are no goroutines blocked in Accept
		// we should wait until the accepting goroutine exits
		err := listener.Close()
		if err != nil {
			log.WithError(err).Warn("Ignoring error closing TCP listener")
		}
	}()

	mode := "unencrypted"
	if s.tlsConfig != nil {
		// wrap the listener with TLS
		listener = tls.NewListener(listener, s.tlsConfig)
		if s.tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
			mode = "authenticated"
		} else {
			mode = "encrypted"
		}
	}

	log.WithFields(logrus.Fields{
		"address": addr, "mode": mode,
	}).Info("Listening for statsd metrics on TCP socket")

	go func() {
		defer func() {
			ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
		}()
		s.ReadTCPSocket(listener)
	}()
	return listener.Addr()
}

// StartSSF starts listening for SSF on an address a, and returns the
// concrete address that the server is listening on.
func StartSSF(s *Server, a net.Addr, tracePool *sync.Pool) net.Addr {
	switch addr := a.(type) {
	case *net.UDPAddr:
		a = startSSFUDP(s, addr, tracePool)
	case *net.UnixAddr:
		_, a = startSSFUnix(s, addr)
	default:
		panic(fmt.Sprintf("Can't listen for SSF on %v: only udp:// & unix:// are supported", a))
	}
	log.WithFields(logrus.Fields{
		"address": a.String(),
		"network": a.Network(),
	}).Info("Listening for SSF traces")
	return a
}

func startSSFUDP(s *Server, addr *net.UDPAddr, tracePool *sync.Pool) net.Addr {
	// TODO: Make this actually use readers / add a predicate
	// function for testing if we should SO_REUSEPORT.
	listener, err := NewSocket(addr, s.RcvbufBytes, s.numReaders > 1)
	if err != nil {
		// if any goroutine fails to create the socket, we can't really
		// recover, so we just blow up
		// this probably indicates a systemic issue, eg lack of
		// SO_REUSEPORT support
		panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
	}
	go func() {
		defer func() {
			ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
		}()
		s.ReadSSFPacketSocket(listener, tracePool)
	}()
	return listener.LocalAddr()
}

// startSSFUnix starts listening for connections that send framed SSF
// spans on a UNIX domain socket address. It does so until the
// server's shutdown socket is closed. startSSFUnix returns a channel
// that is closed once the listener has terminated.
func startSSFUnix(s *Server, addr *net.UnixAddr) (<-chan struct{}, net.Addr) {
	done := make(chan struct{})
	if addr.Network() != "unix" {
		panic(fmt.Sprintf("Can't listen for SSF on %v: only udp:// and unix:// addresses are supported", addr))
	}
	// ensure we are the only ones locking this socket:
	lockname := fmt.Sprintf("%s.lock", addr.String())
	lock := flock.NewFlock(lockname)
	locked, err := lock.TryLock()
	if err != nil {
		panic(fmt.Sprintf("Could not acquire the lock %q to listen on %v: %v", lockname, addr, err))
	}
	if !locked {
		panic(fmt.Sprintf("Lock file %q for %v is in use by another process already", lockname, addr))
	}
	// We have the exclusive use of the socket, clear away any old sockets and listen:
	_ = os.Remove(addr.String())
	listener, err := net.ListenUnix(addr.Network(), addr)
	if err != nil {
		panic(fmt.Sprintf("Couldn't listen on UNIX socket %v: %v", addr, err))
	}

	// Make the socket connectable by everyone with access to the socket pathname:
	err = os.Chmod(addr.String(), 0666)
	if err != nil {
		panic(fmt.Sprintf("Couldn't set permissions on %v: %v", addr, err))
	}

	go func() {
		conns := make(chan net.Conn)
		go func() {
			defer func() {
				lock.Unlock()
				close(done)
			}()
			for {
				conn, err := listener.AcceptUnix()
				if err != nil {
					select {
					case <-s.shutdown:
						// occurs when cleanly shutting down the server e.g. in tests; ignore errors
						log.WithError(err).Info("Ignoring Accept error while shutting down")
						return
					default:
						log.WithError(err).Fatal("Unix accept failed")
					}
				}
				conns <- conn
			}
		}()
		for {
			select {
			case conn := <-conns:
				go s.ReadSSFStreamSocket(conn)
			case <-s.shutdown:
				listener.Close()
				return
			}
		}
	}()
	return done, listener.Addr()
}
<commit_msg>Document the UDP listener's address-passing scheme some<commit_after>package veneur

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"sync"

	"github.com/sirupsen/logrus"
	flock "github.com/theckman/go-flock"
)

// StartStatsd spawns a goroutine that listens for metrics in statsd
// format on the address a, and returns the concrete listening
// address. As this is a setup routine, if any error occurs, it
// panics.
func StartStatsd(s *Server, a net.Addr, packetPool *sync.Pool) net.Addr {
	switch addr := a.(type) {
	case *net.UDPAddr:
		return startStatsdUDP(s, addr, packetPool)
	case *net.TCPAddr:
		return startStatsdTCP(s, addr, packetPool)
	default:
		panic(fmt.Sprintf("Can't listen on %v: only TCP and UDP are supported", a))
	}
}

func startStatsdUDP(s *Server, addr *net.UDPAddr, packetPool *sync.Pool) net.Addr {
	reusePort := s.numReaders != 1
	// If we're reusing the port, make sure we're listening on the
	// exact same address always; this is mostly relevant for
	// tests, where port is typically 0 and the initial ListenUDP
	// call results in a contrete port.
	if reusePort {
		sock, err := NewSocket(addr, s.RcvbufBytes, reusePort)
		defer sock.Close()
		if err != nil {
			panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
		}
		addr = sock.LocalAddr().(*net.UDPAddr)
	}
	addrChan := make(chan net.Addr, 1)
	once := sync.Once{}
	for i := 0; i < s.numReaders; i++ {
		go func() {
			defer func() {
				ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
			}()
			// each goroutine gets its own socket
			// if the sockets support SO_REUSEPORT, then this will cause the
			// kernel to distribute datagrams across them, for better read
			// performance
			sock, err := NewSocket(addr, s.RcvbufBytes, reusePort)
			if err != nil {
				// if any goroutine fails to create the socket, we can't really
				// recover, so we just blow up
				// this probably indicates a systemic issue, eg lack of
				// SO_REUSEPORT support
				panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
			}
			// Pass the address that we are listening on
			// back to whoever spawned this goroutine so
			// it can return that address.
			once.Do(func() {
				addrChan <- sock.LocalAddr()
				log.WithField("address", sock.LocalAddr()).
					Info("Listening for statsd metrics on UDP socket")
				close(addrChan)
			})

			s.ReadMetricSocket(sock, packetPool)
		}()
	}
	return <-addrChan
}

func startStatsdTCP(s *Server, addr *net.TCPAddr, packetPool *sync.Pool) net.Addr {
	var listener net.Listener
	var err error

	listener, err = net.ListenTCP("tcp", addr)
	if err != nil {
		panic(fmt.Sprintf("couldn't listen on TCP socket %v: %v", addr, err))
	}

	go func() {
		<-s.shutdown
		// TODO: the socket is in use until there are no goroutines blocked in Accept
		// we should wait until the accepting goroutine exits
		err := listener.Close()
		if err != nil {
			log.WithError(err).Warn("Ignoring error closing TCP listener")
		}
	}()

	mode := "unencrypted"
	if s.tlsConfig != nil {
		// wrap the listener with TLS
		listener = tls.NewListener(listener, s.tlsConfig)
		if s.tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
			mode = "authenticated"
		} else {
			mode = "encrypted"
		}
	}

	log.WithFields(logrus.Fields{
		"address": addr, "mode": mode,
	}).Info("Listening for statsd metrics on TCP socket")

	go func() {
		defer func() {
			ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
		}()
		s.ReadTCPSocket(listener)
	}()
	return listener.Addr()
}

// StartSSF starts listening for SSF on an address a, and returns the
// concrete address that the server is listening on.
func StartSSF(s *Server, a net.Addr, tracePool *sync.Pool) net.Addr {
	switch addr := a.(type) {
	case *net.UDPAddr:
		a = startSSFUDP(s, addr, tracePool)
	case *net.UnixAddr:
		_, a = startSSFUnix(s, addr)
	default:
		panic(fmt.Sprintf("Can't listen for SSF on %v: only udp:// & unix:// are supported", a))
	}
	log.WithFields(logrus.Fields{
		"address": a.String(),
		"network": a.Network(),
	}).Info("Listening for SSF traces")
	return a
}

func startSSFUDP(s *Server, addr *net.UDPAddr, tracePool *sync.Pool) net.Addr {
	// TODO: Make this actually use readers / add a predicate
	// function for testing if we should SO_REUSEPORT.
	listener, err := NewSocket(addr, s.RcvbufBytes, s.numReaders > 1)
	if err != nil {
		// if any goroutine fails to create the socket, we can't really
		// recover, so we just blow up
		// this probably indicates a systemic issue, eg lack of
		// SO_REUSEPORT support
		panic(fmt.Sprintf("couldn't listen on UDP socket %v: %v", addr, err))
	}
	go func() {
		defer func() {
			ConsumePanic(s.Sentry, s.Statsd, s.Hostname, recover())
		}()
		s.ReadSSFPacketSocket(listener, tracePool)
	}()
	return listener.LocalAddr()
}

// startSSFUnix starts listening for connections that send framed SSF
// spans on a UNIX domain socket address. It does so until the
// server's shutdown socket is closed. startSSFUnix returns a channel
// that is closed once the listener has terminated.
func startSSFUnix(s *Server, addr *net.UnixAddr) (<-chan struct{}, net.Addr) {
	done := make(chan struct{})
	if addr.Network() != "unix" {
		panic(fmt.Sprintf("Can't listen for SSF on %v: only udp:// and unix:// addresses are supported", addr))
	}
	// ensure we are the only ones locking this socket:
	lockname := fmt.Sprintf("%s.lock", addr.String())
	lock := flock.NewFlock(lockname)
	locked, err := lock.TryLock()
	if err != nil {
		panic(fmt.Sprintf("Could not acquire the lock %q to listen on %v: %v", lockname, addr, err))
	}
	if !locked {
		panic(fmt.Sprintf("Lock file %q for %v is in use by another process already", lockname, addr))
	}
	// We have the exclusive use of the socket, clear away any old sockets and listen:
	_ = os.Remove(addr.String())
	listener, err := net.ListenUnix(addr.Network(), addr)
	if err != nil {
		panic(fmt.Sprintf("Couldn't listen on UNIX socket %v: %v", addr, err))
	}

	// Make the socket connectable by everyone with access to the socket pathname:
	err = os.Chmod(addr.String(), 0666)
	if err != nil {
		panic(fmt.Sprintf("Couldn't set permissions on %v: %v", addr, err))
	}

	go func() {
		conns := make(chan net.Conn)
		go func() {
			defer func() {
				lock.Unlock()
				close(done)
			}()
			for {
				conn, err := listener.AcceptUnix()
				if err != nil {
					select {
					case <-s.shutdown:
						// occurs when cleanly shutting down the server e.g. in tests; ignore errors
						log.WithError(err).Info("Ignoring Accept error while shutting down")
						return
					default:
						log.WithError(err).Fatal("Unix accept failed")
					}
				}
				conns <- conn
			}
		}()
		for {
			select {
			case conn := <-conns:
				go s.ReadSSFStreamSocket(conn)
			case <-s.shutdown:
				listener.Close()
				return
			}
		}
	}()
	return done, listener.Addr()
}
<|endoftext|>


<commit_before>package gateway

const VERSION = "v2.10"
<commit_msg>Update version.go (#3143)<commit_after>package gateway

const VERSION = "v3.0.0"
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsproxy

import (
	"io"
	"log"
	"os"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"google.golang.org/cloud/storage"
)

// A view on an object in GCS that allows random access reads and writes.
//
// Reads may involve reading from a local cache. Writes are buffered locally
// until the Sync method is called, at which time a new generation of the
// object is created.
//
// All methods are safe for concurrent access. Concurrent readers and writers
// within process receive the same guarantees as with POSIX files.
type ProxyObject struct {
	/////////////////////////
	// Dependencies
	/////////////////////////

	logger *log.Logger
	bucket gcs.Bucket

	/////////////////////////
	// Constant data
	/////////////////////////

	// The name of the GCS object for which we are a proxy. Might not exist in
	// the bucket.
	objectName string

	/////////////////////////
	// Mutable state
	/////////////////////////

	mu syncutil.InvariantMutex

	// The specific generation of the object from which our local state is
	// branched. If we have no local state, the contents of this object are
	// exactly our contents. May be nil if NoteLatest was never called.
	source *storage.Object // GUARDED_BY(mu)

	// A local temporary file containing the contents of our source (or the empty
	// string if no source) along with any local modifications. When nil, to be
	// regarded as the empty file.
	localFile *os.File // GUARDED_BY(mu)

	// false iff source is non-nil and is authoritative for our view of the
	// contents. Sync needs to do work iff this is true.
	dirty bool // GUARDED_BY(mu)
}

var _ io.ReaderAt = &ProxyObject{}
var _ io.WriterAt = &ProxyObject{}

// Create a new view on the GCS object with the given name. The remote object
// is assumed to be non-existent, so that the local contents are empty. Use
// NoteLatest to change that if necessary.
func NewProxyObject(
	bucket gcs.Bucket,
	name string) (*ProxyObject, error)

// Inform the proxy object of the most recently observed generation of the
// object of interest in GCS.
//
// If this is no newer than the newest generation that has previously been
// observed, it is ignored. Otherwise, it becomes the definitive source of data
// for the object. Any local-only state is clobbered, including local
// modifications.
func (po *ProxyObject) NoteLatest(o storage.Object) error

// Return the current size in bytes of our view of the content.
func (po *ProxyObject) Size() uint64

// Make a random access read into our view of the content. May block for
// network access.
func (po *ProxyObject) ReadAt(buf []byte, offset int64) (int, error)

// Make a random access write into our view of the content. May block for
// network access. Not guaranteed to be reflected remotely until after Sync is
// called successfully.
func (po *ProxyObject) WriteAt(buf []byte, offset int64) (int, error)

// Truncate our view of the content to the given number of bytes, extending if
// n is greater than Size(). May block for network access. Not guaranteed to be
// reflected remotely until after Sync is called successfully.
func (po *ProxyObject) Truncate(n uint64) error

// Ensure that the remote object reflects the local state, returning a record
// for a generation that does. Clobbers the remote version. Does no work if the
// remote version is already up to date.
func (po *ProxyObject) Sync() (storage.Object, error)
<commit_msg>Implemented NewProxyObject.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsproxy

import (
	"io"
	"log"
	"os"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"google.golang.org/cloud/storage"
)

// A view on an object in GCS that allows random access reads and writes.
//
// Reads may involve reading from a local cache. Writes are buffered locally
// until the Sync method is called, at which time a new generation of the
// object is created.
//
// All methods are safe for concurrent access. Concurrent readers and writers
// within process receive the same guarantees as with POSIX files.
type ProxyObject struct {
	/////////////////////////
	// Dependencies
	/////////////////////////

	logger *log.Logger
	bucket gcs.Bucket

	/////////////////////////
	// Constant data
	/////////////////////////

	// The name of the GCS object for which we are a proxy. Might not exist in
	// the bucket.
	name string

	/////////////////////////
	// Mutable state
	/////////////////////////

	mu syncutil.InvariantMutex

	// The specific generation of the object from which our local state is
	// branched. If we have no local state, the contents of this object are
	// exactly our contents. May be nil if NoteLatest was never called.
	source *storage.Object // GUARDED_BY(mu)

	// A local temporary file containing the contents of our source (or the empty
	// string if no source) along with any local modifications. When nil, to be
	// regarded as the empty file.
	localFile *os.File // GUARDED_BY(mu)

	// false iff source is non-nil and is authoritative for our view of the
	// contents. Sync needs to do work iff this is true.
	dirty bool // GUARDED_BY(mu)
}

var _ io.ReaderAt = &ProxyObject{}
var _ io.WriterAt = &ProxyObject{}

// Create a new view on the GCS object with the given name. The remote object
// is assumed to be non-existent, so that the local contents are empty. Use
// NoteLatest to change that if necessary.
func NewProxyObject(
	bucket gcs.Bucket,
	name string) (po *ProxyObject, err error) {
	po = &ProxyObject{
		logger: getLogger(),
		bucket: bucket,
		name:   name,

		// Initial state: empty contents, dirty. (The remote object needs to be
		// truncated.)
		source:    nil,
		localFile: nil,
		dirty:     true,
	}

	po.mu = syncutil.NewInvariantMutex(po.checkInvariants)
	return
}

// SHARED_LOCKS_REQUIRED(po.mu)
func (po *ProxyObject) checkInvariants()

// Inform the proxy object of the most recently observed generation of the
// object of interest in GCS.
//
// If this is no newer than the newest generation that has previously been
// observed, it is ignored. Otherwise, it becomes the definitive source of data
// for the object. Any local-only state is clobbered, including local
// modifications.
func (po *ProxyObject) NoteLatest(o storage.Object) error

// Return the current size in bytes of our view of the content.
func (po *ProxyObject) Size() uint64

// Make a random access read into our view of the content. May block for
// network access.
func (po *ProxyObject) ReadAt(buf []byte, offset int64) (int, error)

// Make a random access write into our view of the content. May block for
// network access. Not guaranteed to be reflected remotely until after Sync is
// called successfully.
func (po *ProxyObject) WriteAt(buf []byte, offset int64) (int, error)

// Truncate our view of the content to the given number of bytes, extending if
// n is greater than Size(). May block for network access. Not guaranteed to be
// reflected remotely until after Sync is called successfully.
func (po *ProxyObject) Truncate(n uint64) error

// Ensure that the remote object reflects the local state, returning a record
// for a generation that does. Clobbers the remote version. Does no work if the
// remote version is already up to date.
func (po *ProxyObject) Sync() (storage.Object, error)
<|endoftext|>


<commit_before>package dexcom

import (
	"fmt"
	"log"
	"time"

	"github.com/ecc1/nightscout"
)

// NightscoutEntries converts records (in reverse-chronological order)
// into a Nightscout entries.  Neighboring Sensor and EGV records are merged.
func NightscoutEntries(records Records) nightscout.Entries {
	entries := make(nightscout.Entries, len(records))
	for i, r := range records {
		entries[i] = r.nightscoutEntry()
	}
	return mergeGlucoseEntries(entries)
}

func (r Record) nightscoutEntry() nightscout.Entry {
	t := r.Time()
	e := nightscout.Entry{
		Date:       nightscout.Date(t),
		DateString: t.Format(nightscout.DateStringLayout),
		Device:     nightscout.Device(),
	}
	if r.Sensor != nil {
		info := r.Sensor
		e.Type = nightscout.SGVType
		e.Unfiltered = int(info.Unfiltered)
		e.Filtered = int(info.Filtered)
		e.RSSI = int(info.RSSI)
		return e
	}
	if r.EGV != nil {
		info := r.EGV
		e.Type = nightscout.SGVType
		e.SGV = int(info.Glucose)
		e.Direction = nightscoutTrend(info.Trend)
		e.Noise = int(info.Noise)
		return e
	}
	if r.Meter != nil {
		info := r.Meter
		e.Type = nightscout.MBGType
		e.MBG = int(info.Glucose)
		return e
	}
	if r.Calibration != nil {
		info := r.Calibration
		e.Type = nightscout.CalType
		e.Slope = info.Slope
		e.Intercept = info.Intercept
		e.Scale = info.Scale
		return e
	}
	panic(fmt.Sprintf("nightscoutEntry %+v", r))
}

func nightscoutTrend(t Trend) string {
	switch t {
	case UpUp:
		return "DoubleUp"
	case Up:
		return "SingleUp"
	case Up45:
		return "FortyFiveUp"
	case Flat:
		return "Flat"
	case Down45:
		return "FortyFiveDown"
	case Down:
		return "SingleDown"
	case DownDown:
		return "DoubleDown"
	default:
		return ""
	}
}

const (
	// Time window within which sensor and EGV readings will be merged.
	glucoseReadingWindow = 10 * time.Second
)

func mergeGlucoseEntries(entries nightscout.Entries) nightscout.Entries {
	merged := make(nightscout.Entries, 0, len(entries))
	i := 0
	for i < len(entries) {
		e := entries[i]
		if e.Type == nightscout.SGVType && i+1 < len(entries) {
			f := entries[i+1]
			if f.Type == nightscout.SGVType {
				delta := e.Time().Sub(f.Time())
				if delta < 0 {
					log.Panicf("out-of-order glucose entries (delta = %v)", delta)
				}
				if delta < glucoseReadingWindow {
					e = combineEntries(e, f)
					i++
				}
			}
		}
		merged = append(merged, e)
		i++
	}
	return merged
}

func combineEntries(a, b nightscout.Entry) nightscout.Entry {
	if a.Type != nightscout.SGVType || b.Type != nightscout.SGVType {
		log.Panicf("combining %s and %s", a.Type, b.Type)
	}
	if b.Time().Before(a.Time()) {
		// Use b's earlier time.
		a.Date = b.Date
		a.DateString = b.DateString
	}
	// Update a with non-zero sgv values from b.
	if b.SGV != 0 {
		a.SGV = b.SGV
	}
	if b.Direction != "" {
		a.Direction = b.Direction
	}
	if b.Filtered != 0 {
		a.Filtered = b.Filtered
	}
	if b.Unfiltered != 0 {
		a.Unfiltered = b.Unfiltered
	}
	if b.RSSI != 0 {
		a.RSSI = b.RSSI
	}
	if b.Noise != 0 {
		a.Noise = b.Noise
	}
	return a
}
<commit_msg>Don't panic on out-of-order glucose entries<commit_after>package dexcom

import (
	"fmt"
	"log"
	"time"

	"github.com/ecc1/nightscout"
)

// NightscoutEntries converts records (in reverse-chronological order)
// into a Nightscout entries.  Neighboring Sensor and EGV records are merged.
func NightscoutEntries(records Records) nightscout.Entries {
	entries := make(nightscout.Entries, len(records))
	for i, r := range records {
		entries[i] = r.nightscoutEntry()
	}
	return mergeGlucoseEntries(entries)
}

func (r Record) nightscoutEntry() nightscout.Entry {
	t := r.Time()
	e := nightscout.Entry{
		Date:       nightscout.Date(t),
		DateString: t.Format(nightscout.DateStringLayout),
		Device:     nightscout.Device(),
	}
	if r.Sensor != nil {
		info := r.Sensor
		e.Type = nightscout.SGVType
		e.Unfiltered = int(info.Unfiltered)
		e.Filtered = int(info.Filtered)
		e.RSSI = int(info.RSSI)
		return e
	}
	if r.EGV != nil {
		info := r.EGV
		e.Type = nightscout.SGVType
		e.SGV = int(info.Glucose)
		e.Direction = nightscoutTrend(info.Trend)
		e.Noise = int(info.Noise)
		return e
	}
	if r.Meter != nil {
		info := r.Meter
		e.Type = nightscout.MBGType
		e.MBG = int(info.Glucose)
		return e
	}
	if r.Calibration != nil {
		info := r.Calibration
		e.Type = nightscout.CalType
		e.Slope = info.Slope
		e.Intercept = info.Intercept
		e.Scale = info.Scale
		return e
	}
	panic(fmt.Sprintf("nightscoutEntry %+v", r))
}

func nightscoutTrend(t Trend) string {
	switch t {
	case UpUp:
		return "DoubleUp"
	case Up:
		return "SingleUp"
	case Up45:
		return "FortyFiveUp"
	case Flat:
		return "Flat"
	case Down45:
		return "FortyFiveDown"
	case Down:
		return "SingleDown"
	case DownDown:
		return "DoubleDown"
	default:
		return ""
	}
}

const (
	// Time window within which sensor and EGV readings will be merged.
	glucoseReadingWindow = 10 * time.Second
)

func mergeGlucoseEntries(entries nightscout.Entries) nightscout.Entries {
	merged := make(nightscout.Entries, 0, len(entries))
	i := 0
	for i < len(entries) {
		e := entries[i]
		if e.Type == nightscout.SGVType && i+1 < len(entries) {
			f := entries[i+1]
			if f.Type == nightscout.SGVType {
				delta := e.Time().Sub(f.Time())
				if 0 <= delta && delta < glucoseReadingWindow {
					e = combineEntries(e, f)
					i++
				}
			}
		}
		merged = append(merged, e)
		i++
	}
	return merged
}

func combineEntries(a, b nightscout.Entry) nightscout.Entry {
	if a.Type != nightscout.SGVType || b.Type != nightscout.SGVType {
		log.Panicf("combining %s and %s", a.Type, b.Type)
	}
	if b.Time().Before(a.Time()) {
		// Use b's earlier time.
		a.Date = b.Date
		a.DateString = b.DateString
	}
	// Update a with non-zero sgv values from b.
	if b.SGV != 0 {
		a.SGV = b.SGV
	}
	if b.Direction != "" {
		a.Direction = b.Direction
	}
	if b.Filtered != 0 {
		a.Filtered = b.Filtered
	}
	if b.Unfiltered != 0 {
		a.Unfiltered = b.Unfiltered
	}
	if b.RSSI != 0 {
		a.RSSI = b.RSSI
	}
	if b.Noise != 0 {
		a.Noise = b.Noise
	}
	return a
}
<|endoftext|>


<commit_before>package auth

import (
	"github.com/gin-gonic/gin"
	"github.com/pufferpanel/apufferi/v4/logging"
	"github.com/pufferpanel/apufferi/v4/response"
	"github.com/pufferpanel/pufferpanel/v2/models"
	"github.com/pufferpanel/pufferpanel/v2/services"
	"github.com/pufferpanel/pufferpanel/v2/web/handlers"
	"gopkg.in/go-playground/validator.v9"
	"net/http"
)

func RegisterPost(c *gin.Context) {
	db := handlers.GetDatabase(c)
	us := &services.User{DB: db}

	request := &registerRequestData{}
	err := c.BindJSON(request)

	if response.HandleError(c, err, http.StatusBadRequest) {
		return
	}

	validate := validator.New()
	err = validate.Struct(request)
	if response.HandleError(c, err, http.StatusBadRequest) {
		return
	}

	user := &models.User{Username: request.Username, Email: request.Email}
	err = user.SetPassword(request.Password)
	if response.HandleError(c, err, http.StatusInternalServerError) {
	}

	err = us.Create(user)
	if response.HandleError(c, err, http.StatusInternalServerError) {
		return
	}

	//TODO: Have this be an optional flag
	token := ""
	if true {
		_, token, err = us.Login(user.Email, request.Password)
		if err != nil {
			logging.Exception("Error trying to auto-login after register", err)
			c.JSON(200, &registerResponse{Success: true})
			return
		}
	}

	c.JSON(200, &registerResponse{Success: true, Token: token})
}

type registerResponse struct {
	Success bool   `json:"success"`
	Token   string `json:"token,omitempty"`
}

type registerRequestData struct {
	Username string `json:"username" validate:"min=3,printascii,required"`
	Email    string `json:"email" validate:"required,email"`
	Password string `json:"password" validate:"required"`
}
<commit_msg>Give perms when you first register<commit_after>package auth

import (
	"github.com/gin-gonic/gin"
	"github.com/pufferpanel/apufferi/v4/logging"
	"github.com/pufferpanel/apufferi/v4/response"
	"github.com/pufferpanel/pufferpanel/v2/models"
	"github.com/pufferpanel/pufferpanel/v2/services"
	"github.com/pufferpanel/pufferpanel/v2/web/handlers"
	"gopkg.in/go-playground/validator.v9"
	"net/http"
)

func RegisterPost(c *gin.Context) {
	db := handlers.GetDatabase(c)
	us := &services.User{DB: db}

	request := &registerRequestData{}
	err := c.BindJSON(request)

	if response.HandleError(c, err, http.StatusBadRequest) {
		return
	}

	validate := validator.New()
	err = validate.Struct(request)
	if response.HandleError(c, err, http.StatusBadRequest) {
		return
	}

	user := &models.User{Username: request.Username, Email: request.Email}
	err = user.SetPassword(request.Password)
	if response.HandleError(c, err, http.StatusInternalServerError) {
	}

	err = us.Create(user)
	if response.HandleError(c, err, http.StatusInternalServerError) {
		return
	}

	ps := &services.Permission{DB: db}
	perms, err := ps.GetForUserAndServer(user.ID, nil)
	if response.HandleError(c, err, http.StatusInternalServerError) {
		return
	}

	perms.ViewServer = true

	err = ps.UpdatePermissions(perms)
	if response.HandleError(c, err, http.StatusInternalServerError) {
		return
	}

	//TODO: Have this be an optional flag
	token := ""
	if true {
		_, token, err = us.Login(user.Email, request.Password)
		if err != nil {
			logging.Exception("Error trying to auto-login after register", err)
			c.JSON(200, &registerResponse{Success: true})
			return
		}
	}

	c.JSON(200, &registerResponse{Success: true, Token: token})
}

type registerResponse struct {
	Success bool   `json:"success"`
	Token   string `json:"token,omitempty"`
}

type registerRequestData struct {
	Username string `json:"username" validate:"min=3,printascii,required"`
	Email    string `json:"email" validate:"required,email"`
	Password string `json:"password" validate:"required"`
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"os/exec"
)

// Execute run a command and return the stdout and stderr as string array.
func Execute(name string, args ...string) ([]string, []string, error) {
	cmd := exec.Command(name, args...)
	// create the pipes for stderr and stdout...
	stderr, errStderr := cmd.StderrPipe()
	if errStderr != nil {
		return []string{}, []string{}, errStderr
	}
	stdout, errStdout := cmd.StdoutPipe()
	if errStdout != nil {
		return []string{}, []string{}, errStdout
	}
	// execute the command
	cmd.Start()
	// read the stderr pipe
	stderrText := readerToStringArray(stderr)
	stdoutText := readerToStringArray(stdout)
	return stdoutText, stderrText, nil
}

func readerToStringArray(in io.Reader) []string {
	var out []string
	r := bufio.NewReader(in)
	line, _, err := r.ReadLine()
	for err == nil {
		out = append(out, string(line)) //string(line) + "\n"
		// fmt.Println(string(line))
		line, _, err = r.ReadLine()
	}
	return out
}
<commit_msg>rename execute package<commit_after>package execute

import (
	"bufio"
	"io"
	"os/exec"
)

// Execute run a command and return the stdout and stderr as string array.
func Execute(name string, args ...string) ([]string, []string, error) {
	cmd := exec.Command(name, args...)
	// create the pipes for stderr and stdout...
	stderr, errStderr := cmd.StderrPipe()
	if errStderr != nil {
		return []string{}, []string{}, errStderr
	}
	stdout, errStdout := cmd.StdoutPipe()
	if errStdout != nil {
		return []string{}, []string{}, errStdout
	}
	// execute the command
	cmd.Start()
	// read the stderr pipe
	stderrText := readerToStringArray(stderr)
	stdoutText := readerToStringArray(stdout)
	return stdoutText, stderrText, nil
}

func readerToStringArray(in io.Reader) []string {
	var out []string
	r := bufio.NewReader(in)
	line, _, err := r.ReadLine()
	for err == nil {
		out = append(out, string(line)) //string(line) + "\n"
		// fmt.Println(string(line))
		line, _, err = r.ReadLine()
	}
	return out
}
<|endoftext|>


<commit_before>package exename

//#include <windows.h>
import "C"

import "bytes"
import "unicode/utf16"

func Query() string {
	var pathW [C.MAX_PATH]C.WCHAR
	C.GetModuleFileNameW(nil, &pathW[0], C.MAX_PATH)

	var path16 [C.MAX_PATH]uint16
	for i := 0; pathW[i] != 0; i++ {
		path16[i] = (uint16)(pathW[i])
	}

	pathRune := utf16.Decode(path16[:])
	var buffer bytes.Buffer
	for _, ch := range pathRune {
		if ch == 0 {
			break
		}
		buffer.WriteRune(ch)
	}
	return buffer.String()
}
<commit_msg>実行ファイルのフルパス取得を http://qiita.com/zetamatta/items/e5fb297099455fe558b6 のコメントの方式に書き換えた<commit_after>package exename

import "syscall"
import "unsafe"

var kernel32 = syscall.NewLazyDLL("kernel32")
var procGetModuleFileName = kernel32.NewProc("GetModuleFileNameW")

func Query() string {
	var path16 [syscall.MAX_PATH]uint16
	procGetModuleFileName.Call(0, uintptr(unsafe.Pointer(&path16[0])), uintptr(len(path16)))
	return syscall.UTF16ToString(path16[:])
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

import (
	"fmt"
	"time"

	"github.com/spf13/pflag"

	"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
	"k8s.io/apiserver/pkg/server"
	authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

type RequestHeaderAuthenticationOptions struct {
	UsernameHeaders     []string
	GroupHeaders        []string
	ExtraHeaderPrefixes []string
	ClientCAFile        string
	AllowedNames        []string
}

func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringSliceVar(&s.UsernameHeaders, "requestheader-username-headers", s.UsernameHeaders, ""+
		"List of request headers to inspect for usernames. X-Remote-User is common.")

	fs.StringSliceVar(&s.GroupHeaders, "requestheader-group-headers", s.GroupHeaders, ""+
		"List of request headers to inspect for groups. X-Remote-Group is suggested.")

	fs.StringSliceVar(&s.ExtraHeaderPrefixes, "requestheader-extra-headers-prefix", s.ExtraHeaderPrefixes, ""+
		"List of request header prefixes to inspect. X-Remote-Extra- is suggested.")

	fs.StringVar(&s.ClientCAFile, "requestheader-client-ca-file", s.ClientCAFile, ""+
		"Root certificate bundle to use to verify client certificates on incoming requests "+
		"before trusting usernames in headers specified by --requestheader-username-headers")

	fs.StringSliceVar(&s.AllowedNames, "requestheader-allowed-names", s.AllowedNames, ""+
		"List of client certificate common names to allow to provide usernames in headers "+
		"specified by --requestheader-username-headers. If empty, any client certificate validated "+
		"by the authorities in --requestheader-client-ca-file is allowed.")
}

// ToAuthenticationRequestHeaderConfig returns a RequestHeaderConfig config object for these options
// if necessary, nil otherwise.
func (s *RequestHeaderAuthenticationOptions) ToAuthenticationRequestHeaderConfig() *authenticatorfactory.RequestHeaderConfig {
	if len(s.ClientCAFile) == 0 {
		return nil
	}

	return &authenticatorfactory.RequestHeaderConfig{
		UsernameHeaders:     s.UsernameHeaders,
		GroupHeaders:        s.GroupHeaders,
		ExtraHeaderPrefixes: s.ExtraHeaderPrefixes,
		ClientCA:            s.ClientCAFile,
		AllowedClientNames:  s.AllowedNames,
	}
}

type ClientCertAuthenticationOptions struct {
	// ClientCA is the certificate bundle for all the signers that you'll recognize for incoming client certificates
	ClientCA string
}

func (s *ClientCertAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.ClientCA, "client-ca-file", s.ClientCA, ""+
		"If set, any request presenting a client certificate signed by one of "+
		"the authorities in the client-ca-file is authenticated with an identity "+
		"corresponding to the CommonName of the client certificate.")
}

// DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to
// the root kube API server.  The API federator will act as
// a front proxy and direction connections will be able to delegate to the core kube API server
type DelegatingAuthenticationOptions struct {
	// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
	// TokenAccessReview.authentication.k8s.io endpoint for checking tokens.
	RemoteKubeConfigFile string

	// CacheTTL is the length of time that a token authentication answer will be cached.
	CacheTTL time.Duration

	ClientCert    ClientCertAuthenticationOptions
	RequestHeader RequestHeaderAuthenticationOptions
}

func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
	return &DelegatingAuthenticationOptions{
		// very low for responsiveness, but high enough to handle storms
		CacheTTL:   10 * time.Second,
		ClientCert: ClientCertAuthenticationOptions{},
		RequestHeader: RequestHeaderAuthenticationOptions{
			UsernameHeaders:     []string{"x-remote-user"},
			GroupHeaders:        []string{"x-remote-group"},
			ExtraHeaderPrefixes: []string{"x-remote-extra-"},
		},
	}
}

func (s *DelegatingAuthenticationOptions) Validate() []error {
	allErrors := []error{}
	return allErrors
}

func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.RemoteKubeConfigFile, "authentication-kubeconfig", s.RemoteKubeConfigFile, ""+
		"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
		"tokenaccessreviews.authentication.k8s.io.")

	fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL,
		"The duration to cache responses from the webhook token authenticator.")

	s.ClientCert.AddFlags(fs)
	s.RequestHeader.AddFlags(fs)
}

func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error {
	var err error
	c, err = c.ApplyClientCert(s.ClientCert.ClientCA)
	if err != nil {
		return fmt.Errorf("unable to load client CA file: %v", err)
	}
	c, err = c.ApplyClientCert(s.RequestHeader.ClientCAFile)
	if err != nil {
		return fmt.Errorf("unable to load client CA file: %v", err)
	}

	cfg, err := s.ToAuthenticationConfig()
	if err != nil {
		return err
	}
	authenticator, securityDefinitions, err := cfg.New()
	if err != nil {
		return err
	}

	c.Authenticator = authenticator
	if c.OpenAPIConfig != nil {
		c.OpenAPIConfig.SecurityDefinitions = securityDefinitions
	}
	c.SupportsBasicAuth = false

	return nil
}

func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticatorfactory.DelegatingAuthenticatorConfig, error) {
	tokenClient, err := s.newTokenAccessReview()
	if err != nil {
		return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
	}

	ret := authenticatorfactory.DelegatingAuthenticatorConfig{
		Anonymous:               true,
		TokenAccessReviewClient: tokenClient,
		CacheTTL:                s.CacheTTL,
		ClientCAFile:            s.ClientCert.ClientCA,
		RequestHeaderConfig:     s.RequestHeader.ToAuthenticationRequestHeaderConfig(),
	}
	return ret, nil
}

func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authenticationclient.TokenReviewInterface, error) {
	var clientConfig *rest.Config
	var err error
	if len(s.RemoteKubeConfigFile) > 0 {
		loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.RemoteKubeConfigFile}
		loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

		clientConfig, err = loader.ClientConfig()

	} else {
		// without the remote kubeconfig file, try to use the in-cluster config.  Most addon API servers will
		// use this path
		clientConfig, err = rest.InClusterConfig()
	}
	if err != nil {
		return nil, err
	}

	// set high qps/burst limits since this will effectively limit API server responsiveness
	clientConfig.QPS = 200
	clientConfig.Burst = 400

	client, err := authenticationclient.NewForConfig(clientConfig)
	if err != nil {
		return nil, err
	}

	return client.TokenReviews(), nil
}
<commit_msg>allow incluster authentication info lookup<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

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

	"github.com/golang/glog"
	"github.com/spf13/pflag"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
	"k8s.io/apiserver/pkg/server"
	authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
	coreclient "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

type RequestHeaderAuthenticationOptions struct {
	UsernameHeaders     []string
	GroupHeaders        []string
	ExtraHeaderPrefixes []string
	ClientCAFile        string
	AllowedNames        []string
}

func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringSliceVar(&s.UsernameHeaders, "requestheader-username-headers", s.UsernameHeaders, ""+
		"List of request headers to inspect for usernames. X-Remote-User is common.")

	fs.StringSliceVar(&s.GroupHeaders, "requestheader-group-headers", s.GroupHeaders, ""+
		"List of request headers to inspect for groups. X-Remote-Group is suggested.")

	fs.StringSliceVar(&s.ExtraHeaderPrefixes, "requestheader-extra-headers-prefix", s.ExtraHeaderPrefixes, ""+
		"List of request header prefixes to inspect. X-Remote-Extra- is suggested.")

	fs.StringVar(&s.ClientCAFile, "requestheader-client-ca-file", s.ClientCAFile, ""+
		"Root certificate bundle to use to verify client certificates on incoming requests "+
		"before trusting usernames in headers specified by --requestheader-username-headers")

	fs.StringSliceVar(&s.AllowedNames, "requestheader-allowed-names", s.AllowedNames, ""+
		"List of client certificate common names to allow to provide usernames in headers "+
		"specified by --requestheader-username-headers. If empty, any client certificate validated "+
		"by the authorities in --requestheader-client-ca-file is allowed.")
}

// ToAuthenticationRequestHeaderConfig returns a RequestHeaderConfig config object for these options
// if necessary, nil otherwise.
func (s *RequestHeaderAuthenticationOptions) ToAuthenticationRequestHeaderConfig() *authenticatorfactory.RequestHeaderConfig {
	if len(s.ClientCAFile) == 0 {
		return nil
	}

	return &authenticatorfactory.RequestHeaderConfig{
		UsernameHeaders:     s.UsernameHeaders,
		GroupHeaders:        s.GroupHeaders,
		ExtraHeaderPrefixes: s.ExtraHeaderPrefixes,
		ClientCA:            s.ClientCAFile,
		AllowedClientNames:  s.AllowedNames,
	}
}

type ClientCertAuthenticationOptions struct {
	// ClientCA is the certificate bundle for all the signers that you'll recognize for incoming client certificates
	ClientCA string
}

func (s *ClientCertAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.ClientCA, "client-ca-file", s.ClientCA, ""+
		"If set, any request presenting a client certificate signed by one of "+
		"the authorities in the client-ca-file is authenticated with an identity "+
		"corresponding to the CommonName of the client certificate.")
}

// DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to
// the root kube API server.  The API federator will act as
// a front proxy and direction connections will be able to delegate to the core kube API server
type DelegatingAuthenticationOptions struct {
	// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
	// TokenAccessReview.authentication.k8s.io endpoint for checking tokens.
	RemoteKubeConfigFile string

	// CacheTTL is the length of time that a token authentication answer will be cached.
	CacheTTL time.Duration

	ClientCert    ClientCertAuthenticationOptions
	RequestHeader RequestHeaderAuthenticationOptions

	SkipInClusterLookup bool
}

func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
	return &DelegatingAuthenticationOptions{
		// very low for responsiveness, but high enough to handle storms
		CacheTTL:   10 * time.Second,
		ClientCert: ClientCertAuthenticationOptions{},
		RequestHeader: RequestHeaderAuthenticationOptions{
			UsernameHeaders:     []string{"x-remote-user"},
			GroupHeaders:        []string{"x-remote-group"},
			ExtraHeaderPrefixes: []string{"x-remote-extra-"},
		},
	}
}

func (s *DelegatingAuthenticationOptions) Validate() []error {
	allErrors := []error{}
	return allErrors
}

func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringVar(&s.RemoteKubeConfigFile, "authentication-kubeconfig", s.RemoteKubeConfigFile, ""+
		"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
		"tokenaccessreviews.authentication.k8s.io.")

	fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL,
		"The duration to cache responses from the webhook token authenticator.")

	s.ClientCert.AddFlags(fs)
	s.RequestHeader.AddFlags(fs)

	fs.BoolVar(&s.SkipInClusterLookup, "authentication-skip-lookup", s.SkipInClusterLookup, ""+
		"If false, the authentication-kubeconfig will be used to lookup missing authentication "+
		"configuration from the cluster.")

}

func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error {
	clientCA, err := s.getClientCA()
	if err != nil {
		return err
	}
	c, err = c.ApplyClientCert(clientCA.ClientCA)
	if err != nil {
		return fmt.Errorf("unable to load client CA file: %v", err)
	}

	requestHeader, err := s.getRequestHeader()
	if err != nil {
		return err
	}
	c, err = c.ApplyClientCert(requestHeader.ClientCAFile)
	if err != nil {
		return fmt.Errorf("unable to load client CA file: %v", err)
	}

	cfg, err := s.ToAuthenticationConfig()
	if err != nil {
		return err
	}
	authenticator, securityDefinitions, err := cfg.New()
	if err != nil {
		return err
	}

	c.Authenticator = authenticator
	if c.OpenAPIConfig != nil {
		c.OpenAPIConfig.SecurityDefinitions = securityDefinitions
	}
	c.SupportsBasicAuth = false

	return nil
}

func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticatorfactory.DelegatingAuthenticatorConfig, error) {
	tokenClient, err := s.newTokenAccessReview()
	if err != nil {
		return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
	}

	clientCA, err := s.getClientCA()
	if err != nil {
		return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
	}
	requestHeader, err := s.getRequestHeader()
	if err != nil {
		return authenticatorfactory.DelegatingAuthenticatorConfig{}, err
	}

	ret := authenticatorfactory.DelegatingAuthenticatorConfig{
		Anonymous:               true,
		TokenAccessReviewClient: tokenClient,
		CacheTTL:                s.CacheTTL,
		ClientCAFile:            clientCA.ClientCA,
		RequestHeaderConfig:     requestHeader.ToAuthenticationRequestHeaderConfig(),
	}
	return ret, nil
}

const (
	authenticationConfigMapNamespace = metav1.NamespaceSystem
	authenticationConfigMapName      = "extension-apiserver-authentication"
	authenticationRoleName           = "extension-apiserver-authentication-reader"
)

func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticationOptions, error) {
	if len(s.ClientCert.ClientCA) > 0 || s.SkipInClusterLookup {
		return &s.ClientCert, nil
	}

	incluster, err := s.lookupInClusterClientCA()
	if err != nil {
		glog.Warningf("Unable to get configmap/%s in %s.  Usually fixed by "+
			"'kubectl create rolebinding -n %s ROLE_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
			authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName)
		return nil, err
	}
	if incluster == nil {
		return nil, fmt.Errorf("cluster doesn't provide client-ca-file")
	}
	return incluster, nil
}

func (s *DelegatingAuthenticationOptions) getRequestHeader() (*RequestHeaderAuthenticationOptions, error) {
	if len(s.RequestHeader.ClientCAFile) > 0 || s.SkipInClusterLookup {
		return &s.RequestHeader, nil
	}

	incluster, err := s.lookupInClusterRequestHeader()
	if err != nil {
		glog.Warningf("Unable to get configmap/%s in %s.  Usually fixed by "+
			"'kubectl create rolebinding -n %s ROLE_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
			authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName)
		return nil, err
	}
	if incluster == nil {
		return nil, fmt.Errorf("cluster doesn't provide requestheader-client-ca-file")
	}
	return incluster, nil
}

func (s *DelegatingAuthenticationOptions) lookupInClusterClientCA() (*ClientCertAuthenticationOptions, error) {
	clientConfig, err := s.getClientConfig()
	if err != nil {
		return nil, err
	}
	client, err := coreclient.NewForConfig(clientConfig)
	if err != nil {
		return nil, err
	}

	authConfigMap, err := client.ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
	if err != nil {
		return nil, err
	}

	clientCA, ok := authConfigMap.Data["client-ca-file"]
	if !ok {
		return nil, nil
	}

	f, err := ioutil.TempFile("", "client-ca-file")
	if err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile(f.Name(), []byte(clientCA), 0600); err != nil {
		return nil, err
	}
	return &ClientCertAuthenticationOptions{ClientCA: f.Name()}, nil
}

func (s *DelegatingAuthenticationOptions) lookupInClusterRequestHeader() (*RequestHeaderAuthenticationOptions, error) {
	clientConfig, err := s.getClientConfig()
	if err != nil {
		return nil, err
	}
	client, err := coreclient.NewForConfig(clientConfig)
	if err != nil {
		return nil, err
	}

	authConfigMap, err := client.ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
	if err != nil {
		return nil, err
	}

	requestHeaderCA, ok := authConfigMap.Data["requestheader-client-ca-file"]
	if !ok {
		return nil, nil
	}

	f, err := ioutil.TempFile("", "requestheader-client-ca-file")
	if err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile(f.Name(), []byte(requestHeaderCA), 0600); err != nil {
		return nil, err
	}
	usernameHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-username-headers"])
	if err != nil {
		return nil, err
	}
	groupHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-group-headers"])
	if err != nil {
		return nil, err
	}
	extraHeaderPrefixes, err := deserializeStrings(authConfigMap.Data["requestheader-extra-headers-prefix"])
	if err != nil {
		return nil, err
	}
	allowedNames, err := deserializeStrings(authConfigMap.Data["requestheader-allowed-names"])
	if err != nil {
		return nil, err
	}

	return &RequestHeaderAuthenticationOptions{
		UsernameHeaders:     usernameHeaders,
		GroupHeaders:        groupHeaders,
		ExtraHeaderPrefixes: extraHeaderPrefixes,
		ClientCAFile:        f.Name(),
		AllowedNames:        allowedNames,
	}, nil
}

func deserializeStrings(in string) ([]string, error) {
	if len(in) == 0 {
		return nil, nil
	}
	var ret []string
	if err := json.Unmarshal([]byte(in), &ret); err != nil {
		return nil, err
	}
	return ret, nil
}

func (s *DelegatingAuthenticationOptions) getClientConfig() (*rest.Config, error) {
	var clientConfig *rest.Config
	var err error
	if len(s.RemoteKubeConfigFile) > 0 {
		loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.RemoteKubeConfigFile}
		loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

		clientConfig, err = loader.ClientConfig()

	} else {
		// without the remote kubeconfig file, try to use the in-cluster config.  Most addon API servers will
		// use this path
		clientConfig, err = rest.InClusterConfig()
	}
	if err != nil {
		return nil, err
	}

	// set high qps/burst limits since this will effectively limit API server responsiveness
	clientConfig.QPS = 200
	clientConfig.Burst = 400

	return clientConfig, nil
}

func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authenticationclient.TokenReviewInterface, error) {
	clientConfig, err := s.getClientConfig()
	if err != nil {
		return nil, err
	}
	client, err := authenticationclient.NewForConfig(clientConfig)
	if err != nil {
		return nil, err
	}

	return client.TokenReviews(), nil
}
<|endoftext|>


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

// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package expression

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/expression/builtin"
)

var (
	_ Expression = (*Call)(nil)
)

// Call is for function expression.
type Call struct {
	// F is the function name.
	F string
	// Args is the function args.
	Args []Expression
	// Distinct only affetcts sum, avg, count, group_concat,
	// so we can ignore it in other functions
	Distinct bool

	distinctKey *int
}

// NewCall creates a Call expression with function name f, function args arg and
// a distinct flag whether this function supports distinct or not.
func NewCall(f string, args []Expression, distinct bool) (v Expression, err error) {
	x := builtin.Funcs[strings.ToLower(f)]
	if x.F == nil {
		return nil, errors.Errorf("undefined: %s", f)
	}

	if g, min, max := len(args), x.MinArgs, x.MaxArgs; g < min || (max != -1 && g > max) {
		a := []interface{}{}
		for _, v := range args {
			a = append(a, v)
		}
		return nil, badNArgs(min, f, a)
	}

	c := Call{F: f, Distinct: distinct, distinctKey: new(int)}
	for _, Val := range args {
		if !Val.IsStatic() {
			c.Args = append(c.Args, Val)
			continue
		}

		eVal, err := Val.Eval(nil, nil)
		if err != nil {
			return nil, err
		}

		c.Args = append(c.Args, Value{eVal})
	}

	return &c, nil
}

// Clone implements the Expression Clone interface.
func (c *Call) Clone() Expression {
	list := cloneExpressionList(c.Args)
	return &Call{F: c.F, Args: list, Distinct: c.Distinct}
}

// IsStatic implements the Expression IsStatic interface.
func (c *Call) IsStatic() bool {
	v := builtin.Funcs[strings.ToLower(c.F)]
	if v.F == nil || !v.IsStatic {
		return false
	}

	for _, v := range c.Args {
		if !v.IsStatic() {
			return false
		}
	}
	return true
}

// String implements the Expression String interface.
func (c *Call) String() string {
	distinct := ""
	if c.Distinct {
		distinct = "DISTINCT "
	}
	a := []string{}
	for _, v := range c.Args {
		a = append(a, v.String())
	}
	return fmt.Sprintf("%s(%s%s)", c.F, distinct, strings.Join(a, ", "))
}

// Eval implements the Expression Eval interface.
func (c *Call) Eval(ctx context.Context, args map[interface{}]interface{}) (v interface{}, err error) {
	f, ok := builtin.Funcs[strings.ToLower(c.F)]
	if !ok {
		return nil, errors.Errorf("unknown function %s", c.F)
	}

	a := make([]interface{}, len(c.Args))
	for i, arg := range c.Args {
		if v, err = arg.Eval(ctx, args); err != nil {
			return nil, err
		}
		a[i] = v
	}

	if c.distinctKey == nil {
		// create an unique distinct key if not.
		c.distinctKey = new(int)
	}

	if args != nil {
		args[builtin.ExprEvalFn] = c
		args[builtin.ExprEvalArgCtx] = ctx
		aggDistinct, ok := args[c.distinctKey]
		if !ok {
			// create an aggregate distinct if not.
			aggDistinct = builtin.CreateAggregateDistinct(c.F, c.Distinct)
			args[c.distinctKey] = aggDistinct
		}

		args[builtin.ExprAggDistinct] = aggDistinct
	}
	return f.F(a, args)
}

// Accept implements Expression Accept interface.
func (c *Call) Accept(v Visitor) (Expression, error) {
	return v.VisitCall(c)
}

func badNArgs(min int, s string, args []interface{}) error {
	a := []string{}
	for _, v := range args {
		a = append(a, fmt.Sprintf("%v", v))
	}
	switch len(args) < min {
	case true:
		return errors.Errorf("missing argument to %s(%s)", s, strings.Join(a, ", "))
	default: //case false:
		return errors.Errorf("too many arguments to %s(%s)", s, strings.Join(a, ", "))
	}
}
<commit_msg>expression: Address comment.<commit_after>// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.

// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package expression

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/expression/builtin"
)

var (
	_ Expression = (*Call)(nil)
)

// Call is for function expression.
type Call struct {
	// F is the function name.
	F string
	// Args is the function args.
	Args []Expression
	// Distinct only affetcts sum, avg, count, group_concat,
	// so we can ignore it in other functions
	Distinct bool

	// distinctKey is the unique key when using same Call object for different Eval args.
	// We have already use Call pointer to store aggregate result, so here we will need
	// another unique key to keep aggregate distincter.
	distinctKey *int
}

// NewCall creates a Call expression with function name f, function args arg and
// a distinct flag whether this function supports distinct or not.
func NewCall(f string, args []Expression, distinct bool) (v Expression, err error) {
	x := builtin.Funcs[strings.ToLower(f)]
	if x.F == nil {
		return nil, errors.Errorf("undefined: %s", f)
	}

	if g, min, max := len(args), x.MinArgs, x.MaxArgs; g < min || (max != -1 && g > max) {
		a := []interface{}{}
		for _, v := range args {
			a = append(a, v)
		}
		return nil, badNArgs(min, f, a)
	}

	c := Call{F: f, Distinct: distinct, distinctKey: new(int)}
	for _, Val := range args {
		if !Val.IsStatic() {
			c.Args = append(c.Args, Val)
			continue
		}

		eVal, err := Val.Eval(nil, nil)
		if err != nil {
			return nil, err
		}

		c.Args = append(c.Args, Value{eVal})
	}

	return &c, nil
}

// Clone implements the Expression Clone interface.
func (c *Call) Clone() Expression {
	list := cloneExpressionList(c.Args)
	return &Call{F: c.F, Args: list, Distinct: c.Distinct}
}

// IsStatic implements the Expression IsStatic interface.
func (c *Call) IsStatic() bool {
	v := builtin.Funcs[strings.ToLower(c.F)]
	if v.F == nil || !v.IsStatic {
		return false
	}

	for _, v := range c.Args {
		if !v.IsStatic() {
			return false
		}
	}
	return true
}

// String implements the Expression String interface.
func (c *Call) String() string {
	distinct := ""
	if c.Distinct {
		distinct = "DISTINCT "
	}
	a := []string{}
	for _, v := range c.Args {
		a = append(a, v.String())
	}
	return fmt.Sprintf("%s(%s%s)", c.F, distinct, strings.Join(a, ", "))
}

// Eval implements the Expression Eval interface.
func (c *Call) Eval(ctx context.Context, args map[interface{}]interface{}) (v interface{}, err error) {
	f, ok := builtin.Funcs[strings.ToLower(c.F)]
	if !ok {
		return nil, errors.Errorf("unknown function %s", c.F)
	}

	a := make([]interface{}, len(c.Args))
	for i, arg := range c.Args {
		if v, err = arg.Eval(ctx, args); err != nil {
			return nil, err
		}
		a[i] = v
	}

	if c.distinctKey == nil {
		// create an unique distinct key if not.
		c.distinctKey = new(int)
	}

	if args != nil {
		args[builtin.ExprEvalFn] = c
		args[builtin.ExprEvalArgCtx] = ctx
		aggDistinct, ok := args[c.distinctKey]
		if !ok {
			// create an aggregate distinct if not.
			aggDistinct = builtin.CreateAggregateDistinct(c.F, c.Distinct)
			args[c.distinctKey] = aggDistinct
		}

		args[builtin.ExprAggDistinct] = aggDistinct
	}
	return f.F(a, args)
}

// Accept implements Expression Accept interface.
func (c *Call) Accept(v Visitor) (Expression, error) {
	return v.VisitCall(c)
}

func badNArgs(min int, s string, args []interface{}) error {
	a := []string{}
	for _, v := range args {
		a = append(a, fmt.Sprintf("%v", v))
	}
	switch len(args) < min {
	case true:
		return errors.Errorf("missing argument to %s(%s)", s, strings.Join(a, ", "))
	default: //case false:
		return errors.Errorf("too many arguments to %s(%s)", s, strings.Join(a, ", "))
	}
}
<|endoftext|>


<commit_before>package practice

import "fmt"

func PrintAdd(x int, y int) {
	fmt.Println(add(x, y))
}

func add(x int, y int) int {
	return x + y
}
<commit_msg>Update cul.go omission args<commit_after>package practice

import "fmt"

func PrintAdd(x int, y int) {
	fmt.Println(add(x, y))
}

func add(x, y int) int {
	return x + y
}
<|endoftext|>


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

// Package opencensus contains Go support for OpenCensus.
package opencensus // import "go.opencensus.io"

// Version is the current release version of OpenCensus in use.
func Version() string {
	return "0.18.0"
}
<commit_msg>Bump version to 0.19.0 (#955)<commit_after>// Copyright 2017, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package opencensus contains Go support for OpenCensus.
package opencensus // import "go.opencensus.io"

// Version is the current release version of OpenCensus in use.
func Version() string {
	return "0.19.0"
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/openshift/origin/tools/rebasehelpers/util"
)

func main() {
	var start, end string
	flag.StringVar(&start, "start", "master", "The start of the revision range for analysis")
	flag.StringVar(&end, "end", "HEAD", "The end of the revision range for analysis")
	flag.Parse()

	commits, err := util.CommitsBetween(start, end)
	if err != nil {
		os.Stderr.WriteString(fmt.Sprintf("ERROR: couldn't find commits from %s..%s: %v\n", start, end, err))
		os.Exit(1)
	}

	// TODO: Filter out bump commits for now until we decide how to deal with
	// them correctly.
	nonbumpCommits := []util.Commit{}
	for _, commit := range commits {
		if commit.DeclaresUpstreamChange() &&
			!strings.HasPrefix(commit.Summary, "bump(") {
			nonbumpCommits = append(nonbumpCommits, commit)
		}
	}

	errs := []string{}
	for _, validate := range AllValidators {
		err := validate(nonbumpCommits)
		if err != nil {
			errs = append(errs, err.Error())
		}
	}

	if len(errs) > 0 {
		os.Stderr.WriteString(strings.Join(errs, "\n\n"))
		os.Exit(2)
	}
}
<commit_msg>Fix commit checker to find commits with upstream changes<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/openshift/origin/tools/rebasehelpers/util"
)

func main() {
	var start, end string
	flag.StringVar(&start, "start", "master", "The start of the revision range for analysis")
	flag.StringVar(&end, "end", "HEAD", "The end of the revision range for analysis")
	flag.Parse()

	commits, err := util.CommitsBetween(start, end)
	if err != nil {
		os.Stderr.WriteString(fmt.Sprintf("ERROR: couldn't find commits from %s..%s: %v\n", start, end, err))
		os.Exit(1)
	}

	// TODO: Filter out bump commits for now until we decide how to deal with
	// them correctly.
	nonbumpCommits := []util.Commit{}
	for _, commit := range commits {
		if !strings.HasPrefix(commit.Summary, "bump(") {
			nonbumpCommits = append(nonbumpCommits, commit)
		}
	}

	errs := []string{}
	for _, validate := range AllValidators {
		err := validate(nonbumpCommits)
		if err != nil {
			errs = append(errs, err.Error())
		}
	}

	if len(errs) > 0 {
		os.Stderr.WriteString(strings.Join(errs, "\n\n"))
		os.Exit(2)
	}
}
<|endoftext|>