<commit_before>package rerouting

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/fatih/goset"
	"github.com/streadway/amqp"
	"koding/tools/amqputil"
	"log"
	"sync"
)

type Consumer struct {
	Conn    *amqp.Connection
	Channel *amqp.Channel
}

type Producer struct {
	Conn    *amqp.Connection
	Channel *amqp.Channel
}

type authMsgJson struct {
	BindingExchange    string  `json:"bindingExchange"`
	BindingKey         string  `json:"bindingKey"`
	PublishingExchange *string `json:"publishingExchange"`
	RoutingKey         string  `json:"routingKey"`
}

type AuthMsg struct {
	BindingExchange    string
	BindingKey         string
	PublishingExchange string
	RoutingKey         string
}

type M map[string]interface{}

type Router struct {
	routes       M
	consumer     *Consumer
	producer     *Producer
	sync.RWMutex // protects routes
}

func NewRouter(c *Consumer, p *Producer) *Router {
	return &Router{
		routes:   M{},
		consumer: c,
		producer: p,
	}
}

func (r *Router) AddRoute(msg *amqp.Delivery) error {

	join, err := createAuthMsg(msg)
	if err != nil {
		return err
	}

	if (join.BindingExchange == "") || (join.BindingKey == "") || (join.RoutingKey == "") {
		return errors.New("Bad join message: Ignoring")
	}

	isNewBindingExchange := false

	if r.routes[join.BindingExchange] == nil {
		r.routes[join.BindingExchange] = M{}
		isNewBindingExchange = true
	}
	bindingExchange := r.routes[join.BindingExchange].(M)

	if bindingExchange[join.BindingKey] == nil {
		bindingExchange[join.BindingKey] = M{}
	}
	bindingKey := bindingExchange[join.BindingKey].(M)

	if bindingKey[join.PublishingExchange] == nil {
		bindingKey[join.PublishingExchange] = M{}
	}
	publishingExchange := bindingKey[join.PublishingExchange].(M)

	if routes, ok := publishingExchange[join.RoutingKey].(*goset.Set); ok {
		routes.Add(*join)
	} else {
		publishingExchange[join.RoutingKey] = goset.New(*join)
	}

	if isNewBindingExchange {
		go func() {
			if err := r.addBinding(join.BindingExchange); err != nil {
				log.Println(err)
			}
		}()
	}

	return nil
}

func (r *Router) RemoveRoute(msg *amqp.Delivery) error {

	leave, err := createAuthMsg(msg)
	if err != nil {
		return err
	}

	if r.routes[leave.BindingExchange] == nil {
		return fmt.Errorf("Unknown binding exchange: %s", leave.BindingExchange)
	}
	bindingExchange := r.routes[leave.BindingExchange].(M)

	if bindingExchange[leave.BindingKey] == nil {
		return fmt.Errorf("Unknown binding key: %s", leave.BindingKey)
	}
	bindingKey := bindingExchange[leave.BindingKey].(M)

	if bindingKey[leave.PublishingExchange] == nil {
		return fmt.Errorf("Unknown publishing exchange: %s", leave.BindingKey)
	}
	publishingExchange := bindingKey[leave.PublishingExchange].(M)

	if publishingExchange[leave.RoutingKey] == nil {
		return fmt.Errorf("Unknown routing key: %s", leave.RoutingKey)
	}
	routes := publishingExchange[leave.RoutingKey].(*goset.Set)

	for _, join := range routes.List() {
		if *leave == join.(AuthMsg) {
			routes.Remove(join)
		}
	}

	return nil

}

func (r *Router) publishTo(join *AuthMsg, msg *amqp.Delivery) error {
	err := r.producer.Channel.Publish(
		join.PublishingExchange,
		join.RoutingKey,
		false,
		false,
		amqp.Publishing{Headers: msg.Headers, Body: msg.Body},
	)

	return err
}

func (r *Router) addBinding(exchange string) error {

	r.RLock()
	c := amqputil.CreateChannel(r.consumer.Conn)
	r.RUnlock()

	var err error

	err = c.ExchangeDeclare(exchange, "topic", false, true, false, false, nil)
	if err != nil {
		log.Fatalf("exchange.declare: %s", err)
		return err
	}

	if _, err := c.QueueDeclare("", false, true, false, false, nil); err != nil {
		log.Fatalf("queue.declare: %s", err)
		return err
	}

	if err := c.QueueBind("", "#", exchange, false, nil); err != nil {
		log.Fatalf("queue.bind: %s", err)
		return err
	}

	deliveries, err := c.Consume("", "", true, false, false, false, nil)
	if err != nil {
		log.Fatalf("basic.consume: %s", err)
		return err
	}

	for msg := range deliveries {

		r.RLock()

		if r.routes[msg.Exchange] == nil {
			r.RUnlock()
			continue // drop it on the floor
		}
		bindingExchange := r.routes[msg.Exchange].(M)

		if bindingExchange[msg.RoutingKey] == nil {
			r.RUnlock()
			continue // drop it on the floor
		}
		bindingKey := bindingExchange[msg.RoutingKey].(M)

		for name := range bindingKey {
			publishingExchange := bindingKey[name].(M)

			for routingKey := range publishingExchange {
				routes := publishingExchange[routingKey].(*goset.Set)
				list := routes.List()

				for i := range list {
					joinMsg := list[i].(AuthMsg)
					if err := r.publishTo(&joinMsg, &msg); err != nil {
						log.Printf("WARNING: %v", err)
					}
				}
			}
		}

		r.RUnlock()
	}

	return nil
}

func createAuthMsg(msg *amqp.Delivery) (*AuthMsg, error) {
	var msgJson authMsgJson

	if err := json.Unmarshal(msg.Body, &msgJson); err != nil {
		return nil, err
	}

	authMsg := AuthMsg{
		BindingExchange: msgJson.BindingExchange,
		BindingKey:      msgJson.BindingKey,
		RoutingKey:      msgJson.RoutingKey,
	}

	if msgJson.PublishingExchange == nil {
		authMsg.PublishingExchange = "broker"
	} else {
		authMsg.PublishingExchange = *msgJson.PublishingExchange
	}

	return &authMsg, nil
}
<commit_msg>rerouting: annotations for streadway/amqp api<commit_after>package rerouting

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/fatih/goset"
	"github.com/streadway/amqp"
	"koding/tools/amqputil"
	"log"
	"sync"
)

type Consumer struct {
	Conn    *amqp.Connection
	Channel *amqp.Channel
}

type Producer struct {
	Conn    *amqp.Connection
	Channel *amqp.Channel
}

type authMsgJson struct {
	BindingExchange    string  `json:"bindingExchange"`
	BindingKey         string  `json:"bindingKey"`
	PublishingExchange *string `json:"publishingExchange"`
	RoutingKey         string  `json:"routingKey"`
}

type AuthMsg struct {
	BindingExchange    string
	BindingKey         string
	PublishingExchange string
	RoutingKey         string
}

type M map[string]interface{}

type Router struct {
	routes       M
	consumer     *Consumer
	producer     *Producer
	sync.RWMutex // protects routes
}

func NewRouter(c *Consumer, p *Producer) *Router {
	return &Router{
		routes:   M{},
		consumer: c,
		producer: p,
	}
}

func (r *Router) AddRoute(msg *amqp.Delivery) error {

	join, err := createAuthMsg(msg)
	if err != nil {
		return err
	}

	if (join.BindingExchange == "") || (join.BindingKey == "") || (join.RoutingKey == "") {
		return errors.New("Bad join message: Ignoring")
	}

	isNewBindingExchange := false

	if r.routes[join.BindingExchange] == nil {
		r.routes[join.BindingExchange] = M{}
		isNewBindingExchange = true
	}
	bindingExchange := r.routes[join.BindingExchange].(M)

	if bindingExchange[join.BindingKey] == nil {
		bindingExchange[join.BindingKey] = M{}
	}
	bindingKey := bindingExchange[join.BindingKey].(M)

	if bindingKey[join.PublishingExchange] == nil {
		bindingKey[join.PublishingExchange] = M{}
	}
	publishingExchange := bindingKey[join.PublishingExchange].(M)

	if routes, ok := publishingExchange[join.RoutingKey].(*goset.Set); ok {
		routes.Add(*join)
	} else {
		publishingExchange[join.RoutingKey] = goset.New(*join)
	}

	if isNewBindingExchange {
		go func() {
			if err := r.addBinding(join.BindingExchange); err != nil {
				log.Println(err)
			}
		}()
	}

	return nil
}

func (r *Router) RemoveRoute(msg *amqp.Delivery) error {

	leave, err := createAuthMsg(msg)
	if err != nil {
		return err
	}

	if r.routes[leave.BindingExchange] == nil {
		return fmt.Errorf("Unknown binding exchange: %s", leave.BindingExchange)
	}
	bindingExchange := r.routes[leave.BindingExchange].(M)

	if bindingExchange[leave.BindingKey] == nil {
		return fmt.Errorf("Unknown binding key: %s", leave.BindingKey)
	}
	bindingKey := bindingExchange[leave.BindingKey].(M)

	if bindingKey[leave.PublishingExchange] == nil {
		return fmt.Errorf("Unknown publishing exchange: %s", leave.BindingKey)
	}
	publishingExchange := bindingKey[leave.PublishingExchange].(M)

	if publishingExchange[leave.RoutingKey] == nil {
		return fmt.Errorf("Unknown routing key: %s", leave.RoutingKey)
	}
	routes := publishingExchange[leave.RoutingKey].(*goset.Set)

	for _, join := range routes.List() {
		if *leave == join.(AuthMsg) {
			routes.Remove(join)
		}
	}

	return nil

}

func (r *Router) publishTo(join *AuthMsg, msg *amqp.Delivery) error {
	return r.producer.Channel.Publish(
		join.PublishingExchange, // exchange name
		join.RoutingKey,         // routing key
		false,                   // mandatory
		false,                   // immediate
		amqp.Publishing{Headers: msg.Headers, Body: msg.Body}, // args
	)
}

func (r *Router) addBinding(exchange string) error {

	r.RLock()
	c := amqputil.CreateChannel(r.consumer.Conn)
	r.RUnlock()

	var err error

	err = c.ExchangeDeclare(
		exchange, // exchange name
		"topic",  // exchange type
		false,    // durable
		true,     // auto-delete
		false,    // internal
		false,    // no-wait
		nil,      // args
	)
	if err != nil {
		log.Fatalf("exchange.declare: %s", err)
		return err
	}

	if _, err := c.QueueDeclare(
		"",    // queue name
		false, // durable
		true,  // auto-delete
		false, // exclusive
		false, // no-wait
		nil,   // args
	); err != nil {
		log.Fatalf("queue.declare: %s", err)
		return err
	}

	if err := c.QueueBind(
		"",       // queue name
		"#",      // routing key
		exchange, // exchange name
		false,    // no-wait
		nil,      // args
	); err != nil {
		log.Fatalf("queue.bind: %s", err)
		return err
	}

	deliveries, err := c.Consume(
		"",    // queue name
		"",    // consumer tag
		true,  // auto-ack
		false, // exclusive
		false, // no-local
		false, // no-wait
		nil,   // args
	)
	if err != nil {
		log.Fatalf("basic.consume: %s", err)
		return err
	}

	for msg := range deliveries {

		r.RLock()

		if r.routes[msg.Exchange] == nil {
			r.RUnlock()
			continue // drop it on the floor
		}
		bindingExchange := r.routes[msg.Exchange].(M)

		if bindingExchange[msg.RoutingKey] == nil {
			r.RUnlock()
			continue // drop it on the floor
		}
		bindingKey := bindingExchange[msg.RoutingKey].(M)

		for name := range bindingKey {
			publishingExchange := bindingKey[name].(M)

			for routingKey := range publishingExchange {
				routes := publishingExchange[routingKey].(*goset.Set)
				list := routes.List()

				for i := range list {
					joinMsg := list[i].(AuthMsg)
					if err := r.publishTo(&joinMsg, &msg); err != nil {
						log.Printf("WARNING: %v", err)
					}
				}
			}
		}

		r.RUnlock()
	}

	return nil
}

func createAuthMsg(msg *amqp.Delivery) (*AuthMsg, error) {
	var msgJson authMsgJson

	if err := json.Unmarshal(msg.Body, &msgJson); err != nil {
		return nil, err
	}

	authMsg := AuthMsg{
		BindingExchange: msgJson.BindingExchange,
		BindingKey:      msgJson.BindingKey,
		RoutingKey:      msgJson.RoutingKey,
	}

	if msgJson.PublishingExchange == nil {
		authMsg.PublishingExchange = "broker"
	} else {
		authMsg.PublishingExchange = *msgJson.PublishingExchange
	}

	return &authMsg, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess 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 vtgate

import (
	"context"
	"testing"
	"time"

	"vitess.io/vitess/go/sync2"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/mysql"
)

func TestLockUnlock(t *testing.T) {
	conn, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	assertMatches(t, conn, `select release_lock('lock name')`, `[[NULL]]`)
	assertMatches(t, conn, `select get_lock('lock name', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select get_lock('lock name', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select is_free_lock('lock name')`, `[[INT64(0)]]`)
	assert.NotEmpty(t,
		exec(t, conn, `select is_used_lock('lock name')`))
	assertMatches(t, conn, `select release_lock('lock name')`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select release_all_locks()`, `[[UINT64(1)]]`)
	assertMatches(t, conn, `select release_lock('lock name')`, `[[NULL]]`)
}

func TestLocksDontIntersect(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock1', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select get_lock('lock2', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn1, `select release_lock('lock1')`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select release_lock('lock2')`, `[[INT64(1)]]`)
}

func TestLocksAreExplicitlyReleaseAndRegrab(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
}

func TestLocksAreReleasedWhenConnectionIsClosed(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	conn1.Close()

	assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
}

func TestLocksBlockEachOther(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	// in the first connection, grab a lock
	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)

	released := sync2.NewAtomicBool(false)

	go func() {
		conn2, err := mysql.Connect(context.Background(), &vtParams)
		require.NoError(t, err)
		defer conn2.Close()

		// in the second connection, we try to grab a lock, and should get blocked
		assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
		assert.True(t, released.Get(), "was not blocked by get_lock")
		assertMatches(t, conn2, `select release_lock('lock')`, `[[INT64(1)]]`)
	}()

	time.Sleep(1 * time.Second)

	released.Set(true)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
}

func TestLocksBlocksWithTx(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	// in the first connection, grab a lock
	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	exec(t, conn1, "begin")
	exec(t, conn1, "insert into t1(id1, id2) values(1,1)") // -80
	exec(t, conn1, "commit")

	released := sync2.NewAtomicBool(false)

	go func() {
		conn2, err := mysql.Connect(context.Background(), &vtParams)
		require.NoError(t, err)
		defer conn2.Close()

		// in the second connection, we try to grab a lock, and should get blocked
		assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
		assert.True(t, released.Get(), "was not blocked by get_lock")
		assertMatches(t, conn2, `select release_lock('lock')`, `[[INT64(1)]]`)
	}()

	time.Sleep(1 * time.Second)

	released.Set(true)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
	exec(t, conn1, "delete from t1")
}
<commit_msg>added tx and lock related endtoend test<commit_after>/*
Copyright 2020 The Vitess 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 vtgate

import (
	"context"
	"fmt"
	"testing"
	"time"

	"vitess.io/vitess/go/sync2"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/mysql"
)

func TestLockUnlock(t *testing.T) {
	conn, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	assertMatches(t, conn, `select release_lock('lock name')`, `[[NULL]]`)
	assertMatches(t, conn, `select get_lock('lock name', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select get_lock('lock name', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select is_free_lock('lock name')`, `[[INT64(0)]]`)
	assert.NotEmpty(t,
		exec(t, conn, `select is_used_lock('lock name')`))
	assertMatches(t, conn, `select release_lock('lock name')`, `[[INT64(1)]]`)
	assertMatches(t, conn, `select release_all_locks()`, `[[UINT64(1)]]`)
	assertMatches(t, conn, `select release_lock('lock name')`, `[[NULL]]`)
}

func TestLocksDontIntersect(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock1', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select get_lock('lock2', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn1, `select release_lock('lock1')`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select release_lock('lock2')`, `[[INT64(1)]]`)
}

func TestLocksIntersect(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock1', 100)`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select get_lock('lock2', 100)`, `[[INT64(1)]]`)

	// Locks will not succeed.
	assertMatches(t, conn1, `select get_lock('lock2', 1)`, `[[INT64(0)]]`)
	assertMatches(t, conn2, `select get_lock('lock1', 1)`, `[[INT64(0)]]`)
	assertMatches(t, conn1, `select release_lock('lock2')`, `[[INT64(0)]]`)
	assertMatches(t, conn2, `select release_lock('lock1')`, `[[INT64(0)]]`)

	assertMatches(t, conn1, `select release_lock('lock1')`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select release_lock('lock2')`, `[[INT64(1)]]`)
}

func TestLocksAreExplicitlyReleaseAndRegrab(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
}

func TestLocksAreReleasedWhenConnectionIsClosed(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()
	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	conn1.Close()

	assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
}

func TestLocksBlockEachOther(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	// in the first connection, grab a lock
	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)

	released := sync2.NewAtomicBool(false)

	go func() {
		conn2, err := mysql.Connect(context.Background(), &vtParams)
		require.NoError(t, err)
		defer conn2.Close()

		// in the second connection, we try to grab a lock, and should get blocked
		assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
		assert.True(t, released.Get(), "was not blocked by get_lock")
		assertMatches(t, conn2, `select release_lock('lock')`, `[[INT64(1)]]`)
	}()

	time.Sleep(1 * time.Second)

	released.Set(true)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
}

func TestLocksBlocksWithTx(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	// in the first connection, grab a lock
	assertMatches(t, conn1, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	exec(t, conn1, "begin")
	exec(t, conn1, "insert into t1(id1, id2) values(1,1)") // -80
	exec(t, conn1, "commit")

	released := sync2.NewAtomicBool(false)

	go func() {
		conn2, err := mysql.Connect(context.Background(), &vtParams)
		require.NoError(t, err)
		defer conn2.Close()

		// in the second connection, we try to grab a lock, and should get blocked
		assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
		assert.True(t, released.Get(), "was not blocked by get_lock")
		assertMatches(t, conn2, `select release_lock('lock')`, `[[INT64(1)]]`)
	}()

	time.Sleep(1 * time.Second)

	released.Set(true)
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
	exec(t, conn1, "delete from t1")
}

func TestLocksWithTxFailure(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	// in the first connection, grab a lock for infinite time
	assertMatches(t, conn1, `select get_lock('lock', -1)`, `[[INT64(1)]]`)

	exec(t, conn1, "use `ks:80-`")
	exec(t, conn1, "begin")
	qr := exec(t, conn1, "select connection_id()")
	exec(t, conn1, "use ks")
	// kill the mysql connection shard which has transaction open.
	vttablet1 := clusterInstance.Keyspaces[0].Shards[1].MasterTablet() // 80-
	vttablet1.VttabletProcess.QueryTablet(fmt.Sprintf("kill %s", qr.Rows[0][0].ToString()), KeyspaceName, false)

	// transaction fails on commit.
	_, err = conn1.ExecuteFetch("commit", 1, true)
	require.Error(t, err)

	// in the second connection, lock acquisition succeeds.
	assertMatches(t, conn2, `select get_lock('lock', 2)`, `[[INT64(1)]]`)
	assertMatches(t, conn2, `select release_lock('lock')`, `[[INT64(1)]]`)
}

func TestLocksWithTxOngoingAndReleaseLock(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	assertMatches(t, conn1, `select get_lock('lock', -1)`, `[[INT64(1)]]`)
	exec(t, conn1, "begin")
	exec(t, conn1, "insert into t1(id1, id2) values(1,1)")
	assertMatches(t, conn1, `select release_lock('lock')`, `[[INT64(1)]]`)
	assertMatches(t, conn1, `select id1, id2 from t1 where id1 = 1`, `[[INT64(1) INT64(1)]]`)
	exec(t, conn1, "rollback")
	assertIsEmpty(t, conn1, `select id1, id2 from t1 where id1 = 1`)
}

func TestLocksWithTxOngoingAndLockFails(t *testing.T) {
	conn1, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn1.Close()

	conn2, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn2.Close()

	assertMatches(t, conn2, `select get_lock('lock', -1)`, `[[INT64(1)]]`)

	exec(t, conn1, "begin")
	exec(t, conn1, "insert into t1(id1, id2) values(1,1)")
	assertMatches(t, conn1, `select get_lock('lock', 1)`, `[[INT64(0)]]`)
	assertMatches(t, conn1, `select id1, id2 from t1 where id1 = 1`, `[[INT64(1) INT64(1)]]`)
	exec(t, conn1, "rollback")
	assertIsEmpty(t, conn1, `select id1, id2 from t1 where id1 = 1`)

	assertMatches(t, conn2, `select get_lock('lock', -1)`, `[[INT64(1)]]`)
}
<|endoftext|>


<commit_before>package espsdk

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

	log "github.com/Sirupsen/logrus"
)

// A Contribution is the metadata that represents a media asset from
// a contributor.
type Contribution struct {
	AdditionalFacialExpressions string            `json:"additional_facial_expressions,omitempty"`
	AlternateID                 string            `json:"alternate_id,omitempty"`
	CallForImage                bool              `json:"call_for_image,omitempty"`
	CameraShotDate              string            `json:"camera_shot_date,omitempty"`
	Caption                     string            `json:"caption,omitempty"`
	City                        string            `json:"city,omitempty"`
	CollectionCode              string            `json:"collection_code,omitempty"`
	ContentProviderName         string            `json:"content_provider_name,omitempty"`
	ContentProviderTitle        string            `json:"content_provider_title,omitempty"`
	ContentWarnings             string            `json:"content_warnings,omitempty"`
	Copyright                   string            `json:"copyright,omitempty"`
	CountryOfShoot              string            `json:"country_of_shoot,omitempty"`
	CreatedAt                   *time.Time        `json:"created_at,omitempty"`
	CreatedDate                 *time.Time        `json:"created_date,omitempty"`
	CreditLine                  string            `json:"credit_line,omitempty"`
	Errors                      map[string]string `json:"errors,omitempty"`
	EventID                     string            `json:"event_id,omitempty"`
	ExclusionRoutes             string            `json:"exclusion_routes,omitempty"`
	ExclusiveCoverage           bool              `json:"exclusive_coverage,omitempty"`
	ExternalFileLocation        string            `json:"external_file_location,omitempty"`
	ExtractedMetadataPresent    bool              `json:"extracted_metadata_present,omitempty"`
	FacialExpressions           string            `json:"facial_expressions,omitempty"`
	FileName                    string            `json:"file_name,omitempty"`
	FilePath                    string            `json:"file_path,omitempty"`
	FileUploaded                bool              `json:"file_uploaded,omitempty"`
	FinalBucket                 string            `json:"final_bucket,omitempty"`
	Headline                    string            `json:"headline,omitempty"`
	ID                          int               `json:"id,omitempty"`
	ImageHeight                 int               `json:"image_height,omitempty"`
	ImageWidth                  int               `json:"image_width,omitempty"`
	InactiveDate                string            `json:"inactive_date,omitempty"`
	InclusionRoutes             string            `json:"inclusion_routes,omitempty"`
	IptcCaptionWriter           string            `json:"iptc_caption_writer,omitempty"`
	IptcCategory                string            `json:"iptc_category,omitempty"`
	IptcSubjects                []string          `json:"iptc_subjects,omitempty"`
	Keywords                    []string          `json:"keywords,omitempty"`
	MasterID                    string            `json:"master_id,omitempty"`
	MediaType                   string            `json:"media_type,omitempty"`
	MetadataExtractionStartedAt *time.Time        `json:"metadata_extraction_started_at,omitempty"`
	MetadataExtractionTimeout   bool              `json:"metadata_extraction_timeout,omitempty"`
	MimeType                    string            `json:"mime_type,omitempty"`
	NumberOfPeople              string            `json:"string,omitempty"`
	PaidAssignment              bool              `json:"paid_assignment,omitempty"`
	PaidAssignmentID            string            `json:"paid_assignment_id,omitempty"`
	ParentSource                string            `json:"parent_source,omitempty"`
	PersonCompositions          string            `json:"person_compositions,omitempty"`
	Personalities               []string          `json:"personalities,omitempty"`
	PicscoutSuggestions         string            `json:"picscout_suggestions,omitempty"`
	ProvinceState               string            `json:"province_state,omitempty"`
	PublicistApprovalRequired   bool              `json:"publicist_approval_required,omitempty"`
	PublishedAt                 *time.Time        `json:"published_at,omitempty"`
	PulledReason                string            `json:"pulled_reason,omitempty"`
	Rank                        int               `json:"rank,omitempty"`
	ReadyForSale                bool              `json:"ready_for_sale,omitempty"`
	RecordedDate                string            `json:"recorded_date,omitempty"`
	RiskCategory                string            `json:"risk_category,omitempty"`
	ShotSpeed                   string            `json:"shot_speed,omitempty"`
	SiteDestination             []string          `json:"site_destination,omitempty"`
	Source                      string            `json:"source,omitempty"`
	SpecialInstructions         string            `json:"special_instructions,omitempty"`
	Status                      string            `json:"status,omitempty"`
	StorageURL                  string            `json:"storage_url,omitempty"`
	SubmissionBatchID           int               `json:"submission_batch_id,omitempty"`
	Submittable                 bool              `json:"submittable,omitempty"`
	SubmittedAt                 *time.Time        `json:"submitted_at,omitempty"`
	SubmittedToReviewAt         string            `json:"submitted_to_review_at,omitempty"`
	ThumbnailURL                string            `json:"thumbnail_url,omitempty"`
	UpdatedAt                   *time.Time        `json:"updated_at,omitempty"`
	UploadBucket                string            `json:"upload_bucket,omitempty"`
	UploadID                    string            `json:"upload_id,omitempty"`
	UserMetadataValid           bool              `json:"user_metadata_valid,omitempty"`
	VisualColor                 string            `json:"visual_color,omitempty"`
}

// Index requests a list of all Contributions associated with the specified
// Submission Batch.
func (c Contribution) Index(client *Client, batchID int) ContributionList {
	c.SubmissionBatchID = batchID
	return ContributionList{}.Unmarshal(client.get(c.Path()))
}

// Path returns the path for the contribution.
// If the Contribution has no ID, Path returns the root for all
// contributions for the Batch (the Contribution Index).
func (c Contribution) Path() string {
	bid := c.SubmissionBatchID
	if c.ID == 0 {
		return fmt.Sprintf("%s/%d/contributions", Batches, bid)
	}
	return fmt.Sprintf("%s/%d/contributions/%d", Batches, bid, c.ID)
}

// Marshal serializes the Contribution into a byte slice.
func (c Contribution) Marshal() ([]byte, error) { return indentedJSON(c) }

// A ContributionUpdate contains a Contribution. This matches the
// structure of the JSON payload the API expects during a PUT.
type ContributionUpdate struct {
	Contribution Contribution `json:"contribution"`
}

// Marshal serializes a ContributionUpdate into a byte slice.
func (c ContributionUpdate) Marshal() ([]byte, error) { return indentedJSON(c) }

// Path returns the path of the contribution being updated.
func (c ContributionUpdate) Path() string { return c.Contribution.Path() }

// A ContributionList is a slice of zero or more Contributions.
type ContributionList []Contribution

// Unmarshal attempts to deserialize the provided JSON payload
// into the complete metadata returned by a request to the Index (GET all)
// API endpoint.
func (cl ContributionList) Unmarshal(payload []byte) ContributionList {
	var contributionList ContributionList
	if err := json.Unmarshal(payload, &contributionList); err != nil {
		log.Fatal(err)
	}
	return contributionList
}
<commit_msg>capitalize entire acronym<commit_after>package espsdk

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

	log "github.com/Sirupsen/logrus"
)

// A Contribution is the metadata that represents a media asset from
// a contributor.
type Contribution struct {
	AdditionalFacialExpressions string            `json:"additional_facial_expressions,omitempty"`
	AlternateID                 string            `json:"alternate_id,omitempty"`
	CallForImage                bool              `json:"call_for_image,omitempty"`
	CameraShotDate              string            `json:"camera_shot_date,omitempty"`
	Caption                     string            `json:"caption,omitempty"`
	City                        string            `json:"city,omitempty"`
	CollectionCode              string            `json:"collection_code,omitempty"`
	ContentProviderName         string            `json:"content_provider_name,omitempty"`
	ContentProviderTitle        string            `json:"content_provider_title,omitempty"`
	ContentWarnings             string            `json:"content_warnings,omitempty"`
	Copyright                   string            `json:"copyright,omitempty"`
	CountryOfShoot              string            `json:"country_of_shoot,omitempty"`
	CreatedAt                   *time.Time        `json:"created_at,omitempty"`
	CreatedDate                 *time.Time        `json:"created_date,omitempty"`
	CreditLine                  string            `json:"credit_line,omitempty"`
	Errors                      map[string]string `json:"errors,omitempty"`
	EventID                     string            `json:"event_id,omitempty"`
	ExclusionRoutes             string            `json:"exclusion_routes,omitempty"`
	ExclusiveCoverage           bool              `json:"exclusive_coverage,omitempty"`
	ExternalFileLocation        string            `json:"external_file_location,omitempty"`
	ExtractedMetadataPresent    bool              `json:"extracted_metadata_present,omitempty"`
	FacialExpressions           string            `json:"facial_expressions,omitempty"`
	FileName                    string            `json:"file_name,omitempty"`
	FilePath                    string            `json:"file_path,omitempty"`
	FileUploaded                bool              `json:"file_uploaded,omitempty"`
	FinalBucket                 string            `json:"final_bucket,omitempty"`
	Headline                    string            `json:"headline,omitempty"`
	ID                          int               `json:"id,omitempty"`
	ImageHeight                 int               `json:"image_height,omitempty"`
	ImageWidth                  int               `json:"image_width,omitempty"`
	InactiveDate                string            `json:"inactive_date,omitempty"`
	InclusionRoutes             string            `json:"inclusion_routes,omitempty"`
	IPTCCaptionWriter           string            `json:"iptc_caption_writer,omitempty"`
	IPTCCategory                string            `json:"iptc_category,omitempty"`
	IPTCSubjects                []string          `json:"iptc_subjects,omitempty"`
	Keywords                    []string          `json:"keywords,omitempty"`
	MasterID                    string            `json:"master_id,omitempty"`
	MediaType                   string            `json:"media_type,omitempty"`
	MetadataExtractionStartedAt *time.Time        `json:"metadata_extraction_started_at,omitempty"`
	MetadataExtractionTimeout   bool              `json:"metadata_extraction_timeout,omitempty"`
	MimeType                    string            `json:"mime_type,omitempty"`
	NumberOfPeople              string            `json:"string,omitempty"`
	PaidAssignment              bool              `json:"paid_assignment,omitempty"`
	PaidAssignmentID            string            `json:"paid_assignment_id,omitempty"`
	ParentSource                string            `json:"parent_source,omitempty"`
	PersonCompositions          string            `json:"person_compositions,omitempty"`
	Personalities               []string          `json:"personalities,omitempty"`
	PicscoutSuggestions         string            `json:"picscout_suggestions,omitempty"`
	ProvinceState               string            `json:"province_state,omitempty"`
	PublicistApprovalRequired   bool              `json:"publicist_approval_required,omitempty"`
	PublishedAt                 *time.Time        `json:"published_at,omitempty"`
	PulledReason                string            `json:"pulled_reason,omitempty"`
	Rank                        int               `json:"rank,omitempty"`
	ReadyForSale                bool              `json:"ready_for_sale,omitempty"`
	RecordedDate                string            `json:"recorded_date,omitempty"`
	RiskCategory                string            `json:"risk_category,omitempty"`
	ShotSpeed                   string            `json:"shot_speed,omitempty"`
	SiteDestination             []string          `json:"site_destination,omitempty"`
	Source                      string            `json:"source,omitempty"`
	SpecialInstructions         string            `json:"special_instructions,omitempty"`
	Status                      string            `json:"status,omitempty"`
	StorageURL                  string            `json:"storage_url,omitempty"`
	SubmissionBatchID           int               `json:"submission_batch_id,omitempty"`
	Submittable                 bool              `json:"submittable,omitempty"`
	SubmittedAt                 *time.Time        `json:"submitted_at,omitempty"`
	SubmittedToReviewAt         string            `json:"submitted_to_review_at,omitempty"`
	ThumbnailURL                string            `json:"thumbnail_url,omitempty"`
	UpdatedAt                   *time.Time        `json:"updated_at,omitempty"`
	UploadBucket                string            `json:"upload_bucket,omitempty"`
	UploadID                    string            `json:"upload_id,omitempty"`
	UserMetadataValid           bool              `json:"user_metadata_valid,omitempty"`
	VisualColor                 string            `json:"visual_color,omitempty"`
}

// Index requests a list of all Contributions associated with the specified
// Submission Batch.
func (c Contribution) Index(client *Client, batchID int) ContributionList {
	c.SubmissionBatchID = batchID
	return ContributionList{}.Unmarshal(client.get(c.Path()))
}

// Path returns the path for the contribution.
// If the Contribution has no ID, Path returns the root for all
// contributions for the Batch (the Contribution Index).
func (c Contribution) Path() string {
	bid := c.SubmissionBatchID
	if c.ID == 0 {
		return fmt.Sprintf("%s/%d/contributions", Batches, bid)
	}
	return fmt.Sprintf("%s/%d/contributions/%d", Batches, bid, c.ID)
}

// Marshal serializes the Contribution into a byte slice.
func (c Contribution) Marshal() ([]byte, error) { return indentedJSON(c) }

// A ContributionUpdate contains a Contribution. This matches the
// structure of the JSON payload the API expects during a PUT.
type ContributionUpdate struct {
	Contribution Contribution `json:"contribution"`
}

// Marshal serializes a ContributionUpdate into a byte slice.
func (c ContributionUpdate) Marshal() ([]byte, error) { return indentedJSON(c) }

// Path returns the path of the contribution being updated.
func (c ContributionUpdate) Path() string { return c.Contribution.Path() }

// A ContributionList is a slice of zero or more Contributions.
type ContributionList []Contribution

// Unmarshal attempts to deserialize the provided JSON payload
// into the complete metadata returned by a request to the Index (GET all)
// API endpoint.
func (cl ContributionList) Unmarshal(payload []byte) ContributionList {
	var contributionList ContributionList
	if err := json.Unmarshal(payload, &contributionList); err != nil {
		log.Fatal(err)
	}
	return contributionList
}
<|endoftext|>


<commit_before>// Copyright 2016 LINE Corporation
//
// LINE Corporation licenses this file to you 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 linebot

const version = "1.0.0"
<commit_msg>Delete version.go<commit_after><|endoftext|>


<commit_before>package app

import (
	"encoding/json"
	"fmt"
	"github.com/DanielRenne/GoCore/core/dbServices"
	"github.com/DanielRenne/GoCore/core/fileCache"
	"github.com/DanielRenne/GoCore/core/ginServer"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

type WebSocketAPIObj struct {
	Data struct {
		//ServerPropertyID int    `json:"ServerPropertyId"`
		Controller string `json:"controller"`
		Method     string `json:"method"`
		CallBackID int    `json:"callBackId"`
	} `json:"data"`
}

func Initialize(path string) {
	serverSettings.Initialize(path)
	dbServices.Initialize()

	if serverSettings.WebConfig.Application.ReleaseMode == "release" {
		ginServer.Initialize(gin.ReleaseMode)
	} else {
		ginServer.Initialize(gin.DebugMode)
	}

	fileCache.Initialize()

}

func Run() {

	if serverSettings.WebConfig.Application.WebServiceOnly == false {

		loadHTMLTemplates()

		ginServer.Router.Static("/web", serverSettings.APP_LOCATION+"/web")

		ginServer.Router.GET("/ws", func(c *gin.Context) {
			webSocketHandler(c.Writer, c.Request)
		})
	}

	initializeStaticRoutes()

	go ginServer.Router.RunTLS(":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort), serverSettings.APP_LOCATION+"/keys/cert.pem", serverSettings.APP_LOCATION+"/keys/key.pem")

	ginServer.Router.Run(":" + strconv.Itoa(serverSettings.WebConfig.Application.HttpPort))

	// go ginServer.Router.GET("/", func(c *gin.Context) {
	// 	c.Redirect(http.StatusMovedPermanently, "https://"+serverSettings.WebConfig.Application.Domain+":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort))
	// })

}

func webSocketHandler(w http.ResponseWriter, r *http.Request) {

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	for {
		messageType, p, err := conn.ReadMessage()

		var wsAPIObj WebSocketAPIObj
		json.Unmarshal(p, &wsAPIObj)

		// Loop over structs and display them.
		// for l := range languages {
		fmt.Printf("controller = %v, method = %v", wsAPIObj.Data.Controller, wsAPIObj.Data.Method)
		fmt.Println()
		// }

		log.Println(string(p[:]))

		if err != nil {
			return
		}
		if err = conn.WriteMessage(messageType, p); err != nil {
			return
		}
	}

}

func loadHTMLTemplates() {

	if serverSettings.WebConfig.Application.HtmlTemplates.Enabled {

		levels := "/*"
		dirLevel := ""

		switch serverSettings.WebConfig.Application.HtmlTemplates.DirectoryLevels {
		case 0:
			levels = "/*"
			dirLevel = ""
		case 1:
			levels = "/**/*"
			dirLevel = "root/"
		case 2:
			levels = "/**/**/*"
			dirLevel = "root/root/"
		}

		ginServer.Router.LoadHTMLGlob(serverSettings.APP_LOCATION + "/web/" + serverSettings.WebConfig.Application.HtmlTemplates.Directory + levels)

		ginServer.Router.GET("", func(c *gin.Context) {
			c.HTML(http.StatusOK, dirLevel+"index.tmpl", gin.H{})
		})
	} else {

		if serverSettings.WebConfig.Application.DisableRootIndex {
			return
		}

		ginServer.Router.GET("", func(c *gin.Context) {
			if serverSettings.WebConfig.Application.RootIndexPath == "" {
				ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/index.htm", c)
			} else {
				ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/"+serverSettings.WebConfig.Application.RootIndexPath, c)
			}
		})
	}
}

func initializeStaticRoutes() {

	ginServer.Router.GET("/swagger", func(c *gin.Context) {
		// c.Redirect(http.StatusMovedPermanently, "https://"+serverSettings.WebConfig.Application.Domain+":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort)+"/web/swagger/dist/index.html")

		ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/swagger/dist/index.html", c)
	})
}
<commit_msg>Alert when up and running<commit_after>package app

import (
	"encoding/json"
	"fmt"
	"github.com/DanielRenne/GoCore/core/dbServices"
	"github.com/DanielRenne/GoCore/core/fileCache"
	"github.com/DanielRenne/GoCore/core/ginServer"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

type WebSocketAPIObj struct {
	Data struct {
		//ServerPropertyID int    `json:"ServerPropertyId"`
		Controller string `json:"controller"`
		Method     string `json:"method"`
		CallBackID int    `json:"callBackId"`
	} `json:"data"`
}

func Initialize(path string) {
	serverSettings.Initialize(path)
	dbServices.Initialize()

	if serverSettings.WebConfig.Application.ReleaseMode == "release" {
		ginServer.Initialize(gin.ReleaseMode)
	} else {
		ginServer.Initialize(gin.DebugMode)
	}

	fileCache.Initialize()

}

func Run() {

	if serverSettings.WebConfig.Application.WebServiceOnly == false {

		loadHTMLTemplates()

		ginServer.Router.Static("/web", serverSettings.APP_LOCATION+"/web")

		ginServer.Router.GET("/ws", func(c *gin.Context) {
			webSocketHandler(c.Writer, c.Request)
		})
	}

	initializeStaticRoutes()

	go ginServer.Router.RunTLS(":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort), serverSettings.APP_LOCATION+"/keys/cert.pem", serverSettings.APP_LOCATION+"/keys/key.pem")

	ginServer.Router.Run(":" + strconv.Itoa(serverSettings.WebConfig.Application.HttpPort))

	fmt.Printf("GoCore Application Started")
	// go ginServer.Router.GET("/", func(c *gin.Context) {
	// 	c.Redirect(http.StatusMovedPermanently, "https://"+serverSettings.WebConfig.Application.Domain+":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort))
	// })

}

func webSocketHandler(w http.ResponseWriter, r *http.Request) {

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	for {
		messageType, p, err := conn.ReadMessage()

		var wsAPIObj WebSocketAPIObj
		json.Unmarshal(p, &wsAPIObj)

		// Loop over structs and display them.
		// for l := range languages {
		fmt.Printf("controller = %v, method = %v", wsAPIObj.Data.Controller, wsAPIObj.Data.Method)
		fmt.Println()
		// }

		log.Println(string(p[:]))

		if err != nil {
			return
		}
		if err = conn.WriteMessage(messageType, p); err != nil {
			return
		}
	}

}

func loadHTMLTemplates() {

	if serverSettings.WebConfig.Application.HtmlTemplates.Enabled {

		levels := "/*"
		dirLevel := ""

		switch serverSettings.WebConfig.Application.HtmlTemplates.DirectoryLevels {
		case 0:
			levels = "/*"
			dirLevel = ""
		case 1:
			levels = "/**/*"
			dirLevel = "root/"
		case 2:
			levels = "/**/**/*"
			dirLevel = "root/root/"
		}

		ginServer.Router.LoadHTMLGlob(serverSettings.APP_LOCATION + "/web/" + serverSettings.WebConfig.Application.HtmlTemplates.Directory + levels)

		ginServer.Router.GET("", func(c *gin.Context) {
			c.HTML(http.StatusOK, dirLevel+"index.tmpl", gin.H{})
		})
	} else {

		if serverSettings.WebConfig.Application.DisableRootIndex {
			return
		}

		ginServer.Router.GET("", func(c *gin.Context) {
			if serverSettings.WebConfig.Application.RootIndexPath == "" {
				ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/index.htm", c)
			} else {
				ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/"+serverSettings.WebConfig.Application.RootIndexPath, c)
			}
		})
	}
}

func initializeStaticRoutes() {

	ginServer.Router.GET("/swagger", func(c *gin.Context) {
		// c.Redirect(http.StatusMovedPermanently, "https://"+serverSettings.WebConfig.Application.Domain+":"+strconv.Itoa(serverSettings.WebConfig.Application.HttpsPort)+"/web/swagger/dist/index.html")

		ginServer.ReadHTMLFile(serverSettings.APP_LOCATION+"/web/swagger/dist/index.html", c)
	})
}
<|endoftext|>


<commit_before>package controller

import (
  "github.com/golang/glog"

  kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
  "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
  "github.com/GoogleCloudPlatform/kubernetes/pkg/util"

  deployapi "github.com/openshift/origin/pkg/deploy/api"
)

// BasicDeploymentController implements the DeploymentStrategyTypeBasic deployment strategy. Its behavior
// is to create new replication controllers as defined on a Deployment, and delete any previously existing
// replication controllers for the same DeploymentConfig associated with the deployment.
type BasicDeploymentController struct {
  DeploymentUpdater           bdcDeploymentUpdater
  ReplicationControllerClient bdcReplicationControllerClient
  NextDeployment              func() *deployapi.Deployment
}

type bdcDeploymentUpdater interface {
  UpdateDeployment(ctx kapi.Context, deployment *deployapi.Deployment) (*deployapi.Deployment, error)
}

type bdcReplicationControllerClient interface {
  ListReplicationControllers(ctx kapi.Context, selector labels.Selector) (*kapi.ReplicationControllerList, error)
  GetReplicationController(ctx kapi.Context, id string) (*kapi.ReplicationController, error)
  CreateReplicationController(ctx kapi.Context, ctrl *kapi.ReplicationController) (*kapi.ReplicationController, error)
  UpdateReplicationController(ctx kapi.Context, ctrl *kapi.ReplicationController) (*kapi.ReplicationController, error)
  DeleteReplicationController(ctx kapi.Context, id string) error
}

func (dc *BasicDeploymentController) Run() {
  go util.Forever(func() { dc.HandleDeployment() }, 0)
}

// HandleDeployment executes a single Deployment. It's assumed that the strategy of the deployment is
// DeploymentStrategyTypeBasic.
func (dc *BasicDeploymentController) HandleDeployment() error {
  deployment := dc.NextDeployment()

  if deployment.Strategy.Type != deployapi.DeploymentStrategyTypeBasic {
    glog.V(4).Infof("Ignoring deployment %s due to incompatible strategy type %s", deployment.ID, deployment.Strategy)
    return nil
  }

  ctx := kapi.WithNamespace(kapi.NewContext(), deployment.Namespace)

  nextStatus := deployment.Status
  switch deployment.Status {
  case deployapi.DeploymentStatusNew:
    nextStatus = dc.handleNew(ctx, deployment)
  }

  // persist any status change
  if deployment.Status != nextStatus {
    deployment.Status = nextStatus
    glog.V(4).Infof("Saving deployment %v status: %v", deployment.ID, deployment.Status)
    if _, err := dc.DeploymentUpdater.UpdateDeployment(ctx, deployment); err != nil {
      glog.V(2).Infof("Received error while saving deployment %v: %v", deployment.ID, err)
      return err
    }
  }

  return nil
}

func (dc *BasicDeploymentController) handleNew(ctx kapi.Context, deployment *deployapi.Deployment) deployapi.DeploymentStatus {
  var controllers *kapi.ReplicationControllerList
  var err error

  configID, hasConfigID := deployment.Labels[deployapi.DeploymentConfigLabel]
  if hasConfigID {
    selector, _ := labels.ParseSelector(deployapi.DeploymentConfigLabel + "=" + configID)
    controllers, err = dc.ReplicationControllerClient.ListReplicationControllers(ctx, selector)
    if err != nil {
      glog.V(2).Infof("Unable to get list of replication controllers for previous deploymentConfig %s: %v\n", configID, err)
      return deployapi.DeploymentStatusFailed
    }
  }

  controller := &kapi.ReplicationController{
    DesiredState: deployment.ControllerTemplate,
    Labels:       map[string]string{deployapi.DeploymentConfigLabel: configID, "deploymentID": deployment.ID},
  }

  if controller.DesiredState.PodTemplate.Labels == nil {
    controller.DesiredState.PodTemplate.Labels = make(map[string]string)
  }

  controller.DesiredState.PodTemplate.Labels[deployapi.DeploymentConfigLabel] = configID
  controller.DesiredState.PodTemplate.Labels["deploymentID"] = deployment.ID

  glog.V(2).Infof("Creating replicationController for deployment %s", deployment.ID)
  if _, err := dc.ReplicationControllerClient.CreateReplicationController(ctx, controller); err != nil {
    glog.V(2).Infof("An error occurred creating the replication controller for deployment %s: %v", deployment.ID, err)
    return deployapi.DeploymentStatusFailed
  }

  allProcessed := true
  // For this simple deploy, remove previous replication controllers
  for _, rc := range controllers.Items {
    configID, _ := deployment.Labels[deployapi.DeploymentConfigLabel]
    glog.V(2).Infof("Stopping replication controller for previous deploymentConfig %s: %v", configID, rc.ID)

    controller, err := dc.ReplicationControllerClient.GetReplicationController(ctx, rc.ID)
    if err != nil {
      glog.V(2).Infof("Unable to get replication controller %s for previous deploymentConfig %s: %#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }

    controller.DesiredState.Replicas = 0
    glog.V(2).Infof("Settings Replicas=0 for replicationController %s for previous deploymentConfig %s", rc.ID, configID)
    if _, err := dc.ReplicationControllerClient.UpdateReplicationController(ctx, controller); err != nil {
      glog.V(2).Infof("Unable to stop replication controller %s for previous deploymentConfig %s: %#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }
  }

  for _, rc := range controllers.Items {
    configID, _ := deployment.Labels[deployapi.DeploymentConfigLabel]
    glog.V(2).Infof("Deleting replication controller %s for previous deploymentConfig %s", rc.ID, configID)
    err := dc.ReplicationControllerClient.DeleteReplicationController(ctx, rc.ID)
    if err != nil {
      glog.V(2).Infof("Unable to remove replication controller %s for previous deploymentConfig %s:%#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }
  }

  if allProcessed {
    return deployapi.DeploymentStatusComplete
  }

  return deployapi.DeploymentStatusFailed
}
<commit_msg>Fix crash handling deployment with no config<commit_after>package controller

import (
  "github.com/golang/glog"

  kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
  "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
  "github.com/GoogleCloudPlatform/kubernetes/pkg/util"

  deployapi "github.com/openshift/origin/pkg/deploy/api"
)

// BasicDeploymentController implements the DeploymentStrategyTypeBasic deployment strategy. Its behavior
// is to create new replication controllers as defined on a Deployment, and delete any previously existing
// replication controllers for the same DeploymentConfig associated with the deployment.
type BasicDeploymentController struct {
  DeploymentUpdater           bdcDeploymentUpdater
  ReplicationControllerClient bdcReplicationControllerClient
  NextDeployment              func() *deployapi.Deployment
}

type bdcDeploymentUpdater interface {
  UpdateDeployment(ctx kapi.Context, deployment *deployapi.Deployment) (*deployapi.Deployment, error)
}

type bdcReplicationControllerClient interface {
  ListReplicationControllers(ctx kapi.Context, selector labels.Selector) (*kapi.ReplicationControllerList, error)
  GetReplicationController(ctx kapi.Context, id string) (*kapi.ReplicationController, error)
  CreateReplicationController(ctx kapi.Context, ctrl *kapi.ReplicationController) (*kapi.ReplicationController, error)
  UpdateReplicationController(ctx kapi.Context, ctrl *kapi.ReplicationController) (*kapi.ReplicationController, error)
  DeleteReplicationController(ctx kapi.Context, id string) error
}

func (dc *BasicDeploymentController) Run() {
  go util.Forever(func() { dc.HandleDeployment() }, 0)
}

// HandleDeployment executes a single Deployment. It's assumed that the strategy of the deployment is
// DeploymentStrategyTypeBasic.
func (dc *BasicDeploymentController) HandleDeployment() error {
  deployment := dc.NextDeployment()

  if deployment.Strategy.Type != deployapi.DeploymentStrategyTypeBasic {
    glog.V(4).Infof("Ignoring deployment %s due to incompatible strategy type %s", deployment.ID, deployment.Strategy)
    return nil
  }

  ctx := kapi.WithNamespace(kapi.NewContext(), deployment.Namespace)

  nextStatus := deployment.Status
  switch deployment.Status {
  case deployapi.DeploymentStatusNew:
    nextStatus = dc.handleNew(ctx, deployment)
  }

  // persist any status change
  if deployment.Status != nextStatus {
    deployment.Status = nextStatus
    glog.V(4).Infof("Saving deployment %v status: %v", deployment.ID, deployment.Status)
    if _, err := dc.DeploymentUpdater.UpdateDeployment(ctx, deployment); err != nil {
      glog.V(2).Infof("Received error while saving deployment %v: %v", deployment.ID, err)
      return err
    }
  }

  return nil
}

func (dc *BasicDeploymentController) handleNew(ctx kapi.Context, deployment *deployapi.Deployment) deployapi.DeploymentStatus {
  controllers := &kapi.ReplicationControllerList{}
  var err error

  configID, hasConfigID := deployment.Labels[deployapi.DeploymentConfigLabel]
  if hasConfigID {
    selector, _ := labels.ParseSelector(deployapi.DeploymentConfigLabel + "=" + configID)
    controllers, err = dc.ReplicationControllerClient.ListReplicationControllers(ctx, selector)
    if err != nil {
      glog.V(2).Infof("Unable to get list of replication controllers for previous deploymentConfig %s: %v\n", configID, err)
      return deployapi.DeploymentStatusFailed
    }
  }

  controller := &kapi.ReplicationController{
    DesiredState: deployment.ControllerTemplate,
    Labels:       map[string]string{deployapi.DeploymentConfigLabel: configID, "deployment": deployment.ID},
  }

  if controller.DesiredState.PodTemplate.Labels == nil {
    controller.DesiredState.PodTemplate.Labels = make(map[string]string)
  }

  controller.DesiredState.PodTemplate.Labels[deployapi.DeploymentConfigLabel] = configID
  controller.DesiredState.PodTemplate.Labels["deployment"] = deployment.ID

  glog.V(2).Infof("Creating replicationController for deployment %s", deployment.ID)
  if _, err := dc.ReplicationControllerClient.CreateReplicationController(ctx, controller); err != nil {
    glog.V(2).Infof("An error occurred creating the replication controller for deployment %s: %v", deployment.ID, err)
    return deployapi.DeploymentStatusFailed
  }

  allProcessed := true
  // For this simple deploy, remove previous replication controllers
  for _, rc := range controllers.Items {
    configID, _ := deployment.Labels[deployapi.DeploymentConfigLabel]
    glog.V(2).Infof("Stopping replication controller for previous deploymentConfig %s: %v", configID, rc.ID)

    controller, err := dc.ReplicationControllerClient.GetReplicationController(ctx, rc.ID)
    if err != nil {
      glog.V(2).Infof("Unable to get replication controller %s for previous deploymentConfig %s: %#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }

    controller.DesiredState.Replicas = 0
    glog.V(2).Infof("Settings Replicas=0 for replicationController %s for previous deploymentConfig %s", rc.ID, configID)
    if _, err := dc.ReplicationControllerClient.UpdateReplicationController(ctx, controller); err != nil {
      glog.V(2).Infof("Unable to stop replication controller %s for previous deploymentConfig %s: %#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }
  }

  for _, rc := range controllers.Items {
    configID, _ := deployment.Labels[deployapi.DeploymentConfigLabel]
    glog.V(2).Infof("Deleting replication controller %s for previous deploymentConfig %s", rc.ID, configID)
    err := dc.ReplicationControllerClient.DeleteReplicationController(ctx, rc.ID)
    if err != nil {
      glog.V(2).Infof("Unable to remove replication controller %s for previous deploymentConfig %s:%#v\n", rc.ID, configID, err)
      allProcessed = false
      continue
    }
  }

  if allProcessed {
    return deployapi.DeploymentStatusComplete
  }

  return deployapi.DeploymentStatusFailed
}
<|endoftext|>


<commit_before>package forwardedheaders

import (
	"net"
	"net/http"
	"os"
	"strings"

	"github.com/containous/traefik/v2/pkg/ip"
)

const (
	xForwardedProto             = "X-Forwarded-Proto"
	xForwardedFor               = "X-Forwarded-For"
	xForwardedHost              = "X-Forwarded-Host"
	xForwardedPort              = "X-Forwarded-Port"
	xForwardedServer            = "X-Forwarded-Server"
	xForwardedURI               = "X-Forwarded-Uri"
	xForwardedMethod            = "X-Forwarded-Method"
	xForwardedTLSClientCert     = "X-Forwarded-Tls-Client-Cert"
	xForwardedTLSClientCertInfo = "X-Forwarded-Tls-Client-Cert-Info"
	xRealIP                     = "X-Real-Ip"
	connection                  = "Connection"
	upgrade                     = "Upgrade"
)

var xHeaders = []string{
	xForwardedProto,
	xForwardedFor,
	xForwardedHost,
	xForwardedPort,
	xForwardedServer,
	xForwardedURI,
	xForwardedMethod,
	xForwardedTLSClientCert,
	xForwardedTLSClientCertInfo,
	xRealIP,
}

// XForwarded is an HTTP handler wrapper that sets the X-Forwarded headers,
// and other relevant headers for a reverse-proxy.
// Unless insecure is set,
// it first removes all the existing values for those headers if the remote address is not one of the trusted ones.
type XForwarded struct {
	insecure   bool
	trustedIps []string
	ipChecker  *ip.Checker
	next       http.Handler
	hostname   string
}

// NewXForwarded creates a new XForwarded.
func NewXForwarded(insecure bool, trustedIps []string, next http.Handler) (*XForwarded, error) {
	var ipChecker *ip.Checker
	if len(trustedIps) > 0 {
		var err error
		ipChecker, err = ip.NewChecker(trustedIps)
		if err != nil {
			return nil, err
		}
	}

	hostname, err := os.Hostname()
	if err != nil {
		hostname = "localhost"
	}

	return &XForwarded{
		insecure:   insecure,
		trustedIps: trustedIps,
		ipChecker:  ipChecker,
		next:       next,
		hostname:   hostname,
	}, nil
}

func (x *XForwarded) isTrustedIP(ip string) bool {
	if x.ipChecker == nil {
		return false
	}
	return x.ipChecker.IsAuthorized(ip) == nil
}

// removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has {zone} information in it,
// like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692".
func removeIPv6Zone(clientIP string) string {
	return strings.Split(clientIP, "%")[0]
}

// isWebsocketRequest returns whether the specified HTTP request is a websocket handshake request.
func isWebsocketRequest(req *http.Request) bool {
	containsHeader := func(name, value string) bool {
		items := strings.Split(req.Header.Get(name), ",")
		for _, item := range items {
			if value == strings.ToLower(strings.TrimSpace(item)) {
				return true
			}
		}
		return false
	}
	return containsHeader(connection, "upgrade") && containsHeader(upgrade, "websocket")
}

func forwardedPort(req *http.Request) string {
	if req == nil {
		return ""
	}

	if _, port, err := net.SplitHostPort(req.Host); err == nil && port != "" {
		return port
	}

	if req.Header.Get(xForwardedProto) == "https" || req.Header.Get(xForwardedProto) == "wss" {
		return "443"
	}

	if req.TLS != nil {
		return "443"
	}

	return "80"
}

func (x *XForwarded) rewrite(outreq *http.Request) {
	if clientIP, _, err := net.SplitHostPort(outreq.RemoteAddr); err == nil {
		clientIP = removeIPv6Zone(clientIP)

		if outreq.Header.Get(xRealIP) == "" {
			outreq.Header.Set(xRealIP, clientIP)
		}
	}

	xfProto := outreq.Header.Get(xForwardedProto)
	if xfProto == "" {
		if outreq.TLS != nil {
			outreq.Header.Set(xForwardedProto, "https")
		} else {
			outreq.Header.Set(xForwardedProto, "http")
		}
	}

	if isWebsocketRequest(outreq) {
		if outreq.Header.Get(xForwardedProto) == "https" || outreq.Header.Get(xForwardedProto) == "wss" {
			outreq.Header.Set(xForwardedProto, "wss")
		} else {
			outreq.Header.Set(xForwardedProto, "ws")
		}
	}

	if xfPort := outreq.Header.Get(xForwardedPort); xfPort == "" {
		outreq.Header.Set(xForwardedPort, forwardedPort(outreq))
	}

	if xfHost := outreq.Header.Get(xForwardedHost); xfHost == "" && outreq.Host != "" {
		outreq.Header.Set(xForwardedHost, outreq.Host)
	}

	if x.hostname != "" {
		outreq.Header.Set(xForwardedServer, x.hostname)
	}
}

// ServeHTTP implements http.Handler.
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
		for _, h := range xHeaders {
			r.Header.Del(h)
		}
	}

	x.rewrite(r)

	x.next.ServeHTTP(w, r)
}
<commit_msg>refactor X-Forwarded-Proto<commit_after>package forwardedheaders

import (
	"net"
	"net/http"
	"os"
	"strings"

	"github.com/containous/traefik/v2/pkg/ip"
)

const (
	xForwardedProto             = "X-Forwarded-Proto"
	xForwardedFor               = "X-Forwarded-For"
	xForwardedHost              = "X-Forwarded-Host"
	xForwardedPort              = "X-Forwarded-Port"
	xForwardedServer            = "X-Forwarded-Server"
	xForwardedURI               = "X-Forwarded-Uri"
	xForwardedMethod            = "X-Forwarded-Method"
	xForwardedTLSClientCert     = "X-Forwarded-Tls-Client-Cert"
	xForwardedTLSClientCertInfo = "X-Forwarded-Tls-Client-Cert-Info"
	xRealIP                     = "X-Real-Ip"
	connection                  = "Connection"
	upgrade                     = "Upgrade"
)

var xHeaders = []string{
	xForwardedProto,
	xForwardedFor,
	xForwardedHost,
	xForwardedPort,
	xForwardedServer,
	xForwardedURI,
	xForwardedMethod,
	xForwardedTLSClientCert,
	xForwardedTLSClientCertInfo,
	xRealIP,
}

// XForwarded is an HTTP handler wrapper that sets the X-Forwarded headers,
// and other relevant headers for a reverse-proxy.
// Unless insecure is set,
// it first removes all the existing values for those headers if the remote address is not one of the trusted ones.
type XForwarded struct {
	insecure   bool
	trustedIps []string
	ipChecker  *ip.Checker
	next       http.Handler
	hostname   string
}

// NewXForwarded creates a new XForwarded.
func NewXForwarded(insecure bool, trustedIps []string, next http.Handler) (*XForwarded, error) {
	var ipChecker *ip.Checker
	if len(trustedIps) > 0 {
		var err error
		ipChecker, err = ip.NewChecker(trustedIps)
		if err != nil {
			return nil, err
		}
	}

	hostname, err := os.Hostname()
	if err != nil {
		hostname = "localhost"
	}

	return &XForwarded{
		insecure:   insecure,
		trustedIps: trustedIps,
		ipChecker:  ipChecker,
		next:       next,
		hostname:   hostname,
	}, nil
}

func (x *XForwarded) isTrustedIP(ip string) bool {
	if x.ipChecker == nil {
		return false
	}
	return x.ipChecker.IsAuthorized(ip) == nil
}

// removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has {zone} information in it,
// like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692".
func removeIPv6Zone(clientIP string) string {
	return strings.Split(clientIP, "%")[0]
}

// isWebsocketRequest returns whether the specified HTTP request is a websocket handshake request.
func isWebsocketRequest(req *http.Request) bool {
	containsHeader := func(name, value string) bool {
		items := strings.Split(req.Header.Get(name), ",")
		for _, item := range items {
			if value == strings.ToLower(strings.TrimSpace(item)) {
				return true
			}
		}
		return false
	}
	return containsHeader(connection, "upgrade") && containsHeader(upgrade, "websocket")
}

func forwardedPort(req *http.Request) string {
	if req == nil {
		return ""
	}

	if _, port, err := net.SplitHostPort(req.Host); err == nil && port != "" {
		return port
	}

	if req.Header.Get(xForwardedProto) == "https" || req.Header.Get(xForwardedProto) == "wss" {
		return "443"
	}

	if req.TLS != nil {
		return "443"
	}

	return "80"
}

func (x *XForwarded) rewrite(outreq *http.Request) {
	if clientIP, _, err := net.SplitHostPort(outreq.RemoteAddr); err == nil {
		clientIP = removeIPv6Zone(clientIP)

		if outreq.Header.Get(xRealIP) == "" {
			outreq.Header.Set(xRealIP, clientIP)
		}
	}

	xfProto := outreq.Header.Get(xForwardedProto)
	if xfProto == "" {
		if isWebsocketRequest(outreq) {
			if outreq.TLS != nil {
				outreq.Header.Set(xForwardedProto, "wss")
			} else {
				outreq.Header.Set(xForwardedProto, "ws")
			}
		} else {
			if outreq.TLS != nil {
				outreq.Header.Set(xForwardedProto, "https")
			} else {
				outreq.Header.Set(xForwardedProto, "http")
			}
		}
	}

	if xfPort := outreq.Header.Get(xForwardedPort); xfPort == "" {
		outreq.Header.Set(xForwardedPort, forwardedPort(outreq))
	}

	if xfHost := outreq.Header.Get(xForwardedHost); xfHost == "" && outreq.Host != "" {
		outreq.Header.Set(xForwardedHost, outreq.Host)
	}

	if x.hostname != "" {
		outreq.Header.Set(xForwardedServer, x.hostname)
	}
}

// ServeHTTP implements http.Handler.
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
		for _, h := range xHeaders {
			r.Header.Del(h)
		}
	}

	x.rewrite(r)

	x.next.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// +build postgres

package migrator

import (
	"database/sql"
	"errors"
	"log"
	"path/filepath"
	"sort"
	"strings"
	"time"

	_ "github.com/lib/pq"
)

var (
	ErrCreatingTable        = errors.New("error-creating-migration-table")
	ErrMigrationFailed      = errors.New("migration-failed")
	ErrRegisteringMigration = errors.New("error-registering-migration")
	ErrGettingMigrations    = errors.New("error-getting-migrations")
	ErrRollbackFailed       = errors.New("error-rolling-back-migrations")
	ErrUpdatingMigration    = errors.New("error-updating-migration-metadata")
)

type postgres struct {
	db *sql.DB
}

func NewPostgres(db *sql.DB) *postgres {
	return &postgres{db: db}
}

func (p *postgres) Init() error {
	_, err := p.db.Exec(`
		-- creates an enum type for OAuth2 token types
		do $$
		begin
			if not exists (select 1 from pg_type where typname = 'migration_status_type') then
				create type migration_status_type as enum ('up', 'down');
			end if;
		end$$;
		-- creates citext extension
		create extension if not exists citext;

		-- creates table schema_migrations
		create table if not exists schema_migrations (
			-- migration identifier as found in migration file name.
			id            citext not null,
			-- migration name as found in migration file name.
			name          text   not null,
			-- migration file name.
			filename      text   not null,
			-- migration sql content as found in Up migration file.
			up            text   not null,
			-- migration sql content as found in Down migration file.
			down          text   not null,
			-- status of this migration
			status        migration_status_type,
			-- timestamp of when the grant was created.
			created_at    timestamptz not null default current_timestamp,

			primary key (id)
		);
	`)

	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrCreatingTable
	}

	return nil
}

// isApplied checks whether the migration was already applied or not
func (p *postgres) isApplied(id string) (applied, exist bool, err error) {
	var status string
	row := p.db.QueryRow(`SELECT status FROM schema_migrations WHERE id = $1`, id)
	err = row.Scan(&status)
	if err != nil {
		if sql.ErrNoRows == err {
			return false, false, nil
		}

		return false, false, err
	}

	if status == "up" {
		return true, true, nil
	}

	return false, true, nil
}

func (p *postgres) MigrateFromAsset(assetFunc AssetFunc, assetDirFunc AssetDirFunc) error {
	baseDir := "migrations/postgres"
	files, err := assetDirFunc(baseDir)
	if err != nil {
		log.Printf("[ERROR] trying to get list of migration files from embedded asset directory %s", baseDir)
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	sort.Strings(files)

	for i := 0; i < len(files); i++ {
		f := files[i]
		// File names should be formatted like so: id_migration-name_up.sql or
		// id_migration-name_down.sql. Ex: 0002_create_extension_citext_down.sql
		parts := strings.Split(f, "_")
		if len(parts) != 3 {
			log.Printf("[ERROR] Bad file format: %s", f)
			return ErrBadFilenameFormat
		}

		m := new(Migration)
		m.ID = parts[0]
		m.Name = parts[1]
		m.Filename = f

		if parts[2] != "up.sql" {
			continue
		}

		upFile := filepath.Join(baseDir, f)
		upSQL, err := assetFunc(upFile)
		if err != nil {
			log.Printf("[ERROR] Extracting asset content from %s", upFile)
			log.Printf("[ERROR] %#v", err)
			return ErrMigrationFailed
		}

		downFile := filepath.Join(baseDir, strings.Replace(f, "up.sql", "down.sql", 1))
		downSQL, err := assetFunc(downFile)
		if err != nil {
			log.Printf("[ERROR] Extracting asset content from %s", downFile)
			log.Printf("[ERROR] %#v", err)
			return ErrMigrationFailed
		}

		m.Up = string(upSQL[:])
		m.Down = string(downSQL[:])

		if err := p.migrate(m); err != nil {
			return err
		}
	}
	return nil
}

func (p *postgres) migrate(m *Migration) error {
	tx, err := p.db.Begin()
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	applied, exists, err := p.isApplied(m.ID)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	if applied {
		return nil
	}

	if _, err := tx.Exec(m.Up); err != nil {
		log.Printf("[ERROR] %#v", err)
		log.Printf("[ERROR] %s", m.Up)
		tx.Rollback()
		return ErrMigrationFailed
	}

	if !exists {
		if _, err := tx.Exec(`
			INSERT INTO schema_migrations (
				id, name, filename, up, down, status, created_at
			) VALUES ($1, $2, $3, $4, $5, $6, now());
		`, m.ID, m.Name, m.Filename, m.Up, m.Down, "up"); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrRegisteringMigration
		}
	} else {
		if _, err := tx.Exec(`
			UPDATE schema_migrations
			SET    status = $1
			WHERE  id = $2`, "up", m.ID); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrUpdatingMigration
		}
	}

	if err := tx.Commit(); err != nil {
		log.Printf("[ERROR] %#v", err)
		tx.Rollback()
		return ErrMigrationFailed
	}

	return nil
}

func (p *postgres) Rollback() error {
	return p.RollbackN(1)
}

func (p *postgres) RollbackN(n uint) error {
	migrations, err := p.db.Query(`
		SELECT id, down FROM schema_migrations
		WHERE status = 'up'
		ORDER BY id DESC LIMIT $1`, n)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrRollbackFailed
	}
	defer migrations.Close()

	for migrations.Next() {
		var id, downSQL string
		if err := migrations.Scan(&id, &downSQL); err != nil {
			log.Printf("[ERROR] %#v", err)
			return ErrRollbackFailed
		}

		tx, err := p.db.Begin()
		if err != nil {
			log.Printf("[ERROR] %#v", err)
			return ErrRollbackFailed
		}

		if _, err = tx.Exec(downSQL); err != nil {
			log.Printf("[ERROR] %#v", err)
			log.Printf("[ERROR] Down query: %s", downSQL)
			tx.Rollback()
			return ErrRollbackFailed
		}

		if _, err = tx.Exec(`
			UPDATE schema_migrations
			SET    status = $1
			WHERE  id = $2
		`, "down", id); err != nil {
			log.Printf("[ERROR] id=%s status=%s err=%#v", id, "down", err)
			tx.Rollback()
			return ErrRollbackFailed
		}

		if err := tx.Commit(); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrRollbackFailed
		}
	}

	if err = migrations.Err(); err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrRollbackFailed
	}
	return nil
}

func (p *postgres) Migrations() ([]*Migration, error) {
	rows, err := p.db.Query(`
		SELECT id, name, filename, up, down, status, created_at
		FROM schema_migrations
	`)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return nil, ErrGettingMigrations
	}
	defer rows.Close()
	migrations := make([]*Migration, 0)
	for rows.Next() {
		var id, name, filename, up, down, status string
		var createdAt time.Time

		rows.Scan(&id, &name, &filename, &up, &down, &status, &createdAt)
		m := new(Migration)
		m.ID = id
		m.Name = name
		m.Filename = filename
		m.Up = up
		m.Down = down
		m.Status = status
		m.CreatedAt = createdAt

		migrations = append(migrations, m)
	}

	if err = rows.Err(); err != nil {
		log.Printf("[ERROR] %#v", err)
		return nil, ErrGettingMigrations
	}
	return migrations, nil
}
<commit_msg>Fixes typo in comments<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// +build postgres

package migrator

import (
	"database/sql"
	"errors"
	"log"
	"path/filepath"
	"sort"
	"strings"
	"time"

	_ "github.com/lib/pq"
)

var (
	ErrCreatingTable        = errors.New("error-creating-migration-table")
	ErrMigrationFailed      = errors.New("migration-failed")
	ErrRegisteringMigration = errors.New("error-registering-migration")
	ErrGettingMigrations    = errors.New("error-getting-migrations")
	ErrRollbackFailed       = errors.New("error-rolling-back-migrations")
	ErrUpdatingMigration    = errors.New("error-updating-migration-metadata")
)

type postgres struct {
	db *sql.DB
}

func NewPostgres(db *sql.DB) *postgres {
	return &postgres{db: db}
}

func (p *postgres) Init() error {
	_, err := p.db.Exec(`
		-- creates an enum type for OAuth2 token types
		do $$
		begin
			if not exists (select 1 from pg_type where typname = 'migration_status_type') then
				create type migration_status_type as enum ('up', 'down');
			end if;
		end$$;
		-- creates citext extension
		create extension if not exists citext;

		-- creates table schema_migrations
		create table if not exists schema_migrations (
			-- migration identifier as found in migration file name.
			id            citext not null,
			-- migration name as found in migration file name.
			name          text   not null,
			-- migration file name.
			filename      text   not null,
			-- migration sql content as found in Up migration file.
			up            text   not null,
			-- migration sql content as found in Down migration file.
			down          text   not null,
			-- status of this migration
			status        migration_status_type,
			-- timestamp of when the grant was created.
			created_at    timestamptz not null default current_timestamp,

			primary key (id)
		);
	`)

	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrCreatingTable
	}

	return nil
}

// isApplied checks whether the migration was already applied or not
func (p *postgres) isApplied(id string) (applied, exist bool, err error) {
	var status string
	row := p.db.QueryRow(`SELECT status FROM schema_migrations WHERE id = $1`, id)
	err = row.Scan(&status)
	if err != nil {
		if sql.ErrNoRows == err {
			return false, false, nil
		}

		return false, false, err
	}

	if status == "up" {
		return true, true, nil
	}

	return false, true, nil
}

func (p *postgres) MigrateFromAsset(assetFunc AssetFunc, assetDirFunc AssetDirFunc) error {
	baseDir := "migrations/postgres"
	files, err := assetDirFunc(baseDir)
	if err != nil {
		log.Printf("[ERROR] trying to get list of migration files from embedded asset directory %s", baseDir)
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	sort.Strings(files)

	for i := 0; i < len(files); i++ {
		f := files[i]
		// File names should be formatted like so: id_migration-name_up.sql or
		// id_migration-name_down.sql. Ex: 0002_create-extension-citext_down.sql
		parts := strings.Split(f, "_")
		if len(parts) != 3 {
			log.Printf("[ERROR] Bad file format: %s", f)
			return ErrBadFilenameFormat
		}

		m := new(Migration)
		m.ID = parts[0]
		m.Name = parts[1]
		m.Filename = f

		if parts[2] != "up.sql" {
			continue
		}

		upFile := filepath.Join(baseDir, f)
		upSQL, err := assetFunc(upFile)
		if err != nil {
			log.Printf("[ERROR] Extracting asset content from %s", upFile)
			log.Printf("[ERROR] %#v", err)
			return ErrMigrationFailed
		}

		downFile := filepath.Join(baseDir, strings.Replace(f, "up.sql", "down.sql", 1))
		downSQL, err := assetFunc(downFile)
		if err != nil {
			log.Printf("[ERROR] Extracting asset content from %s", downFile)
			log.Printf("[ERROR] %#v", err)
			return ErrMigrationFailed
		}

		m.Up = string(upSQL[:])
		m.Down = string(downSQL[:])

		if err := p.migrate(m); err != nil {
			return err
		}
	}
	return nil
}

func (p *postgres) migrate(m *Migration) error {
	tx, err := p.db.Begin()
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	applied, exists, err := p.isApplied(m.ID)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrMigrationFailed
	}

	if applied {
		return nil
	}

	if _, err := tx.Exec(m.Up); err != nil {
		log.Printf("[ERROR] %#v", err)
		log.Printf("[ERROR] %s", m.Up)
		tx.Rollback()
		return ErrMigrationFailed
	}

	if !exists {
		if _, err := tx.Exec(`
			INSERT INTO schema_migrations (
				id, name, filename, up, down, status, created_at
			) VALUES ($1, $2, $3, $4, $5, $6, now());
		`, m.ID, m.Name, m.Filename, m.Up, m.Down, "up"); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrRegisteringMigration
		}
	} else {
		if _, err := tx.Exec(`
			UPDATE schema_migrations
			SET    status = $1
			WHERE  id = $2`, "up", m.ID); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrUpdatingMigration
		}
	}

	if err := tx.Commit(); err != nil {
		log.Printf("[ERROR] %#v", err)
		tx.Rollback()
		return ErrMigrationFailed
	}

	return nil
}

func (p *postgres) Rollback() error {
	return p.RollbackN(1)
}

func (p *postgres) RollbackN(n uint) error {
	migrations, err := p.db.Query(`
		SELECT id, down FROM schema_migrations
		WHERE status = 'up'
		ORDER BY id DESC LIMIT $1`, n)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrRollbackFailed
	}
	defer migrations.Close()

	for migrations.Next() {
		var id, downSQL string
		if err := migrations.Scan(&id, &downSQL); err != nil {
			log.Printf("[ERROR] %#v", err)
			return ErrRollbackFailed
		}

		tx, err := p.db.Begin()
		if err != nil {
			log.Printf("[ERROR] %#v", err)
			return ErrRollbackFailed
		}

		if _, err = tx.Exec(downSQL); err != nil {
			log.Printf("[ERROR] %#v", err)
			log.Printf("[ERROR] Down query: %s", downSQL)
			tx.Rollback()
			return ErrRollbackFailed
		}

		if _, err = tx.Exec(`
			UPDATE schema_migrations
			SET    status = $1
			WHERE  id = $2
		`, "down", id); err != nil {
			log.Printf("[ERROR] id=%s status=%s err=%#v", id, "down", err)
			tx.Rollback()
			return ErrRollbackFailed
		}

		if err := tx.Commit(); err != nil {
			log.Printf("[ERROR] %#v", err)
			tx.Rollback()
			return ErrRollbackFailed
		}
	}

	if err = migrations.Err(); err != nil {
		log.Printf("[ERROR] %#v", err)
		return ErrRollbackFailed
	}
	return nil
}

func (p *postgres) Migrations() ([]*Migration, error) {
	rows, err := p.db.Query(`
		SELECT id, name, filename, up, down, status, created_at
		FROM schema_migrations
	`)
	if err != nil {
		log.Printf("[ERROR] %#v", err)
		return nil, ErrGettingMigrations
	}
	defer rows.Close()
	migrations := make([]*Migration, 0)
	for rows.Next() {
		var id, name, filename, up, down, status string
		var createdAt time.Time

		rows.Scan(&id, &name, &filename, &up, &down, &status, &createdAt)
		m := new(Migration)
		m.ID = id
		m.Name = name
		m.Filename = filename
		m.Up = up
		m.Down = down
		m.Status = status
		m.CreatedAt = createdAt

		migrations = append(migrations, m)
	}

	if err = rows.Err(); err != nil {
		log.Printf("[ERROR] %#v", err)
		return nil, ErrGettingMigrations
	}
	return migrations, nil
}
<|endoftext|>


<commit_before>// +build darwin

package buildah

import (
	"github.com/containers/buildah/define"
	nettypes "github.com/containers/common/libnetwork/types"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/containers/storage"
	"github.com/pkg/errors"
)

// ContainerDevices is an alias for a slice of github.com/opencontainers/runc/libcontainer/configs.Device structures.
type ContainerDevices define.ContainerDevices

func setChildProcess() error {
	return errors.New("function not supported on non-linux systems")
}

func runUsingRuntimeMain() {}

func (b *Builder) Run(command []string, options RunOptions) error {
	return errors.New("function not supported on non-linux systems")
}
func DefaultNamespaceOptions() (NamespaceOptions, error) {
	options := NamespaceOptions{
		{Name: string(specs.CgroupNamespace), Host: false},
		{Name: string(specs.IPCNamespace), Host: false},
		{Name: string(specs.MountNamespace), Host: false},
		{Name: string(specs.NetworkNamespace), Host: false},
		{Name: string(specs.PIDNamespace), Host: false},
		{Name: string(specs.UserNamespace), Host: false},
		{Name: string(specs.UTSNamespace), Host: false},
	}
	return options, nil
}

// getNetworkInterface creates the network interface
func getNetworkInterface(store storage.Store, cniConfDir, cniPluginPath string) (nettypes.ContainerNetwork, error) {
	return nil, errors.New("function not supported on non-linux systems")
}
<commit_msg>run_unix: don't return an error from getNetworkInterface<commit_after>// +build darwin

package buildah

import (
	"github.com/containers/buildah/define"
	nettypes "github.com/containers/common/libnetwork/types"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/containers/storage"
	"github.com/pkg/errors"
)

// ContainerDevices is an alias for a slice of github.com/opencontainers/runc/libcontainer/configs.Device structures.
type ContainerDevices define.ContainerDevices

func setChildProcess() error {
	return errors.New("function not supported on non-linux systems")
}

func runUsingRuntimeMain() {}

func (b *Builder) Run(command []string, options RunOptions) error {
	return errors.New("function not supported on non-linux systems")
}
func DefaultNamespaceOptions() (NamespaceOptions, error) {
	options := NamespaceOptions{
		{Name: string(specs.CgroupNamespace), Host: false},
		{Name: string(specs.IPCNamespace), Host: false},
		{Name: string(specs.MountNamespace), Host: false},
		{Name: string(specs.NetworkNamespace), Host: false},
		{Name: string(specs.PIDNamespace), Host: false},
		{Name: string(specs.UserNamespace), Host: false},
		{Name: string(specs.UTSNamespace), Host: false},
	}
	return options, nil
}

// getNetworkInterface creates the network interface
func getNetworkInterface(store storage.Store, cniConfDir, cniPluginPath string) (nettypes.ContainerNetwork, error) {
	return nil, nil
}
<|endoftext|>