<commit_before>package app

import (
	"log"
	"net/http"
	"fmt"

	"github.com/gorilla/mux"
	"github.com/gorilla/handlers"
	"github.com/steffen25/golang.zone/database"
	"github.com/steffen25/golang.zone/config"
)

type App struct {
	Config 		config.Config
	Database 	*database.MySQLDB
	Redis 	*database.RedisDB
}

func New(cfg config.Config) *App {
	db, err := database.NewMySQLDB(cfg.MySQL)
	if err != nil {
		log.Fatal(err)
	}
	redis, err := database.NewRedisDB(cfg.Redis)
	if err != nil {
		log.Fatal(err)
	}

	return &App{cfg, db, redis}
}

func (a *App) Run(r *mux.Router)  {
	port := a.Config.Port
	addr := fmt.Sprintf(":%v", port)
	fmt.Printf("APP is listening on port: %d\n", port)
	log.Fatal(http.ListenAndServe(addr, handlers.CORS()(r)))
}

func (a *App) IsProd() bool {
	return a.Config.Env == "prod"
}<commit_msg>Test CORS<commit_after>package app

import (
	"log"
	"net/http"
	"fmt"

	"github.com/gorilla/mux"
	"github.com/gorilla/handlers"
	"github.com/steffen25/golang.zone/database"
	"github.com/steffen25/golang.zone/config"
)

type App struct {
	Config 		config.Config
	Database 	*database.MySQLDB
	Redis 	*database.RedisDB
}

func New(cfg config.Config) *App {
	db, err := database.NewMySQLDB(cfg.MySQL)
	if err != nil {
		log.Fatal(err)
	}
	redis, err := database.NewRedisDB(cfg.Redis)
	if err != nil {
		log.Fatal(err)
	}

	return &App{cfg, db, redis}
}

func (a *App) Run(r *mux.Router)  {
	headersOk := handlers.AllowedHeaders([]string{"X-Requested-With"})
	originsOk := handlers.AllowedOrigins([]string{"*"})
	methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
	port := a.Config.Port
	addr := fmt.Sprintf(":%v", port)
	fmt.Printf("APP is listening on port: %d\n", port)
	log.Fatal(http.ListenAndServe(addr, handlers.CORS(originsOk, headersOk, methodsOk)(r)))
}

func (a *App) IsProd() bool {
	return a.Config.Env == "prod"
}<|endoftext|>


<commit_before>package app

import (
	"time"
	"github.com/davidhiendl/telegraf-docker-sd/app/config"
	"github.com/davidhiendl/telegraf-docker-sd/app/utils"
	"github.com/davidhiendl/telegraf-docker-sd/app/backend"
	"github.com/davidhiendl/telegraf-docker-sd/app/sdtemplate"
	"github.com/davidhiendl/telegraf-docker-sd/app/constants"
	"regexp"
	"os"
	"io/ioutil"
	"github.com/sirupsen/logrus"
)

type App struct {
	config                *config.ConfigSpec
	telegrafReloader      *utils.TelegrafReloader
	processedMainTemplate bool
	backends              map[string]backend.Backend
	templates             map[string]*sdtemplate.Template
}

// Create new config and populate it from environment
func NewApp(cfg *config.ConfigSpec) (*App) {
	app := App{
		config:                cfg,
		processedMainTemplate: false,
		backends:              make(map[string]backend.Backend),
	}

	// register telegraf reload handler
	app.telegrafReloader = utils.NewTelegrafReloader()
	logrus.Infof("created reloader: %+v", app.telegrafReloader)

	app.loadTemplates()
	app.loadBackends()

	return &app
}

func (app *App) Run() {
	interval := time.Duration(constants.DEFAULT_QUERY_INTERVAL) * time.Second

	app.processGlobalConfig()

	for {
		for _, b := range app.backends {
			logrus.Debugf("run backend: %v", b.Name())
			b.Run()
		}
		app.telegrafReloader.ReloadIfRequested()
		time.Sleep(interval)
	}
}

// remove all configuration files that were created by regex: starting with prefix and ending with extension
func (app *App) ClearConfigFiles() {
	files, err := ioutil.ReadDir(app.config.ConfigDir)
	if err != nil {
		logrus.Fatalf("failed to clear config: %v", err)
	}

	// summarized: ^prefix[a-zA-Z0-9._-]*extension$
	rex, _ := regexp.Compile(
		"^" +
			regexp.QuoteMeta(app.config.AutoConfPrefix) +
			"[a-zA-Z0-9_\\.\\-]*" +
			regexp.QuoteMeta(app.config.AutoConfExtension) +
			"$")

	for _, f := range files {
		if rex.MatchString(f.Name()) {
			logrus.Debugf("cleaning up file: %v", f.Name())
			path := app.config.ConfigDir + "/" + f.Name()

			stat, err := os.Stat(path)
			if os.IsNotExist(err) {
				continue
			}

			// do not touch anything that is not a file
			if !stat.Mode().IsRegular() {
				logrus.Debugf("Config file is not a regular file: %v", path)
				continue
			}

			err = os.Remove(path)
			if err != nil {
				logrus.Debugf("failed to remove file: %v, err: %v", path, err)
			}
		}
	}
}
<commit_msg>added query interval customization<commit_after>package app

import (
	"time"
	"github.com/davidhiendl/telegraf-docker-sd/app/config"
	"github.com/davidhiendl/telegraf-docker-sd/app/utils"
	"github.com/davidhiendl/telegraf-docker-sd/app/backend"
	"github.com/davidhiendl/telegraf-docker-sd/app/sdtemplate"
	"github.com/davidhiendl/telegraf-docker-sd/app/constants"
	"regexp"
	"os"
	"io/ioutil"
	"github.com/sirupsen/logrus"
)

type App struct {
	config                *config.ConfigSpec
	telegrafReloader      *utils.TelegrafReloader
	processedMainTemplate bool
	backends              map[string]backend.Backend
	templates             map[string]*sdtemplate.Template
}

// Create new config and populate it from environment
func NewApp(cfg *config.ConfigSpec) (*App) {
	app := App{
		config:                cfg,
		processedMainTemplate: false,
		backends:              make(map[string]backend.Backend),
	}

	// register telegraf reload handler
	app.telegrafReloader = utils.NewTelegrafReloader()
	logrus.Infof("created reloader: %+v", app.telegrafReloader)

	app.loadTemplates()
	app.loadBackends()

	return &app
}

func (app *App) Run() {
	interval := app.config.QueryInterval
	if interval <= 0 {
		interval = constants.DEFAULT_QUERY_INTERVAL
	}
	dInterval := time.Duration(interval) * time.Second

	app.processGlobalConfig()

	for {
		for _, b := range app.backends {
			logrus.Debugf("run backend: %v", b.Name())
			b.Run()
		}
		app.telegrafReloader.ReloadIfRequested()
		time.Sleep(dInterval)
	}
}

// remove all configuration files that were created by regex: starting with prefix and ending with extension
func (app *App) ClearConfigFiles() {
	files, err := ioutil.ReadDir(app.config.ConfigDir)
	if err != nil {
		logrus.Fatalf("failed to clear config: %v", err)
	}

	// summarized: ^prefix[a-zA-Z0-9._-]*extension$
	rex, _ := regexp.Compile(
		"^" +
			regexp.QuoteMeta(app.config.AutoConfPrefix) +
			"[a-zA-Z0-9_\\.\\-]*" +
			regexp.QuoteMeta(app.config.AutoConfExtension) +
			"$")

	for _, f := range files {
		if rex.MatchString(f.Name()) {
			logrus.Debugf("cleaning up file: %v", f.Name())
			path := app.config.ConfigDir + "/" + f.Name()

			stat, err := os.Stat(path)
			if os.IsNotExist(err) {
				continue
			}

			// do not touch anything that is not a file
			if !stat.Mode().IsRegular() {
				logrus.Debugf("Config file is not a regular file: %v", path)
				continue
			}

			err = os.Remove(path)
			if err != nil {
				logrus.Debugf("failed to remove file: %v, err: %v", path, err)
			}
		}
	}
}
<|endoftext|>


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

package circonusgometrics

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"strconv"
	"time"

	"github.com/circonus-labs/circonus-gometrics/api"
	"github.com/hashicorp/go-retryablehttp"
	"github.com/pkg/errors"
)

func (m *CirconusMetrics) submit(output Metrics, newMetrics map[string]*api.CheckBundleMetric) {

	// if there is nowhere to send metrics to, just return.
	if !m.check.IsReady() {
		m.Log.Printf("[WARN] check not ready, skipping metric submission")
		return
	}

	// update check if there are any new metrics or, if metric tags have been added since last submit
	m.check.UpdateCheck(newMetrics)

	str, err := json.Marshal(output)
	if err != nil {
		m.Log.Printf("[ERROR] marshaling output %+v", err)
		return
	}

	numStats, err := m.trapCall(str)
	if err != nil {
		m.Log.Printf("[ERROR] %+v\n", err)
		return
	}

	// OK response from circonus-agent does not
	// indicate how many metrics were received
	if numStats == -1 {
		numStats = len(output)
	}

	if m.Debug {
		m.Log.Printf("[DEBUG] %d stats sent\n", numStats)
	}
}

func (m *CirconusMetrics) trapCall(payload []byte) (int, error) {
	trap, err := m.check.GetSubmissionURL()
	if err != nil {
		return 0, errors.Wrap(err, "trap call")
	}

	dataReader := bytes.NewReader(payload)

	req, err := retryablehttp.NewRequest("PUT", trap.URL.String(), dataReader)
	if err != nil {
		return 0, err
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")

	// keep last HTTP error in the event of retry failure
	var lastHTTPError error
	retryPolicy := func(ctx context.Context, resp *http.Response, err error) (bool, error) {
		if ctxErr := ctx.Err(); ctxErr != nil {
			return false, ctxErr
		}

		if err != nil {
			lastHTTPError = err
			return true, errors.Wrap(err, "retry policy")
		}
		// Check the response code. We retry on 500-range responses to allow
		// the server time to recover, as 500's are typically not permanent
		// errors and may relate to outages on the server side. This will catch
		// invalid response codes as well, like 0 and 999.
		if resp.StatusCode == 0 || resp.StatusCode >= 500 {
			body, readErr := ioutil.ReadAll(resp.Body)
			if readErr != nil {
				lastHTTPError = fmt.Errorf("- last HTTP error: %d %+v", resp.StatusCode, readErr)
			} else {
				lastHTTPError = fmt.Errorf("- last HTTP error: %d %s", resp.StatusCode, string(body))
			}
			return true, nil
		}
		return false, nil
	}

	client := retryablehttp.NewClient()
	if trap.URL.Scheme == "https" {
		client.HTTPClient.Transport = &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).Dial,
			TLSHandshakeTimeout: 10 * time.Second,
			TLSClientConfig:     trap.TLS,
			DisableKeepAlives:   true,
			MaxIdleConnsPerHost: -1,
			DisableCompression:  false,
		}
	} else if trap.URL.Scheme == "http" {
		client.HTTPClient.Transport = &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).Dial,
			DisableKeepAlives:   true,
			MaxIdleConnsPerHost: -1,
			DisableCompression:  false,
		}
	} else if trap.IsSocket {
		m.Log.Println("using socket transport")
		client.HTTPClient.Transport = trap.SockTransport
	} else {
		return 0, errors.Errorf("unknown scheme (%s), skipping submission", trap.URL.Scheme)
	}
	client.RetryWaitMin = 1 * time.Second
	client.RetryWaitMax = 5 * time.Second
	client.RetryMax = 3
	// retryablehttp only groks log or no log
	// but, outputs everything as [DEBUG] messages
	if m.Debug {
		client.Logger = m.Log
	} else {
		client.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
	}
	client.CheckRetry = retryPolicy

	attempts := -1
	client.RequestLogHook = func(logger *log.Logger, req *http.Request, retryNumber int) {
		attempts = retryNumber
	}

	resp, err := client.Do(req)
	if err != nil {
		if lastHTTPError != nil {
			return 0, fmt.Errorf("[ERROR] submitting: %+v %+v", err, lastHTTPError)
		}
		if attempts == client.RetryMax {
			m.check.RefreshTrap()
		}
		return 0, errors.Wrap(err, "trap call")
	}

	defer resp.Body.Close()

	// no content - expected result from
	// circonus-agent when metrics accepted
	if resp.StatusCode == http.StatusNoContent {
		return -1, nil
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		m.Log.Printf("[ERROR] reading body, proceeding. %s\n", err)
	}

	var response map[string]interface{}
	if err := json.Unmarshal(body, &response); err != nil {
		m.Log.Printf("[ERROR] parsing body, proceeding. %v (%s)\n", err, body)
	}

	if resp.StatusCode != http.StatusOK {
		return 0, errors.New("[ERROR] bad response code: " + strconv.Itoa(resp.StatusCode))
	}
	switch v := response["stats"].(type) {
	case float64:
		return int(v), nil
	case int:
		return v, nil
	default:
	}
	return 0, errors.New("[ERROR] bad response type")
}
<commit_msg>fix: func signature for retryablehttp.RequestLogHook<commit_after>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package circonusgometrics

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"strconv"
	"time"

	"github.com/circonus-labs/circonus-gometrics/api"
	"github.com/hashicorp/go-retryablehttp"
	"github.com/pkg/errors"
)

func (m *CirconusMetrics) submit(output Metrics, newMetrics map[string]*api.CheckBundleMetric) {

	// if there is nowhere to send metrics to, just return.
	if !m.check.IsReady() {
		m.Log.Printf("[WARN] check not ready, skipping metric submission")
		return
	}

	// update check if there are any new metrics or, if metric tags have been added since last submit
	m.check.UpdateCheck(newMetrics)

	str, err := json.Marshal(output)
	if err != nil {
		m.Log.Printf("[ERROR] marshaling output %+v", err)
		return
	}

	numStats, err := m.trapCall(str)
	if err != nil {
		m.Log.Printf("[ERROR] %+v\n", err)
		return
	}

	// OK response from circonus-agent does not
	// indicate how many metrics were received
	if numStats == -1 {
		numStats = len(output)
	}

	if m.Debug {
		m.Log.Printf("[DEBUG] %d stats sent\n", numStats)
	}
}

func (m *CirconusMetrics) trapCall(payload []byte) (int, error) {
	trap, err := m.check.GetSubmissionURL()
	if err != nil {
		return 0, errors.Wrap(err, "trap call")
	}

	dataReader := bytes.NewReader(payload)

	req, err := retryablehttp.NewRequest("PUT", trap.URL.String(), dataReader)
	if err != nil {
		return 0, err
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")

	// keep last HTTP error in the event of retry failure
	var lastHTTPError error
	retryPolicy := func(ctx context.Context, resp *http.Response, err error) (bool, error) {
		if ctxErr := ctx.Err(); ctxErr != nil {
			return false, ctxErr
		}

		if err != nil {
			lastHTTPError = err
			return true, errors.Wrap(err, "retry policy")
		}
		// Check the response code. We retry on 500-range responses to allow
		// the server time to recover, as 500's are typically not permanent
		// errors and may relate to outages on the server side. This will catch
		// invalid response codes as well, like 0 and 999.
		if resp.StatusCode == 0 || resp.StatusCode >= 500 {
			body, readErr := ioutil.ReadAll(resp.Body)
			if readErr != nil {
				lastHTTPError = fmt.Errorf("- last HTTP error: %d %+v", resp.StatusCode, readErr)
			} else {
				lastHTTPError = fmt.Errorf("- last HTTP error: %d %s", resp.StatusCode, string(body))
			}
			return true, nil
		}
		return false, nil
	}

	client := retryablehttp.NewClient()
	if trap.URL.Scheme == "https" {
		client.HTTPClient.Transport = &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).Dial,
			TLSHandshakeTimeout: 10 * time.Second,
			TLSClientConfig:     trap.TLS,
			DisableKeepAlives:   true,
			MaxIdleConnsPerHost: -1,
			DisableCompression:  false,
		}
	} else if trap.URL.Scheme == "http" {
		client.HTTPClient.Transport = &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).Dial,
			DisableKeepAlives:   true,
			MaxIdleConnsPerHost: -1,
			DisableCompression:  false,
		}
	} else if trap.IsSocket {
		m.Log.Println("using socket transport")
		client.HTTPClient.Transport = trap.SockTransport
	} else {
		return 0, errors.Errorf("unknown scheme (%s), skipping submission", trap.URL.Scheme)
	}
	client.RetryWaitMin = 1 * time.Second
	client.RetryWaitMax = 5 * time.Second
	client.RetryMax = 3
	// retryablehttp only groks log or no log
	// but, outputs everything as [DEBUG] messages
	if m.Debug {
		client.Logger = m.Log
	} else {
		client.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
	}
	client.CheckRetry = retryPolicy

	attempts := -1
	client.RequestLogHook = func(logger retryablehttp.Logger, req *http.Request, retryNumber int) {
		attempts = retryNumber
	}

	resp, err := client.Do(req)
	if err != nil {
		if lastHTTPError != nil {
			return 0, fmt.Errorf("[ERROR] submitting: %+v %+v", err, lastHTTPError)
		}
		if attempts == client.RetryMax {
			m.check.RefreshTrap()
		}
		return 0, errors.Wrap(err, "trap call")
	}

	defer resp.Body.Close()

	// no content - expected result from
	// circonus-agent when metrics accepted
	if resp.StatusCode == http.StatusNoContent {
		return -1, nil
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		m.Log.Printf("[ERROR] reading body, proceeding. %s\n", err)
	}

	var response map[string]interface{}
	if err := json.Unmarshal(body, &response); err != nil {
		m.Log.Printf("[ERROR] parsing body, proceeding. %v (%s)\n", err, body)
	}

	if resp.StatusCode != http.StatusOK {
		return 0, errors.New("[ERROR] bad response code: " + strconv.Itoa(resp.StatusCode))
	}
	switch v := response["stats"].(type) {
	case float64:
		return int(v), nil
	case int:
		return v, nil
	default:
	}
	return 0, errors.New("[ERROR] bad response type")
}
<|endoftext|>


<commit_before>package xco

import (
	"github.com/pkg/errors"
)

const (

	// SUBSCRIBE represents the subscribe Presence message type
	SUBSCRIBE = "subscribe"

	// SUBSCRIBED represents the subscribed Presence message type
	SUBSCRIBED = "subscribed"

	// UNSUBSCRIBE represents the unsubsribe Presence message type
	UNSUBSCRIBE = "unsubscribe"

	// UNSUBSCRIBED represents the unsubsribed Presence message type
	UNSUBSCRIBED = "unsubscribed"

	// UNAVAILABLE represents the unavailable Presence message type
	UNAVAILABLE = "unavailable"

	// PROBE represents the probe Presence message type
	PROBE = "probe"
)

// Presence represents a message identifying whether an entity is available and the subscription requests/responses for the entity
type Presence struct {
	Header

	Show     string `xml:"show,omitempty"`
	Status   string `xml:"status,omitempty"`
	Priority byte   `xml:"priority,omitempty"`

	Type string `xml:"type,attr"`

	// XEP-0172 User nicknames
	Nick string `xml:"http://jabber.org/protocol/nick nick,omitempty"`

	XMLName string `xml:"presence"`
}

// PresenceHandler handles incoming presence requests
type PresenceHandler func(c *Component, p *Presence) error

func noOpPresenceHandler(c *Component, p *Presence) error {
	return nil
}

// AlwaysOnlinePresenceHandler always returns "subscribed" to any presence requests
func AlwaysOnlinePresenceHandler(c *Component, p *Presence) error {
	resp := &Presence{
		Header: Header{
			From: p.To,
			To:   p.From,
			ID:   p.ID,
		},
		Type: "subscribed",
	}

	return errors.Wrap(c.Send(resp), "Error sending always online presence")
}

// ToAddressPresenceHandler calls the function with the To address
func ToAddressPresenceHandler(fn func(subject Address) error) PresenceHandler {
	return func(c *Component, p *Presence) error {
		return fn(*p.To)
	}
}
<commit_msg>Omit presence type if empty<commit_after>package xco

import (
	"github.com/pkg/errors"
)

const (

	// SUBSCRIBE represents the subscribe Presence message type
	SUBSCRIBE = "subscribe"

	// SUBSCRIBED represents the subscribed Presence message type
	SUBSCRIBED = "subscribed"

	// UNSUBSCRIBE represents the unsubsribe Presence message type
	UNSUBSCRIBE = "unsubscribe"

	// UNSUBSCRIBED represents the unsubsribed Presence message type
	UNSUBSCRIBED = "unsubscribed"

	// UNAVAILABLE represents the unavailable Presence message type
	UNAVAILABLE = "unavailable"

	// PROBE represents the probe Presence message type
	PROBE = "probe"
)

// Presence represents a message identifying whether an entity is available and the subscription requests/responses for the entity
type Presence struct {
	Header

	Show     string `xml:"show,omitempty"`
	Status   string `xml:"status,omitempty"`
	Priority byte   `xml:"priority,omitempty"`

	Type string `xml:"type,attr,omitempty"`

	// XEP-0172 User nicknames
	Nick string `xml:"http://jabber.org/protocol/nick nick,omitempty"`

	XMLName string `xml:"presence"`
}

// PresenceHandler handles incoming presence requests
type PresenceHandler func(c *Component, p *Presence) error

func noOpPresenceHandler(c *Component, p *Presence) error {
	return nil
}

// AlwaysOnlinePresenceHandler always returns "subscribed" to any presence requests
func AlwaysOnlinePresenceHandler(c *Component, p *Presence) error {
	resp := &Presence{
		Header: Header{
			From: p.To,
			To:   p.From,
			ID:   p.ID,
		},
		Type: "subscribed",
	}

	return errors.Wrap(c.Send(resp), "Error sending always online presence")
}

// ToAddressPresenceHandler calls the function with the To address
func ToAddressPresenceHandler(fn func(subject Address) error) PresenceHandler {
	return func(c *Component, p *Presence) error {
		return fn(*p.To)
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"strings"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func init() {
	resource.AddTestSweepers("aws_api_gateway_rest_api", &resource.Sweeper{
		Name: "aws_api_gateway_rest_api",
		F:    testSweepAPIGatewayRestApis,
	})
}

func testSweepAPIGatewayRestApis(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).apigateway

	// https://github.com/terraform-providers/terraform-provider-aws/issues/3808
	prefixes := []string{
		"test",
		"tf_acc_",
		"tf-acc-",
	}

	err = conn.GetRestApisPages(&apigateway.GetRestApisInput{}, func(page *apigateway.GetRestApisOutput, lastPage bool) bool {
		for _, item := range page.Items {
			skip := true
			for _, prefix := range prefixes {
				if strings.HasPrefix(*item.Name, prefix) {
					skip = false
					break
				}
			}
			if skip {
				log.Printf("[INFO] Skipping API Gateway REST API: %s", *item.Name)
				continue
			}

			input := &apigateway.DeleteRestApiInput{
				RestApiId: item.Id,
			}
			log.Printf("[INFO] Deleting API Gateway REST API: %s", input)
			// TooManyRequestsException: Too Many Requests can take over a minute to resolve itself
			err := resource.Retry(2*time.Minute, func() *resource.RetryError {
				_, err := conn.DeleteRestApi(input)
				if err != nil {
					if isAWSErr(err, apigateway.ErrCodeTooManyRequestsException, "") {
						return resource.RetryableError(err)
					}
					return resource.NonRetryableError(err)
				}
				return nil
			})
			if err != nil {
				log.Printf("[ERROR] Failed to delete API Gateway REST API %s: %s", *item.Name, err)
				continue
			}
		}
		return !lastPage
	})
	if err != nil {
		return fmt.Errorf("Error retrieving API Gateway REST APIs: %s", err)
	}

	return nil
}

func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) {
	var conf apigateway.RestApi

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayRestAPIConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "bar"),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 0),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "bar"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "0"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIUpdateConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 10485760),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "10485760"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.#", "1"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.0", "application/octet-stream"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIDisableCompressionConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(&conf),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "-1"),
				),
			},
		},
	})
}

func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) {
	var conf apigateway.RestApi

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayRestAPIConfigOpenAPI,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/update"}),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
				),
			},
		},
	})
}

func testAccCheckAWSAPIGatewayRestAPINameAttribute(conf *apigateway.RestApi, name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.Name != name {
			return fmt.Errorf("Wrong Name: %q", *conf.Name)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(conf *apigateway.RestApi, description string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.Description != description {
			return fmt.Errorf("Wrong Description: %q", *conf.Description)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(conf *apigateway.RestApi, minimumCompressionSize int64) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if conf.MinimumCompressionSize == nil {
			return fmt.Errorf("MinimumCompressionSize should not be nil")
		}
		if *conf.MinimumCompressionSize != minimumCompressionSize {
			return fmt.Errorf("Wrong MinimumCompressionSize: %d", *conf.MinimumCompressionSize)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(conf *apigateway.RestApi) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if conf.MinimumCompressionSize != nil {
			return fmt.Errorf("MinimumCompressionSize should be nil: %d", *conf.MinimumCompressionSize)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIRoutes(conf *apigateway.RestApi, routes []string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).apigateway

		resp, err := conn.GetResources(&apigateway.GetResourcesInput{
			RestApiId: conf.Id,
		})
		if err != nil {
			return err
		}

		actualRoutePaths := map[string]bool{}
		for _, resource := range resp.Items {
			actualRoutePaths[*resource.Path] = true
		}

		for _, route := range routes {
			if _, ok := actualRoutePaths[route]; !ok {
				return fmt.Errorf("Expected path %v but did not find it in %v", route, actualRoutePaths)
			}
			delete(actualRoutePaths, route)
		}

		if len(actualRoutePaths) > 0 {
			return fmt.Errorf("Found unexpected paths %v", actualRoutePaths)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIExists(n string, res *apigateway.RestApi) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No API Gateway ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).apigateway

		req := &apigateway.GetRestApiInput{
			RestApiId: aws.String(rs.Primary.ID),
		}
		describe, err := conn.GetRestApi(req)
		if err != nil {
			return err
		}

		if *describe.Id != rs.Primary.ID {
			return fmt.Errorf("APIGateway not found")
		}

		*res = *describe

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).apigateway

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

		req := &apigateway.GetRestApisInput{}
		describe, err := conn.GetRestApis(req)

		if err == nil {
			if len(describe.Items) != 0 &&
				*describe.Items[0].Id == rs.Primary.ID {
				return fmt.Errorf("API Gateway still exists")
			}
		}

		return err
	}

	return nil
}

const testAccAWSAPIGatewayRestAPIConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "bar"
  minimum_compression_size = 0
}
`

const testAccAWSAPIGatewayRestAPIUpdateConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  description = "test"
  binary_media_types = ["application/octet-stream"]
  minimum_compression_size = 10485760
}
`

const testAccAWSAPIGatewayRestAPIDisableCompressionConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  description = "test"
  binary_media_types = ["application/octet-stream"]
  minimum_compression_size = -1
}
`

const testAccAWSAPIGatewayRestAPIConfigOpenAPI = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  body = <<EOF
{
  "swagger": "2.0",
  "info": {
    "title": "test",
    "version": "2017-04-20T04:08:08Z"
  },
  "schemes": [
    "https"
  ],
  "paths": {
    "/test": {
      "get": {
        "responses": {
          "200": {
            "description": "200 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP",
          "uri": "https://www.google.de",
          "httpMethod": "GET",
          "responses": {
            "default": {
              "statusCode": 200
            }
          }
        }
      }
    }
  }
}
EOF
}
`

const testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  body = <<EOF
{
  "swagger": "2.0",
  "info": {
    "title": "test",
    "version": "2017-04-20T04:08:08Z"
  },
  "schemes": [
    "https"
  ],
  "paths": {
    "/update": {
      "get": {
        "responses": {
          "200": {
            "description": "200 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP",
          "uri": "https://www.google.de",
          "httpMethod": "GET",
          "responses": {
            "default": {
              "statusCode": 200
            }
          }
        }
      }
    }
  }
}
EOF
}
`
<commit_msg>Update aws_api_gateway_rest_api tests to check for existence of `execution_arn` attribute<commit_after>package aws

import (
	"fmt"
	"log"
	"strings"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func init() {
	resource.AddTestSweepers("aws_api_gateway_rest_api", &resource.Sweeper{
		Name: "aws_api_gateway_rest_api",
		F:    testSweepAPIGatewayRestApis,
	})
}

func testSweepAPIGatewayRestApis(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).apigateway

	// https://github.com/terraform-providers/terraform-provider-aws/issues/3808
	prefixes := []string{
		"test",
		"tf_acc_",
		"tf-acc-",
	}

	err = conn.GetRestApisPages(&apigateway.GetRestApisInput{}, func(page *apigateway.GetRestApisOutput, lastPage bool) bool {
		for _, item := range page.Items {
			skip := true
			for _, prefix := range prefixes {
				if strings.HasPrefix(*item.Name, prefix) {
					skip = false
					break
				}
			}
			if skip {
				log.Printf("[INFO] Skipping API Gateway REST API: %s", *item.Name)
				continue
			}

			input := &apigateway.DeleteRestApiInput{
				RestApiId: item.Id,
			}
			log.Printf("[INFO] Deleting API Gateway REST API: %s", input)
			// TooManyRequestsException: Too Many Requests can take over a minute to resolve itself
			err := resource.Retry(2*time.Minute, func() *resource.RetryError {
				_, err := conn.DeleteRestApi(input)
				if err != nil {
					if isAWSErr(err, apigateway.ErrCodeTooManyRequestsException, "") {
						return resource.RetryableError(err)
					}
					return resource.NonRetryableError(err)
				}
				return nil
			})
			if err != nil {
				log.Printf("[ERROR] Failed to delete API Gateway REST API %s: %s", *item.Name, err)
				continue
			}
		}
		return !lastPage
	})
	if err != nil {
		return fmt.Errorf("Error retrieving API Gateway REST APIs: %s", err)
	}

	return nil
}

func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) {
	var conf apigateway.RestApi

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayRestAPIConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "bar"),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 0),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "bar"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "0"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"),
					resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIUpdateConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 10485760),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "10485760"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.#", "1"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.0", "application/octet-stream"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIDisableCompressionConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(&conf),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "-1"),
				),
			},
		},
	})
}

func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) {
	var conf apigateway.RestApi

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayRestAPIConfigOpenAPI,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"),
					resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"),
				),
			},

			{
				Config: testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf),
					testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"),
					testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/update"}),
					resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"),
					resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"),
				),
			},
		},
	})
}

func testAccCheckAWSAPIGatewayRestAPINameAttribute(conf *apigateway.RestApi, name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.Name != name {
			return fmt.Errorf("Wrong Name: %q", *conf.Name)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(conf *apigateway.RestApi, description string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *conf.Description != description {
			return fmt.Errorf("Wrong Description: %q", *conf.Description)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(conf *apigateway.RestApi, minimumCompressionSize int64) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if conf.MinimumCompressionSize == nil {
			return fmt.Errorf("MinimumCompressionSize should not be nil")
		}
		if *conf.MinimumCompressionSize != minimumCompressionSize {
			return fmt.Errorf("Wrong MinimumCompressionSize: %d", *conf.MinimumCompressionSize)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(conf *apigateway.RestApi) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if conf.MinimumCompressionSize != nil {
			return fmt.Errorf("MinimumCompressionSize should be nil: %d", *conf.MinimumCompressionSize)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIRoutes(conf *apigateway.RestApi, routes []string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).apigateway

		resp, err := conn.GetResources(&apigateway.GetResourcesInput{
			RestApiId: conf.Id,
		})
		if err != nil {
			return err
		}

		actualRoutePaths := map[string]bool{}
		for _, resource := range resp.Items {
			actualRoutePaths[*resource.Path] = true
		}

		for _, route := range routes {
			if _, ok := actualRoutePaths[route]; !ok {
				return fmt.Errorf("Expected path %v but did not find it in %v", route, actualRoutePaths)
			}
			delete(actualRoutePaths, route)
		}

		if len(actualRoutePaths) > 0 {
			return fmt.Errorf("Found unexpected paths %v", actualRoutePaths)
		}

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIExists(n string, res *apigateway.RestApi) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No API Gateway ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).apigateway

		req := &apigateway.GetRestApiInput{
			RestApiId: aws.String(rs.Primary.ID),
		}
		describe, err := conn.GetRestApi(req)
		if err != nil {
			return err
		}

		if *describe.Id != rs.Primary.ID {
			return fmt.Errorf("APIGateway not found")
		}

		*res = *describe

		return nil
	}
}

func testAccCheckAWSAPIGatewayRestAPIDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).apigateway

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

		req := &apigateway.GetRestApisInput{}
		describe, err := conn.GetRestApis(req)

		if err == nil {
			if len(describe.Items) != 0 &&
				*describe.Items[0].Id == rs.Primary.ID {
				return fmt.Errorf("API Gateway still exists")
			}
		}

		return err
	}

	return nil
}

const testAccAWSAPIGatewayRestAPIConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "bar"
  minimum_compression_size = 0
}
`

const testAccAWSAPIGatewayRestAPIUpdateConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  description = "test"
  binary_media_types = ["application/octet-stream"]
  minimum_compression_size = 10485760
}
`

const testAccAWSAPIGatewayRestAPIDisableCompressionConfig = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  description = "test"
  binary_media_types = ["application/octet-stream"]
  minimum_compression_size = -1
}
`

const testAccAWSAPIGatewayRestAPIConfigOpenAPI = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  body = <<EOF
{
  "swagger": "2.0",
  "info": {
    "title": "test",
    "version": "2017-04-20T04:08:08Z"
  },
  "schemes": [
    "https"
  ],
  "paths": {
    "/test": {
      "get": {
        "responses": {
          "200": {
            "description": "200 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP",
          "uri": "https://www.google.de",
          "httpMethod": "GET",
          "responses": {
            "default": {
              "statusCode": 200
            }
          }
        }
      }
    }
  }
}
EOF
}
`

const testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI = `
resource "aws_api_gateway_rest_api" "test" {
  name = "test"
  body = <<EOF
{
  "swagger": "2.0",
  "info": {
    "title": "test",
    "version": "2017-04-20T04:08:08Z"
  },
  "schemes": [
    "https"
  ],
  "paths": {
    "/update": {
      "get": {
        "responses": {
          "200": {
            "description": "200 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP",
          "uri": "https://www.google.de",
          "httpMethod": "GET",
          "responses": {
            "default": {
              "statusCode": 200
            }
          }
        }
      }
    }
  }
}
EOF
}
`
<|endoftext|>


<commit_before>package utils

var (
	version string
	sha     string
)

func init() {
	if version == "" {
		version = "1.0.0.preview1"

		if sha != "" {
			version = version + "-" + sha
		}
	}
}

// Version returns the current program version
func Version() string {
	return version
}

// SHA returns the build commit sha
func SHA() string {
	return sha
}
<commit_msg>fix(utils): always take sha into account<commit_after>package utils

var (
	version string
	sha     string
)

func init() {
	if version == "" {
		version = "1.0.0.preview1"
	}

	if sha != "" {
		version = version + "-" + sha
	}
}

// Version returns the current program version
func Version() string {
	return version
}

// SHA returns the build commit sha
func SHA() string {
	return sha
}
<|endoftext|>


<commit_before>// +build linux

package main_test

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var createdContainers = []string{}

func TestWshd(t *testing.T) {
	if os.Getenv("GARDEN_TEST_ROOTFS") != "" {
		RegisterFailHandler(Fail)

		RunSpecs(t, "wshd Suite")

		for _, containerDir := range createdContainers {
			log.Println("cleaning up", containerDir)

			wshdPidfile, err := os.Open(path.Join(containerDir, "run", "wshd.pid"))
			if err == nil {
				var wshdPid int

				_, err := fmt.Fscanf(wshdPidfile, "%d", &wshdPid)
				if err == nil {
					proc, err := os.FindProcess(wshdPid)
					if err == nil {
						log.Println("killing", wshdPid, proc.Kill())
					}
				}
			}

			for i := 0; i < 100; i++ {
				umount := exec.Command("umount", path.Join(containerDir, "mnt"))

				err := umount.Run()

				log.Println("unmounting", err)

				if err == nil {
					break
				}

				time.Sleep(1 * time.Second)
			}
		}

		for _, containerDir := range createdContainers {
			for i := 0; i < 100; i++ {
				err := os.RemoveAll(containerDir)

				log.Println("destroying", err)

				if err == nil {
					break
				}

				time.Sleep(1 * time.Second)
			}
		}
	}
}
<commit_msg>only retry cleanup 4 times, not 100<commit_after>// +build linux

package main_test

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var createdContainers = []string{}

func TestWshd(t *testing.T) {
	if os.Getenv("GARDEN_TEST_ROOTFS") != "" {
		RegisterFailHandler(Fail)

		RunSpecs(t, "wshd Suite")

		for _, containerDir := range createdContainers {
			log.Println("cleaning up", containerDir)

			wshdPidfile, err := os.Open(path.Join(containerDir, "run", "wshd.pid"))
			if err == nil {
				var wshdPid int

				_, err := fmt.Fscanf(wshdPidfile, "%d", &wshdPid)
				if err == nil {
					proc, err := os.FindProcess(wshdPid)
					if err == nil {
						log.Println("killing", wshdPid, proc.Kill())
					}
				}
			}

			for i := 0; i < 4; i++ {
				umount := exec.Command("umount", path.Join(containerDir, "mnt"))

				err := umount.Run()

				log.Println("unmounting", err)

				if err == nil {
					break
				}

				time.Sleep(1 * time.Second)
			}
		}

		for _, containerDir := range createdContainers {
			for i := 0; i < 4; i++ {
				err := os.RemoveAll(containerDir)

				log.Println("destroying", err)

				if err == nil {
					break
				}

				time.Sleep(1 * time.Second)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"github.com/samalba/dockerclient"
	"gopkg.in/BlueDragonX/simplelog.v1"
	"strings"
	"time"
)

// Monitor docker for service changes and emit events.
type ServiceMonitor struct {
	client       dockerclient.DockerClient
	hostname     string
	tags         map[string]bool
	configVar    string
	tagsVar      string
	state        int32
	containers   map[string]bool
	services     map[string]*Service
	pollInterval time.Duration
	stop         chan bool
	log          *simplelog.Logger
}

// Create a new service monitor listening on the given URL. Look for service
// config in the Docker environment variable names configVar.
func NewServiceMonitor(url, hostname string, tags []string, configVar, tagsVar string, pollInterval time.Duration, log *simplelog.Logger) (mon *ServiceMonitor, err error) {
	mon = &ServiceMonitor{}
	mon.client, err = dockerclient.NewDockerClient(url, nil)
	mon.hostname = hostname
	mon.tags = make(map[string]bool)
	mon.configVar = configVar
	mon.tagsVar = tagsVar
	mon.state = Stopped
	mon.pollInterval = pollInterval
	mon.stop = make(chan bool)
	mon.log = log

	if tags != nil {
		for _, tag := range tags {
			if tag != "" {
				mon.tags[tag] = true
			}
		}
	}
	return
}

func (mon *ServiceMonitor) addContainer(serviceEvents chan ServiceEvent, containerId string) {
	errorFmt := "container %.12s: %s"
	var err error
	var containerInfo *dockerclient.ContainerInfo
	if containerInfo, err = mon.client.InspectContainer(containerId); err != nil {
		mon.log.Error(errorFmt, containerId, err)
		return
	}

	configEnv := ""
	tagsEnv := ""
	for _, envVar := range containerInfo.Config.Env {
		envName, envValue := parseEnv(envVar)
		if envName == mon.configVar {
			configEnv = envValue
		} else if envName == mon.tagsVar {
			tagsEnv = envValue
		}
	}

	if configEnv == "" {
		mon.log.Debug(errorFmt, containerId, "no services defined, skipping")
		return
	}

	tags := parseTags(tagsEnv)
	if len(mon.tags) > 0 {
		found := false
		for _, tag := range tags {
			if _, found = mon.tags[tag]; found {
				break
			}
		}
		if !found {
			mon.log.Debug(errorFmt, containerId, "not tagged, skipping")
			return
		}
	}

	configValues := strings.Split(configEnv, ",")
	for _, configValue := range configValues {
		svc := &Service{}
		if err = svc.loadConfig(configValue); err != nil {
			mon.log.Warn(errorFmt, containerId, err)
			return
		}
		if err = svc.loadInfo(containerInfo, mon.hostname); err != nil {
			mon.log.Warn(errorFmt, containerId, err)
			return
		}

		oldSvc, update := mon.services[svc.Hash()]
		if update {
			serviceEvents <- ServiceEvent{Heartbeat, svc}
		} else if update && *svc == *oldSvc {
			serviceEvents <- ServiceEvent{Update, svc}
		} else {
			serviceEvents <- ServiceEvent{Add, svc}
		}
		mon.services[svc.Hash()] = svc
	}
}

func (mon *ServiceMonitor) removeContainer(serviceEvents chan ServiceEvent, containerId string) {
	remove := []string{}
	for hash, svc := range mon.services {
		if svc.ContainerId == containerId {
			remove = append(remove, hash)
		}
	}

	for _, hash := range remove {
		serviceEvents <- ServiceEvent{Remove, mon.services[hash]}
		delete(mon.services, hash)
	}
}

func (mon *ServiceMonitor) poll(serviceEvents chan ServiceEvent) {
	var err error
	var containers []dockerclient.Container
	if containers, err = mon.client.ListContainers(false); err != nil {
		mon.log.Error("polling failed: %s", err)
		return
	}

	mon.log.Debug("polling for containers")

	containerIds := make(map[string]bool, len(containers))
	for _, container := range containers {
		mon.addContainer(serviceEvents, container.Id)
		containerIds[container.Id] = true
	}

	for id := range mon.containers {
		if _, ok := containerIds[id]; !ok {
			mon.removeContainer(serviceEvents, id)
		}
	}
	mon.containers = containerIds
}

func (mon *ServiceMonitor) Listen(serviceEvents chan ServiceEvent) error {
	if !stateListening(&mon.state) {
		return errors.New("already listening")
	}

	mon.containers = make(map[string]bool)
	mon.services = make(map[string]*Service)
	containerEvents := make(chan ContainerEvent, 1)

	cb := func(e *dockerclient.Event, args ...interface{}) {
		if e.Status == "start" {
			containerEvents <- ContainerEvent{Add, e.Id}
		} else if e.Status == "die" {
			containerEvents <- ContainerEvent{Remove, e.Id}
		}
	}

	mon.poll(serviceEvents)
	mon.client.StartMonitorEvents(cb)

Loop:
	for {
		select {
		case e := <-containerEvents:
			switch e.State {
			case Add:
				mon.addContainer(serviceEvents, e.ContainerId)
			case Remove:
				mon.removeContainer(serviceEvents, e.ContainerId)
			}
		case <-time.After(mon.pollInterval):
			mon.poll(serviceEvents)
		case <-mon.stop:
			break Loop
		}
	}

	mon.client.StopAllMonitorEvents()
	for _, service := range mon.services {
		serviceEvents <- ServiceEvent{Remove, service}
	}
	close(serviceEvents)

	stateStopped(&mon.state)
	return nil
}

func (mon *ServiceMonitor) Stop() error {
	if !stateStopping(&mon.state) {
		return errors.New("not listening")
	}
	mon.stop <- true
	return nil
}
<commit_msg>Revert "Fix docker client usage."<commit_after>package main

import (
	"errors"
	"github.com/samalba/dockerclient"
	"gopkg.in/BlueDragonX/simplelog.v1"
	"strings"
	"time"
)

// Monitor docker for service changes and emit events.
type ServiceMonitor struct {
	client       *dockerclient.DockerClient
	hostname     string
	tags         map[string]bool
	configVar    string
	tagsVar      string
	state        int32
	containers   map[string]bool
	services     map[string]*Service
	pollInterval time.Duration
	stop         chan bool
	log          *simplelog.Logger
}

// Create a new service monitor listening on the given URL. Look for service
// config in the Docker environment variable names configVar.
func NewServiceMonitor(url, hostname string, tags []string, configVar, tagsVar string, pollInterval time.Duration, log *simplelog.Logger) (mon *ServiceMonitor, err error) {
	mon = &ServiceMonitor{}
	mon.client, err = dockerclient.NewDockerClient(url, nil)
	mon.hostname = hostname
	mon.tags = make(map[string]bool)
	mon.configVar = configVar
	mon.tagsVar = tagsVar
	mon.state = Stopped
	mon.pollInterval = pollInterval
	mon.stop = make(chan bool)
	mon.log = log

	if tags != nil {
		for _, tag := range tags {
			if tag != "" {
				mon.tags[tag] = true
			}
		}
	}
	return
}

func (mon *ServiceMonitor) addContainer(serviceEvents chan ServiceEvent, containerId string) {
	errorFmt := "container %.12s: %s"
	var err error
	var containerInfo *dockerclient.ContainerInfo
	if containerInfo, err = mon.client.InspectContainer(containerId); err != nil {
		mon.log.Error(errorFmt, containerId, err)
		return
	}

	configEnv := ""
	tagsEnv := ""
	for _, envVar := range containerInfo.Config.Env {
		envName, envValue := parseEnv(envVar)
		if envName == mon.configVar {
			configEnv = envValue
		} else if envName == mon.tagsVar {
			tagsEnv = envValue
		}
	}

	if configEnv == "" {
		mon.log.Debug(errorFmt, containerId, "no services defined, skipping")
		return
	}

	tags := parseTags(tagsEnv)
	if len(mon.tags) > 0 {
		found := false
		for _, tag := range tags {
			if _, found = mon.tags[tag]; found {
				break
			}
		}
		if !found {
			mon.log.Debug(errorFmt, containerId, "not tagged, skipping")
			return
		}
	}

	configValues := strings.Split(configEnv, ",")
	for _, configValue := range configValues {
		svc := &Service{}
		if err = svc.loadConfig(configValue); err != nil {
			mon.log.Warn(errorFmt, containerId, err)
			return
		}
		if err = svc.loadInfo(containerInfo, mon.hostname); err != nil {
			mon.log.Warn(errorFmt, containerId, err)
			return
		}

		oldSvc, update := mon.services[svc.Hash()]
		if update {
			serviceEvents <- ServiceEvent{Heartbeat, svc}
		} else if update && *svc == *oldSvc {
			serviceEvents <- ServiceEvent{Update, svc}
		} else {
			serviceEvents <- ServiceEvent{Add, svc}
		}
		mon.services[svc.Hash()] = svc
	}
}

func (mon *ServiceMonitor) removeContainer(serviceEvents chan ServiceEvent, containerId string) {
	remove := []string{}
	for hash, svc := range mon.services {
		if svc.ContainerId == containerId {
			remove = append(remove, hash)
		}
	}

	for _, hash := range remove {
		serviceEvents <- ServiceEvent{Remove, mon.services[hash]}
		delete(mon.services, hash)
	}
}

func (mon *ServiceMonitor) poll(serviceEvents chan ServiceEvent) {
	var err error
	var containers []dockerclient.Container
	if containers, err = mon.client.ListContainers(false); err != nil {
		mon.log.Error("polling failed: %s", err)
		return
	}

	mon.log.Debug("polling for containers")

	containerIds := make(map[string]bool, len(containers))
	for _, container := range containers {
		mon.addContainer(serviceEvents, container.Id)
		containerIds[container.Id] = true
	}

	for id := range mon.containers {
		if _, ok := containerIds[id]; !ok {
			mon.removeContainer(serviceEvents, id)
		}
	}
	mon.containers = containerIds
}

func (mon *ServiceMonitor) Listen(serviceEvents chan ServiceEvent) error {
	if !stateListening(&mon.state) {
		return errors.New("already listening")
	}

	mon.containers = make(map[string]bool)
	mon.services = make(map[string]*Service)
	containerEvents := make(chan ContainerEvent, 1)

	cb := func(e *dockerclient.Event, args ...interface{}) {
		if e.Status == "start" {
			containerEvents <- ContainerEvent{Add, e.Id}
		} else if e.Status == "die" {
			containerEvents <- ContainerEvent{Remove, e.Id}
		}
	}

	mon.poll(serviceEvents)
	mon.client.StartMonitorEvents(cb)

Loop:
	for {
		select {
		case e := <-containerEvents:
			switch e.State {
			case Add:
				mon.addContainer(serviceEvents, e.ContainerId)
			case Remove:
				mon.removeContainer(serviceEvents, e.ContainerId)
			}
		case <-time.After(mon.pollInterval):
			mon.poll(serviceEvents)
		case <-mon.stop:
			break Loop
		}
	}

	mon.client.StopAllMonitorEvents()
	for _, service := range mon.services {
		serviceEvents <- ServiceEvent{Remove, service}
	}
	close(serviceEvents)

	stateStopped(&mon.state)
	return nil
}

func (mon *ServiceMonitor) Stop() error {
	if !stateStopping(&mon.state) {
		return errors.New("not listening")
	}
	mon.stop <- true
	return nil
}
<|endoftext|>


<commit_before>package multiex

import (
	"errors"
	"os"
	"path"
	"reflect"
)

// Struct for describe included commands
// ATTENTION: don't use short initialization form of structure (without field names) - it can have additional fields in
// the feauture.

// Структура для описания подключаемой команды
// ВНИМАНИЕ: не используйте короткую форму инициализации структуры (без указания имен полей) - структура может
// дополняться в будущем и использование короткой формы сломает код при обновлении библиотеки
type ExecutorDescribe struct {
	Function  func() // Pointer for function. Указатель на функцию.
	Name      string // Name os command what was called. Имя команды, по которому функция будет вызываться.
	NoInstall bool   // Don't create symlink when multiex install called. Не создавать ссылку при вызове команды установки.
}

// Task for function registration
// Описание задачи для регистрации функции
type registerQueueTask struct {
	module ExecutorDescribe
	err    chan error
}

// Golang hasn't explicit gurantee about sequense exec of init function. Create chan for gurantee of registration.
// Golang не гарантирует строго последовательного вызова функции init. Создаем канал для гарантии поочередной регистрации функций.
var registerQueue = make(chan registerQueueTask)

// Map of funcctions: name - describe
// Карта функций: имя - описание
var executors = make(map[string]ExecutorDescribe)

// Call executor-function by description
// Вызвать функцию-исполнитель по описанию
func callWorker(module ExecutorDescribe) {
	f := reflect.ValueOf(module.Function)
	f.Call([]reflect.Value{})
}

// Start goroutines for register workers.
// Запускает горутины для регистрации обработчиков
func startRegisterWorker() {
	var registerTask registerQueueTask

	// infinite loop for add modules from queue
	// бесконечный цикл для добавления функций из очереди
	go func() {
		// This defer function ensure infinite goroutine for sequence registration of workers
		// Эта отложенная функция гарантирует непрерывное выполнение горутины для последовательной регистрации обработчиков

		defer func() {
			if err := recover(); err != nil && registerTask.err != nil {
				registerTask.err <- err.(error)
			}
			startRegisterWorker() // restore infinite loop. Восстановить цикл обработки
		}()

		for {
			registerTask = <-registerQueue
			if _, has := executors[registerTask.module.Name]; has {
				registerTask.err <- errors.New("Module has registered already (модуль уже зарегистрирован): '" + registerTask.module.Name + "'")
			} else {
				executors[registerTask.module.Name] = registerTask.module
				registerTask.err <- nil
			}
		}
	}()
}

// Register function as module worker
// Зарегистрировать функцию как обработчик
func Register(module ExecutorDescribe) error {
	if module.Function == nil {
		return errors.New("Function can't be nil")
	}
	if module.Name == "" {
		return errors.New("Name can't be empty")
	}
	errChan := make(chan error)
	registerQueue <- registerQueueTask{module: module, err: errChan}
	return <-errChan
}

// Function to call from executable module for start process dispatch call
// Функция для вызова из выполняемого файла для распознавания и вызова итогового обработчика
func Main() {
	var commandName string

	commandName = os.Args[0]
	commandName = path.Base(commandName)
	module, has := executors[commandName]
	if !has {
		// check explicit command name in first argument
		if len(os.Args) > 1 {
			// restore original args while exit
			oldArgs := make([]string, len(os.Args))
			copy(oldArgs, os.Args)
			defer func() { os.Args = oldArgs }()

			commandName = os.Args[1]
			os.Args = os.Args[1:]
			os.Args[0] = oldArgs[0] // preserve path
		} else {
		}

		module, has = executors[commandName]
	}

	if has {
		callWorker(module)
	} else {
		printUsage()
		printModules()
		return
	}
}

func init() {
	startRegisterWorker()
}
<commit_msg>fix args restore поправлено восстановление аргументов<commit_after>package multiex

import (
	"errors"
	"os"
	"path"
	"reflect"
	"strings"
	"io"
)

// Struct for describe included commands
// ATTENTION: don't use short initialization form of structure (without field names) - it can have additional fields in
// the feauture.

// Структура для описания подключаемой команды
// ВНИМАНИЕ: не используйте короткую форму инициализации структуры (без указания имен полей) - структура может
// дополняться в будущем и использование короткой формы сломает код при обновлении библиотеки
type ExecutorDescribe struct {
	Function  func() // Pointer for function. Указатель на функцию.
	Name      string // Name os command what was called. Имя команды, по которому функция будет вызываться.
	NoInstall bool   // Don't create symlink when multiex install called. Не создавать ссылку при вызове команды установки.
}

// Task for function registration
// Описание задачи для регистрации функции
type registerQueueTask struct {
	module ExecutorDescribe
	err    chan error
}

// Golang hasn't explicit gurantee about sequense exec of init function. Create chan for gurantee of registration.
// Golang не гарантирует строго последовательного вызова функции init. Создаем канал для гарантии поочередной регистрации функций.
var registerQueue = make(chan registerQueueTask)

// Map of funcctions: name - describe
// Карта функций: имя - описание
var executors = make(map[string]ExecutorDescribe)

// Call executor-function by description
// Вызвать функцию-исполнитель по описанию
func callWorker(module ExecutorDescribe) {
	f := reflect.ValueOf(module.Function)
	f.Call([]reflect.Value{})
}

// Start goroutines for register workers.
// Запускает горутины для регистрации обработчиков
func startRegisterWorker() {
	var registerTask registerQueueTask

	// infinite loop for add modules from queue
	// бесконечный цикл для добавления функций из очереди
	go func() {
		// This defer function ensure infinite goroutine for sequence registration of workers
		// Эта отложенная функция гарантирует непрерывное выполнение горутины для последовательной регистрации обработчиков

		defer func() {
			if err := recover(); err != nil && registerTask.err != nil {
				registerTask.err <- err.(error)
			}
			startRegisterWorker() // restore infinite loop. Восстановить цикл обработки
		}()

		for {
			registerTask = <-registerQueue
			if _, has := executors[registerTask.module.Name]; has {
				registerTask.err <- errors.New("Module has registered already (модуль уже зарегистрирован): '" + registerTask.module.Name + "'")
			} else {
				executors[registerTask.module.Name] = registerTask.module
				registerTask.err <- nil
			}
		}
	}()
}

// Register function as module worker
// Зарегистрировать функцию как обработчик
func Register(module ExecutorDescribe) error {
	if module.Function == nil {
		return errors.New("Function can't be nil")
	}
	if module.Name == "" {
		return errors.New("Name can't be empty")
	}
	errChan := make(chan error)
	registerQueue <- registerQueueTask{module: module, err: errChan}
	return <-errChan
}

// Function to call from executable module for start process dispatch call
// Функция для вызова из выполняемого файла для распознавания и вызова итогового обработчика
func Main() {

	// restore original args while exit
	oldArgs := make([]string, len(os.Args))
	copy(oldArgs, os.Args)

	revert_args := func (){
		os.Args = make([]string, len(oldArgs))
		copy(os.Args, oldArgs)
	}

	defer func() { revert_args() }()

	var commandName string

	commandName = os.Args[0]
	commandName = path.Base(commandName)
	module, has := executors[commandName]
	if !has {
		// check explicit command name in first argument
		// Проверка имени команды в первом аргументе
		if len(os.Args) > 1 {

			commandName = os.Args[1]
			os.Args = os.Args[1:]
			os.Args[0] = oldArgs[0] // preserve path. Сохраняем путь к вызываемому бинарнику
			module, has = executors[commandName]

			// If doesn't find command - restore os.Args
			// Если команду не нашли - восстанавливаем аргументы к начальному виду
			if !has{
				revert_args()
			}
		}
	}

	if !has && len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "--multiex-command=") {
		commandName = strings.TrimSpace(os.Args[1])[len("--multiex-command="):]
		os.Args = os.Args[1:]
		os.Args[0] = oldArgs[0] // preserve path. Сохраняем путь вызываемого бинарника

		module, has = executors[commandName]
		// If doesn't find command - restore os.Args
		// Если команду не нашли - восстанавливаем аргументы к начальному виду
		if !has{
			revert_args()
		}
		if has {
			io.WriteString(os.Stderr,
`!!!WARNING!!! --multiex-command is deprecated and will remove in once of next updates
!!!ВНИМАНИЕ!!! --multiex-command устарел и будет удалён в одном из следующих обновлений
`)
		}
	}

	if has {
		callWorker(module)
	} else {
		printUsage()
		printModules()
		return
	}
}

func init() {
	startRegisterWorker()
}
<|endoftext|>


<commit_before>// Copyright 2014 beego 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.
//
// Maintain by https://github.com/slene

package apps

import (
	"fmt"
	"net/url"

	"github.com/astaxie/beego/httplib"

	"github.com/Michael2008S/oauth2beego"
)

type QQ struct {
	BaseProvider
}

func (p *QQ) GetType() social.SocialType {
	return social.SocialQQ
}

func (p *QQ) GetName() string {
	return "QQ"
}

func (p *QQ) GetPath() string {
	return "qq"
}

func (p *QQ) GetIndentify(tok *social.Token) (string, error) {
	uri := "https://graph.z.qq.com/moc2/me?access_token=" + url.QueryEscape(tok.AccessToken)
	req := httplib.Get(uri)
	req.SetTransport(social.DefaultTransport)

	body, err := req.String()
	if err != nil {
		return "", err
	}

	vals, err := url.ParseQuery(body)
	if err != nil {
		return "", err
	}

	if vals.Get("code") != "" {
		return "", fmt.Errorf("code: %s, msg: %s", vals.Get("code"), vals.Get("msg"))
	}

	return vals.Get("openid"), nil
}

var _ social.Provider = new(QQ)

func NewQQ(clientId, secret string) *QQ {
	p := new(QQ)
	p.App = p
	p.ClientId = clientId
	p.ClientSecret = secret
	p.Scope = "get_user_info"
	p.AuthURL = "https://graph.qq.com/oauth2.0/authorize"
	p.TokenURL = "https://graph.qq.com/oauth2.0/token"
	p.RedirectURL = social.DefaultAppUrl + "loginsocial/qq/access"
	p.AccessType = "offline"
	p.ApprovalPrompt = "auto"
	return p
}
<commit_msg>1)修改qq，登陆问题。<commit_after>// Copyright 2014 beego 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.
//
// Maintain by https://github.com/slene

package apps

import (
	"encoding/json"
	"fmt"
	"net/url"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/httplib"

	"github.com/Michael2008S/oauth2beego"
)

type QQ struct {
	BaseProvider
}

func (p *QQ) GetType() social.SocialType {
	return social.SocialQQ
}

func (p *QQ) GetName() string {
	return "QQ"
}

func (p *QQ) GetPath() string {
	return "qq"
}

func (p *QQ) GetIndentify(tok *social.Token) (string, error) {
	uri := "https://graph.qq.com/oauth2.0/me?access_token=" + url.QueryEscape(tok.AccessToken)
	req := httplib.Get(uri)
	req.SetTransport(social.DefaultTransport)

	body, err := req.String()
	if err != nil {
		return "", err
	}

	bodyStr := string(body)

	noCallBackStr := bodyStr[10 : len(bodyStr)-4]

	var f interface{}
	err = json.Unmarshal([]byte(noCallBackStr), &f)
	if err != nil {
		beego.Error(err)

		vals, err := url.ParseQuery(body)
		if err != nil {
			return "", err
		}
		fmt.Println("noCallBackStr:", noCallBackStr)
		if vals.Get("code") != "" {
			return "", fmt.Errorf("code: %s, msg: %s", vals.Get("code"), vals.Get("msg"))
		}

	} else {
		m := f.(map[string]interface{})
		beego.Info(m)
		beego.Error("openid:", (m["openid"]).(string))
		return (m["openid"]).(string), nil
	}
	return "", fmt.Errorf("openid no found")

}

var _ social.Provider = new(QQ)

func NewQQ(clientId, secret string) *QQ {
	p := new(QQ)
	p.App = p
	p.ClientId = clientId
	p.ClientSecret = secret
	p.Scope = "get_user_info"
	p.AuthURL = "https://graph.qq.com/oauth2.0/authorize"
	p.TokenURL = "https://graph.qq.com/oauth2.0/token"
	p.RedirectURL = social.DefaultAppUrl + "loginsocial/qq/access"
	p.AccessType = "offline"
	p.ApprovalPrompt = "auto"
	return p
}
<|endoftext|>


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

package main

import (
	"bytes"
	"crypto/rand"
	"crypto/sha512"
	"fmt"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"labix.org/v2/mgo/bson"
)

const collectionName = "archives"

const (
	StatusBuilding Status = iota
	StatusReady
	StatusError
)

type Status byte

func (s Status) String() string {
	switch s {
	case StatusBuilding:
		return "building"
	case StatusReady:
		return "ready"
	case StatusError:
		return "error"
	default:
		return "unknown"
	}
}

type Archive struct {
	ID     string `bson:"_id"`
	Path   string
	Status Status
	Log    string
}

func NewArchive(path, refid, baseDir, prefix string) (*Archive, error) {
	archive := Archive{
		ID:     newID(path),
		Status: StatusBuilding,
	}
	archive.Path = filepath.Join(baseDir, archive.ID+".tar.gz")
	db, err := conn()
	if err != nil {
		return nil, err
	}
	defer db.Close()
	err = db.Collection(collectionName).Insert(archive)
	if err != nil {
		return nil, err
	}
	go generate(archive, path, refid, archive.Path, prefix)
	return &archive, nil
}

func newID(path string) string {
	var buf [32]byte
	_, err := rand.Read(buf[:])
	if err != nil {
		return ""
	}
	nanoUnix := time.Now().UnixNano()
	hash := sha512.New()
	hash.Write(buf[:])
	hash.Write([]byte(path))
	hash.Write([]byte(fmt.Sprintf("%d", nanoUnix)))
	return fmt.Sprintf("%x", hash.Sum(nil))
}

func generate(archive Archive, repositoryPath, refid, archivePath, prefix string) {
	db, err := conn()
	if err != nil {
		return
	}
	defer db.Close()
	status := StatusReady
	if !strings.HasSuffix(prefix, "/") {
		prefix += "/"
	}
	var buf bytes.Buffer
	command := exec.Command(
		"git", "archive", "--format=tar.gz",
		"--output="+archivePath, "--prefix="+prefix, refid,
	)
	command.Dir = repositoryPath
	command.Stdout = &buf
	command.Stderr = &buf
	if err := command.Run(); err != nil {
		status = StatusError
	}
	archive.Log = buf.String()
	update := bson.M{"$set": bson.M{"status": status, "log": archive.Log}}
	db.Collection(collectionName).UpdateId(archive.ID, update)
}
<commit_msg>archive: make generate a method of Archive<commit_after>// Copyright 2014 Globo.com. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/rand"
	"crypto/sha512"
	"fmt"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"labix.org/v2/mgo/bson"
)

const collectionName = "archives"

const (
	StatusBuilding Status = iota
	StatusReady
	StatusError
)

type Status byte

func (s Status) String() string {
	switch s {
	case StatusBuilding:
		return "building"
	case StatusReady:
		return "ready"
	case StatusError:
		return "error"
	default:
		return "unknown"
	}
}

type Archive struct {
	ID     string `bson:"_id"`
	Path   string
	Status Status
	Log    string
}

func NewArchive(path, refid, baseDir, prefix string) (*Archive, error) {
	archive := Archive{
		ID:     newID(path),
		Status: StatusBuilding,
	}
	archive.Path = filepath.Join(baseDir, archive.ID+".tar.gz")
	db, err := conn()
	if err != nil {
		return nil, err
	}
	defer db.Close()
	err = db.Collection(collectionName).Insert(archive)
	if err != nil {
		return nil, err
	}
	go archive.generate(path, refid, archive.Path, prefix)
	return &archive, nil
}

func (archive Archive) generate(repositoryPath, refid, archivePath, prefix string) {
	db, err := conn()
	if err != nil {
		return
	}
	defer db.Close()
	status := StatusReady
	if !strings.HasSuffix(prefix, "/") {
		prefix += "/"
	}
	var buf bytes.Buffer
	command := exec.Command(
		"git", "archive", "--format=tar.gz",
		"--output="+archivePath, "--prefix="+prefix, refid,
	)
	command.Dir = repositoryPath
	command.Stdout = &buf
	command.Stderr = &buf
	if err := command.Run(); err != nil {
		status = StatusError
	}
	archive.Log = buf.String()
	update := bson.M{"$set": bson.M{"status": status, "log": archive.Log}}
	db.Collection(collectionName).UpdateId(archive.ID, update)
}

func newID(path string) string {
	var buf [32]byte
	_, err := rand.Read(buf[:])
	if err != nil {
		return ""
	}
	nanoUnix := time.Now().UnixNano()
	hash := sha512.New()
	hash.Write(buf[:])
	hash.Write([]byte(path))
	hash.Write([]byte(fmt.Sprintf("%d", nanoUnix)))
	return fmt.Sprintf("%x", hash.Sum(nil))
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"time"

	"github.com/splicers/jet"
)

type Project struct {
	Id        int       `json:"-"`
	Name      string    `json:"name"`
	ApiToken  string    `json:"api_token"`
	CreatedAt time.Time `json:"created_at"`
}

func (p *Project) Store(db *jet.Db) bool {
	var err error
	if p.Id != 0 {
		err = db.Query(`UPDATE projects SET WHERE id = $1`, p.Id).Run()
	} else {
		err = db.Query(`INSERT INTO projects
			(name, api_token, created_at)
			VALUES
			($1, $2, NOW()) RETURNING *`, p.Name, p.ApiToken).Rows(p)
	}
	return err == nil
}

type ProjectsController struct {
	*jet.Db
}

func NewProjectsController(base *jet.Db) *ProjectsController {
	return &ProjectsController{Db: base}
}

const STRLEN = 32

func generateApiToken() string {
	bytes := make([]byte, STRLEN)
	rand.Read(bytes)

	encoding := base64.StdEncoding
	encoded := make([]byte, encoding.EncodedLen(len(bytes)))
	encoding.Encode(encoded, bytes)

	return string(encoded)
}

func (controller *ProjectsController) CreateProject(w http.ResponseWriter, req *http.Request) {
	dec := json.NewDecoder(req.Body)

	var project Project
	if err := dec.Decode(&project); err != nil && err != io.EOF {
		log.Fatal("decode error", err)
	} else {
		project.CreatedAt = time.Now()
	}
	project.ApiToken = generateApiToken()

	// TODO loop until no collision on ApiToken exists

	if !project.Store(controller.Db) {
		log.Fatal("unable to create project")
	}

	b, _ := json.Marshal(project)
	io.WriteString(w, string(b))
}
<commit_msg>loop api token generation to avoid dups<commit_after>package main

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"time"

	"github.com/splicers/jet"
)

type Project struct {
	Id        int       `json:"-"`
	Name      string    `json:"name"`
	ApiToken  string    `json:"api_token"`
	CreatedAt time.Time `json:"created_at"`
}

func (p *Project) Store(db *jet.Db) bool {
	var err error
	if p.Id != 0 {
		err = db.Query(`UPDATE projects SET WHERE id = $1`, p.Id).Run()
	} else {
		err = db.Query(`INSERT INTO projects
			(name, api_token, created_at)
			VALUES
			($1, $2, NOW()) RETURNING *`, p.Name, p.ApiToken).Rows(p)
	}
	return err == nil
}

func (p *Project) IsValid(db *jet.Db) bool {
	if p.Name == "" {
		return false
	}
	if p.ApiToken == "" {
		return false
	}

	exists := new(bool)
	if db.Query(`select 't' from projects where api_token = '$1' limit 1`, p.ApiToken).Rows(&exists); *exists == true {
		return false
	}
	return true
}

type ProjectsController struct {
	*jet.Db
}

func NewProjectsController(base *jet.Db) *ProjectsController {
	return &ProjectsController{Db: base}
}

const STRLEN = 32

func generateApiToken() string {
	bytes := make([]byte, STRLEN)
	rand.Read(bytes)

	encoding := base64.StdEncoding
	encoded := make([]byte, encoding.EncodedLen(len(bytes)))
	encoding.Encode(encoded, bytes)

	return string(encoded)
}

func (controller *ProjectsController) CreateProject(w http.ResponseWriter, req *http.Request) {
	dec := json.NewDecoder(req.Body)

	var project Project
	if err := dec.Decode(&project); err != nil && err != io.EOF {
		log.Fatal("decode error", err)
	} else {
		project.CreatedAt = time.Now()
	}
	project.ApiToken = generateApiToken()

	for i := 0; i < 10; i++ {
		if !project.IsValid(controller.Db) {
			project.ApiToken = generateApiToken()
		} else {
			break
		}
	}
	if !project.IsValid(controller.Db) {
		log.Fatal("project is not valid. %v", project)
	}

	if !project.Store(controller.Db) {
		log.Fatal("unable to create project")
	}

	b, _ := json.Marshal(project)
	io.WriteString(w, string(b))
}
<|endoftext|>


<commit_before>package common

import (
	"context"
	"fmt"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type StepAMIRegionCopy struct {
	AccessConfig      *AccessConfig
	Regions           []string
	AMIKmsKeyId       string
	RegionKeyIds      map[string]string
	EncryptBootVolume *bool // nil means preserve
	Name              string
}

func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(*ec2.EC2)
	ui := state.Get("ui").(packer.Ui)
	amis := state.Get("amis").(map[string]string)
	snapshots := state.Get("snapshots").(map[string][]string)
	ami := amis[*ec2conn.Config.Region]

	if s.EncryptBootVolume != nil {
		// encrypt_boot was set, we now have to copy the temporary
		// AMI with required encryption setting.
		// temp image was created by stepCreateAMI.
		s.Regions = append(s.Regions, *ec2conn.Config.Region)
		if s.RegionKeyIds == nil {
			s.RegionKeyIds = make(map[string]string)
		}
		s.RegionKeyIds[*ec2conn.Config.Region] = s.AMIKmsKeyId
	}

	if len(s.Regions) == 0 {
		return multistep.ActionContinue
	}

	ui.Say(fmt.Sprintf("Copying AMI (%s) to other regions...", ami))

	var lock sync.Mutex
	var wg sync.WaitGroup
	var regKeyID string
	errs := new(packer.MultiError)

	wg.Add(len(s.Regions))
	for _, region := range s.Regions {
		if region == *ec2conn.Config.Region && s.EncryptBootVolume == nil {
			ui.Message(fmt.Sprintf(
				"Avoiding copying AMI to duplicate region %s", region))
			continue
		}

		ui.Message(fmt.Sprintf("Copying to: %s", region))

		if s.EncryptBootVolume != nil && *s.EncryptBootVolume {
			regKeyID = s.RegionKeyIds[region]
		}

		go func(region string) {
			defer wg.Done()
			id, snapshotIds, err := amiRegionCopy(ctx, state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region, regKeyID, s.EncryptBootVolume)
			lock.Lock()
			defer lock.Unlock()
			amis[region] = id
			snapshots[region] = snapshotIds
			if err != nil {
				errs = packer.MultiErrorAppend(errs, err)
			}
		}(region)
	}

	// TODO(mitchellh): Wait but also allow for cancels to go through...
	ui.Message("Waiting for all copies to complete...")
	wg.Wait()

	// If there were errors, show them
	if len(errs.Errors) > 0 {
		state.Put("error", errs)
		ui.Error(errs.Error())
		return multistep.ActionHalt
	}

	state.Put("amis", amis)
	return multistep.ActionContinue
}

func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) {
	// No cleanup...
}

// amiRegionCopy does a copy for the given AMI to the target region and
// returns the resulting ID and snapshot IDs, or error.
func amiRegionCopy(ctx context.Context, state multistep.StateBag, config *AccessConfig, name, imageId,
	target, source, keyId string, encrypt *bool) (string, []string, error) {
	snapshotIds := []string{}

	// Connect to the region where the AMI will be copied to
	session, err := config.Session()
	if err != nil {
		return "", snapshotIds, err
	}

	regionconn := ec2.New(session.Copy(&aws.Config{
		Region: aws.String(target),
	}))

	resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
		SourceRegion:  &source,
		SourceImageId: &imageId,
		Name:          &name,
		Encrypted:     encrypt,
		KmsKeyId:      aws.String(keyId),
	})

	if err != nil {
		return "", snapshotIds, fmt.Errorf("Error Copying AMI (%s) to region (%s): %s",
			imageId, target, err)
	}

	// Wait for the image to become ready
	if err := WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
		return "", snapshotIds, fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
			*resp.ImageId, target, err)
	}

	// Getting snapshot IDs out of the copied AMI
	describeImageResp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{resp.ImageId}})
	if err != nil {
		return "", snapshotIds, fmt.Errorf("Error describing copied AMI (%s) in region (%s): %s",
			imageId, target, err)
	}

	for _, blockDeviceMapping := range describeImageResp.Images[0].BlockDeviceMappings {
		if blockDeviceMapping.Ebs != nil && blockDeviceMapping.Ebs.SnapshotId != nil {
			snapshotIds = append(snapshotIds, *blockDeviceMapping.Ebs.SnapshotId)
		}
	}

	return *resp.ImageId, snapshotIds, nil
}
<commit_msg>if encrypt_boot is explicitly set to false, don't copy. Also, make sure we don't cause a wait group block when we aren't performing a copy.<commit_after>package common

import (
	"context"
	"fmt"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type StepAMIRegionCopy struct {
	AccessConfig      *AccessConfig
	Regions           []string
	AMIKmsKeyId       string
	RegionKeyIds      map[string]string
	EncryptBootVolume *bool // nil means preserve
	Name              string
}

func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(*ec2.EC2)
	ui := state.Get("ui").(packer.Ui)
	amis := state.Get("amis").(map[string]string)
	snapshots := state.Get("snapshots").(map[string][]string)
	ami := amis[*ec2conn.Config.Region]

	if s.EncryptBootVolume != nil {
		// encrypt_boot was set, we now have to copy the temporary
		// AMI with required encryption setting.
		// temp image was created by stepCreateAMI.
		s.Regions = append(s.Regions, *ec2conn.Config.Region)
		if s.RegionKeyIds == nil {
			s.RegionKeyIds = make(map[string]string)
		}
		s.RegionKeyIds[*ec2conn.Config.Region] = s.AMIKmsKeyId
	}

	if len(s.Regions) == 0 {
		return multistep.ActionContinue
	}

	ui.Say(fmt.Sprintf("Copying AMI (%s) to other regions...", ami))

	var lock sync.Mutex
	var wg sync.WaitGroup
	var regKeyID string
	errs := new(packer.MultiError)

	wg.Add(len(s.Regions))
	for _, region := range s.Regions {
		if region == *ec2conn.Config.Region &&
			(s.EncryptBootVolume == nil || *s.EncryptBootVolume == false) {
			ui.Message(fmt.Sprintf(
				"Avoiding copying AMI to duplicate region %s", region))
			wg.Done()
			continue
		}

		ui.Message(fmt.Sprintf("Copying to: %s", region))

		if s.EncryptBootVolume != nil && *s.EncryptBootVolume {
			regKeyID = s.RegionKeyIds[region]
		}

		go func(region string) {
			defer wg.Done()
			id, snapshotIds, err := amiRegionCopy(ctx, state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region, regKeyID, s.EncryptBootVolume)
			lock.Lock()
			defer lock.Unlock()
			amis[region] = id
			snapshots[region] = snapshotIds
			if err != nil {
				errs = packer.MultiErrorAppend(errs, err)
			}
		}(region)
	}

	// TODO(mitchellh): Wait but also allow for cancels to go through...
	ui.Message("Waiting for all copies to complete...")
	wg.Wait()

	// If there were errors, show them
	if len(errs.Errors) > 0 {
		state.Put("error", errs)
		ui.Error(errs.Error())
		return multistep.ActionHalt
	}

	state.Put("amis", amis)
	return multistep.ActionContinue
}

func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) {
	// No cleanup...
}

// amiRegionCopy does a copy for the given AMI to the target region and
// returns the resulting ID and snapshot IDs, or error.
func amiRegionCopy(ctx context.Context, state multistep.StateBag, config *AccessConfig, name, imageId,
	target, source, keyId string, encrypt *bool) (string, []string, error) {
	snapshotIds := []string{}

	// Connect to the region where the AMI will be copied to
	session, err := config.Session()
	if err != nil {
		return "", snapshotIds, err
	}

	regionconn := ec2.New(session.Copy(&aws.Config{
		Region: aws.String(target),
	}))

	resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
		SourceRegion:  &source,
		SourceImageId: &imageId,
		Name:          &name,
		Encrypted:     encrypt,
		KmsKeyId:      aws.String(keyId),
	})

	if err != nil {
		return "", snapshotIds, fmt.Errorf("Error Copying AMI (%s) to region (%s): %s",
			imageId, target, err)
	}

	// Wait for the image to become ready
	if err := WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
		return "", snapshotIds, fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
			*resp.ImageId, target, err)
	}

	// Getting snapshot IDs out of the copied AMI
	describeImageResp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{resp.ImageId}})
	if err != nil {
		return "", snapshotIds, fmt.Errorf("Error describing copied AMI (%s) in region (%s): %s",
			imageId, target, err)
	}

	for _, blockDeviceMapping := range describeImageResp.Images[0].BlockDeviceMappings {
		if blockDeviceMapping.Ebs != nil && blockDeviceMapping.Ebs.SnapshotId != nil {
			snapshotIds = append(snapshotIds, *blockDeviceMapping.Ebs.SnapshotId)
		}
	}

	return *resp.ImageId, snapshotIds, nil
}
<|endoftext|>


<commit_before>package buildpackrunner_test

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

func TestBuildpackrunner(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Buildpackrunner Suite")
}

var tmpDir string
var httpServer *httptest.Server
var gitUrl url.URL

var _ = SynchronizedBeforeSuite(func() []byte {
	gitPath, err := exec.LookPath("git")
	Ω(err).ShouldNot(HaveOccurred())

	tmpDir, err = ioutil.TempDir("", "tmpDir")
	Ω(err).ShouldNot(HaveOccurred())
	tmpDir, err = ioutil.TempDir("", "tmpDir")
	Ω(err).ShouldNot(HaveOccurred())
	buildpackDir := filepath.Join(tmpDir, "fake-buildpack")
	err = os.MkdirAll(buildpackDir, os.ModePerm)
	Ω(err).ShouldNot(HaveOccurred())

	execute(buildpackDir, "rm", "-rf", ".git")
	execute(buildpackDir, gitPath, "init")

	err = ioutil.WriteFile(filepath.Join(buildpackDir, "content"),
		[]byte("some content"), os.ModePerm)
	Ω(err).ShouldNot(HaveOccurred())

	execute(buildpackDir, gitPath, "add", ".")
	execute(buildpackDir, gitPath, "add", "-A")
	execute(buildpackDir, gitPath, "commit", "-am", "fake commit")
	execute(buildpackDir, gitPath, "branch", "a_branch")
	execute(buildpackDir, gitPath, "tag", "-m", "annotated tag", "a_tag")
	execute(buildpackDir, gitPath, "tag", "a_lightweight_tag")
	execute(buildpackDir, gitPath, "update-server-info")

	httpServer = httptest.NewServer(http.FileServer(http.Dir(tmpDir)))

	gitUrl = url.URL{
		Scheme: "http",
		Host:   httpServer.Listener.Addr().String(),
		Path:   "/fake-buildpack/.git",
	}
	return []byte(gitUrl.String())
}, func(data []byte) {
	u, err := url.Parse(string(data))
	Ω(err).ShouldNot(HaveOccurred())
	gitUrl = *u
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	httpServer.Close()
	os.RemoveAll(tmpDir)
})

func execute(dir string, execCmd string, args ...string) {
	cmd := exec.Command(execCmd, args...)
	cmd.Dir = dir
	err := cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())
}
<commit_msg>Set git name and email [#76320826]<commit_after>package buildpackrunner_test

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

func TestBuildpackrunner(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Buildpackrunner Suite")
}

var tmpDir string
var httpServer *httptest.Server
var gitUrl url.URL

var _ = SynchronizedBeforeSuite(func() []byte {
	gitPath, err := exec.LookPath("git")
	Ω(err).ShouldNot(HaveOccurred())

	tmpDir, err = ioutil.TempDir("", "tmpDir")
	Ω(err).ShouldNot(HaveOccurred())
	tmpDir, err = ioutil.TempDir("", "tmpDir")
	Ω(err).ShouldNot(HaveOccurred())
	buildpackDir := filepath.Join(tmpDir, "fake-buildpack")
	err = os.MkdirAll(buildpackDir, os.ModePerm)
	Ω(err).ShouldNot(HaveOccurred())

	execute(buildpackDir, "rm", "-rf", ".git")
	execute(buildpackDir, gitPath, "init")
	execute(buildpackDir, gitPath, "config", "user.email", "you@example.com")
	execute(buildpackDir, gitPath, "config", "user.name", "your name")

	err = ioutil.WriteFile(filepath.Join(buildpackDir, "content"),
		[]byte("some content"), os.ModePerm)
	Ω(err).ShouldNot(HaveOccurred())

	execute(buildpackDir, gitPath, "add", ".")
	execute(buildpackDir, gitPath, "add", "-A")
	execute(buildpackDir, gitPath, "commit", "-am", "fake commit")
	execute(buildpackDir, gitPath, "branch", "a_branch")
	execute(buildpackDir, gitPath, "tag", "-m", "annotated tag", "a_tag")
	execute(buildpackDir, gitPath, "tag", "a_lightweight_tag")
	execute(buildpackDir, gitPath, "update-server-info")

	httpServer = httptest.NewServer(http.FileServer(http.Dir(tmpDir)))

	gitUrl = url.URL{
		Scheme: "http",
		Host:   httpServer.Listener.Addr().String(),
		Path:   "/fake-buildpack/.git",
	}
	return []byte(gitUrl.String())
}, func(data []byte) {
	u, err := url.Parse(string(data))
	Ω(err).ShouldNot(HaveOccurred())
	gitUrl = *u
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	httpServer.Close()
	os.RemoveAll(tmpDir)
})

func execute(dir string, execCmd string, args ...string) {
	cmd := exec.Command(execCmd, args...)
	cmd.Dir = dir
	err := cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())
}
<|endoftext|>