<commit_before>package tumblr

import (
	"encoding/json"
	"fmt"
	"github.com/MariaTerzieva/gotumblr"
	// Used for getting tumblr env vars
	_ "github.com/joho/godotenv/autoload"
	"os"
	"strconv"
)

const (
	tumblrURL  = "http://api.tumblr.com"
	blogName   = "devopsreactions.tumblr.com"
	blogTypes  = "text"
	postsLimit = 20
)

func GetPosts() []gotumblr.TextPost {
	var posts, newPosts []gotumblr.TextPost
	offset := 0
	client := getTumblrClient()
	for len(newPosts) == postsLimit || offset == 0 {
		options := getTumblrOptions(offset)
		postsResponse := client.Posts(blogName, blogTypes, options)
		newPosts = parsePosts(postsResponse)
		posts = append(posts, newPosts...)
		offset += postsLimit
	}
	return posts
}

func getTumblrClient() *gotumblr.TumblrRestClient {
	client := gotumblr.NewTumblrRestClient(
		os.Getenv("CONSUMER_KEY"),
		os.Getenv("CONSUMER_SECRET"),
		os.Getenv("TOKEN"),
		os.Getenv("TOKEN_SECRET"),
		"https://www.albertyw.com/",
		tumblrURL,
	)
	return client
}

func getTumblrOptions(offset int) map[string]string {
	options := map[string]string{}
	options["offset"] = strconv.Itoa(offset)
	options["limit"] = strconv.Itoa(postsLimit)
	return options
}

func parsePosts(postsResponse gotumblr.PostsResponse) []gotumblr.TextPost {
	var posts []gotumblr.TextPost
	var post gotumblr.TextPost
	for _, element := range postsResponse.Posts {
		err := json.Unmarshal(element, &post)
		if err != nil {
			fmt.Println(err)
		} else {
			posts = append(posts, post)
		}
	}
	return posts
}
<commit_msg>Add status messages<commit_after>package tumblr

import (
	"encoding/json"
	"fmt"
	"github.com/MariaTerzieva/gotumblr"
	// Used for getting tumblr env vars
	_ "github.com/joho/godotenv/autoload"
	"os"
	"strconv"
)

const (
	tumblrURL  = "http://api.tumblr.com"
	blogName   = "devopsreactions.tumblr.com"
	blogTypes  = "text"
	postsLimit = 20
)

func GetPosts() []gotumblr.TextPost {
	var posts, newPosts []gotumblr.TextPost
	offset := 0
	client := getTumblrClient()
	for len(newPosts) == postsLimit || offset == 0 {
		fmt.Println("Downloading", offset)
		options := getTumblrOptions(offset)
		postsResponse := client.Posts(blogName, blogTypes, options)
		newPosts = parsePosts(postsResponse)
		posts = append(posts, newPosts...)
		offset += postsLimit
	}
	return posts
}

func getTumblrClient() *gotumblr.TumblrRestClient {
	client := gotumblr.NewTumblrRestClient(
		os.Getenv("CONSUMER_KEY"),
		os.Getenv("CONSUMER_SECRET"),
		os.Getenv("TOKEN"),
		os.Getenv("TOKEN_SECRET"),
		"https://www.albertyw.com/",
		tumblrURL,
	)
	return client
}

func getTumblrOptions(offset int) map[string]string {
	options := map[string]string{}
	options["offset"] = strconv.Itoa(offset)
	options["limit"] = strconv.Itoa(postsLimit)
	return options
}

func parsePosts(postsResponse gotumblr.PostsResponse) []gotumblr.TextPost {
	var posts []gotumblr.TextPost
	var post gotumblr.TextPost
	for _, element := range postsResponse.Posts {
		err := json.Unmarshal(element, &post)
		if err != nil {
			fmt.Println(err)
		} else {
			posts = append(posts, post)
		}
	}
	return posts
}
<|endoftext|>


<commit_before>package tunnel

import (
	"errors"

	"github.com/koding/klient/Godeps/_workspace/src/github.com/koding/kite"
	"github.com/koding/tunnel"
)

type registerResult struct {
	VirtualHost string
	Identifier  string
}

func Start(k *kite.Kite, conf *tunnel.ClientConfig) error {
	if conf.ServerAddr == "" {
		return errors.New("Tunnel server addr is empty")
	}

	tunnelserver := k.NewClient("http://" + conf.ServerAddr + "/kite")
	connected, err := tunnelserver.DialForever()
	if err != nil {
		return err
	}

	<-connected

	conf.FetchIdentifier = func() (string, error) {
		result, err := callRegister(tunnelserver)
		if err != nil {
			return "", err
		}

		k.Log.Info("Our tunnel public host is: '%s'", result.VirtualHost)
		return result.Identifier, nil
	}

	client, err := tunnel.NewClient(conf)
	if err != nil {
		return err
	}

	go client.Start()
	return nil
}

func callRegister(tunnelserver *kite.Client) (*registerResult, error) {
	response, err := tunnelserver.Tell("register", nil)
	if err != nil {
		return nil, err
	}

	result := &registerResult{}
	err = response.Unmarshal(result)
	if err != nil {
		return nil, err
	}

	return result, nil
}
<commit_msg>tunnel: should use vendored package<commit_after>package tunnel

import (
	"errors"

	"github.com/koding/klient/Godeps/_workspace/src/github.com/koding/kite"
	"github.com/koding/klient/Godeps/_workspace/src/github.com/koding/tunnel"
)

type registerResult struct {
	VirtualHost string
	Identifier  string
}

func Start(k *kite.Kite, conf *tunnel.ClientConfig) error {
	if conf.ServerAddr == "" {
		return errors.New("Tunnel server addr is empty")
	}

	tunnelserver := k.NewClient("http://" + conf.ServerAddr + "/kite")
	connected, err := tunnelserver.DialForever()
	if err != nil {
		return err
	}

	<-connected

	conf.FetchIdentifier = func() (string, error) {
		result, err := callRegister(tunnelserver)
		if err != nil {
			return "", err
		}

		k.Log.Info("Our tunnel public host is: '%s'", result.VirtualHost)
		return result.Identifier, nil
	}

	client, err := tunnel.NewClient(conf)
	if err != nil {
		return err
	}

	go client.Start()
	return nil
}

func callRegister(tunnelserver *kite.Client) (*registerResult, error) {
	response, err := tunnelserver.Tell("register", nil)
	if err != nil {
		return nil, err
	}

	result := &registerResult{}
	err = response.Unmarshal(result)
	if err != nil {
		return nil, err
	}

	return result, nil
}
<|endoftext|>


<commit_before>package core

import "strings"

type ListType struct {
	first *Thunk
	rest  *Thunk
}

var (
	emptyList = ListType{nil, nil}
	EmptyList = Normal(emptyList)
)

func NewList(ts ...*Thunk) *Thunk {
	l := Normal(emptyList)

	for i := len(ts) - 1; i >= 0; i-- {
		l = Normal(cons(ts[i], l))
	}

	return l
}

func (l ListType) equal(e equalable) Object {
	ll := e.(ListType)

	if l == emptyList || ll == emptyList {
		return rawBool(l == ll)
	}

	for _, t := range []*Thunk{
		// Don't evaluate these parallelly for short circuit behavior.
		PApp(Equal, l.first, ll.first),
		PApp(Equal, l.rest, ll.rest),
	} {
		o := t.Eval()
		b, ok := o.(BoolType)

		if !ok {
			return NotBoolError(o)
		} else if !b {
			return False
		}
	}

	return True
}

var Prepend = NewLazyFunction(
	NewSignature(
		[]string{}, []OptionalArgument{}, "elemsAndList",
		[]string{}, []OptionalArgument{}, "",
	),
	func(ts ...*Thunk) Object {
		o := ts[0].Eval()
		ts, err := o.(ListType).ToThunks()

		if err != nil {
			return err
		} else if len(ts) == 0 {
			return NumArgsError("prepend", "> 0")
		}

		last := len(ts) - 1
		t := ts[last]

		for i := last - 1; i >= 0; i-- {
			t = Normal(cons(ts[i], t))
		}

		return t
	})

func cons(t1, t2 *Thunk) ListType {
	return ListType{t1, t2}
}

var First = NewStrictFunction(
	NewSignature(
		[]string{"list"}, []OptionalArgument{}, "",
		[]string{}, []OptionalArgument{}, "",
	),
	func(os ...Object) Object {
		o := os[0]
		l, ok := o.(ListType)

		if !ok {
			return NotListError(o)
		} else if l == emptyList {
			return emptyListError()
		}

		return l.first
	})

var Rest = NewStrictFunction(
	NewSignature(
		[]string{"list"}, []OptionalArgument{}, "",
		[]string{}, []OptionalArgument{}, "",
	),
	func(os ...Object) Object {
		o := os[0]
		l, ok := o.(ListType)

		if !ok {
			return NotListError(o)
		} else if l == emptyList {
			return emptyListError()
		}

		return l.rest
	})

var appendFuncSignature = NewSignature(
	[]string{"list", "elem"}, []OptionalArgument{}, "",
	[]string{}, []OptionalArgument{}, "",
)

var Append = NewLazyFunction(appendFuncSignature, appendFunc)

func appendFunc(ts ...*Thunk) Object {
	o := ts[0].Eval()
	l, ok := o.(ListType)

	if !ok {
		return NotListError(o)
	}

	if l == emptyList {
		return NewList(ts[1])
	}

	return cons(
		l.first,
		PApp(NewLazyFunction(appendFuncSignature, appendFunc), l.rest, ts[1]),
	)
}

func emptyListError() *Thunk {
	return ValueError("The list is empty. You cannot apply rest.")
}

func (l ListType) merge(ts ...*Thunk) Object {
	if l == emptyList {
		return PApp(Merge, ts...)
	}

	return cons(l.first, PApp(Merge, append([]*Thunk{l.rest}, ts...)...))
}

func (l ListType) less(ord ordered) bool {
	ll := ord.(ListType)

	if ll == emptyList {
		return false
	} else if l == emptyList {
		return true
	}

	// Compare firsts

	o1 := l.first.Eval()
	o2 := ll.first.Eval()

	if less(o1, o2) {
		return true
	} else if less(o2, o1) {
		return false
	}

	// Compare rests

	return less(l.rest.Eval(), ll.rest.Eval())
}

func (l ListType) string() Object {
	os, err := l.ToObjects()

	if err != nil {
		return err.Eval()
	}

	ss := make([]string, len(os))

	for i, o := range os {
		if err, ok := o.(ErrorType); ok {
			return err
		}

		o = PApp(ToString, Normal(o)).Eval()
		s, ok := o.(StringType)

		if !ok {
			return NotStringError(o)
		}

		ss[i] = string(s)
	}

	return StringType("[" + strings.Join(ss, " ") + "]")
}

func (l ListType) ToThunks() ([]*Thunk, *Thunk) {
	ts := make([]*Thunk, 0)

	for l != emptyList {
		ts = append(ts, l.first)

		o := l.rest.Eval()
		var ok bool
		l, ok = o.(ListType)

		if !ok {
			return nil, NotListError(o)
		}
	}

	return ts, nil
}

func (l ListType) ToObjects() ([]Object, *Thunk) {
	ts, err := l.ToThunks()

	if err != nil {
		return nil, err
	}

	os := make([]Object, len(ts))

	for _, t := range ts {
		go t.Eval()
	}

	for i, t := range ts {
		os[i] = t.Eval()
	}

	return os, nil
}
<commit_msg>Add documentation of core/list.go<commit_after>package core

import "strings"

// ListType represents a sequence of values.
// They can have infinite number of elements inside.
type ListType struct {
	first *Thunk
	rest  *Thunk
}

var (
	emptyList = ListType{nil, nil}

	// EmptyList is a thunk of an empty list.
	EmptyList = Normal(emptyList)
)

// NewList creates a list from its elements.
func NewList(ts ...*Thunk) *Thunk {
	l := Normal(emptyList)

	for i := len(ts) - 1; i >= 0; i-- {
		l = Normal(cons(ts[i], l))
	}

	return l
}

func (l ListType) equal(e equalable) Object {
	ll := e.(ListType)

	if l == emptyList || ll == emptyList {
		return rawBool(l == ll)
	}

	for _, t := range []*Thunk{
		// Don't evaluate these parallelly for short circuit behavior.
		PApp(Equal, l.first, ll.first),
		PApp(Equal, l.rest, ll.rest),
	} {
		o := t.Eval()
		b, ok := o.(BoolType)

		if !ok {
			return NotBoolError(o)
		} else if !b {
			return False
		}
	}

	return True
}

// Prepend prepends multiple elements to a list of the last argument.
var Prepend = NewLazyFunction(
	NewSignature(
		[]string{}, []OptionalArgument{}, "elemsAndList",
		[]string{}, []OptionalArgument{}, "",
	),
	func(ts ...*Thunk) Object {
		o := ts[0].Eval()
		ts, err := o.(ListType).ToThunks()

		if err != nil {
			return err
		} else if len(ts) == 0 {
			return NumArgsError("prepend", "> 0")
		}

		last := len(ts) - 1
		t := ts[last]

		for i := last - 1; i >= 0; i-- {
			t = Normal(cons(ts[i], t))
		}

		return t
	})

func cons(t1, t2 *Thunk) ListType {
	return ListType{t1, t2}
}

// First takes the first element in a list.
var First = NewStrictFunction(
	NewSignature(
		[]string{"list"}, []OptionalArgument{}, "",
		[]string{}, []OptionalArgument{}, "",
	),
	func(os ...Object) Object {
		o := os[0]
		l, ok := o.(ListType)

		if !ok {
			return NotListError(o)
		} else if l == emptyList {
			return emptyListError()
		}

		return l.first
	})

// Rest returns a list which has the second to last elements of a given list.
var Rest = NewStrictFunction(
	NewSignature(
		[]string{"list"}, []OptionalArgument{}, "",
		[]string{}, []OptionalArgument{}, "",
	),
	func(os ...Object) Object {
		o := os[0]
		l, ok := o.(ListType)

		if !ok {
			return NotListError(o)
		} else if l == emptyList {
			return emptyListError()
		}

		return l.rest
	})

var appendFuncSignature = NewSignature(
	[]string{"list", "elem"}, []OptionalArgument{}, "",
	[]string{}, []OptionalArgument{}, "",
)

// Append appends an element at the end of a given list.
var Append = NewLazyFunction(appendFuncSignature, appendFunc)

func appendFunc(ts ...*Thunk) Object {
	o := ts[0].Eval()
	l, ok := o.(ListType)

	if !ok {
		return NotListError(o)
	}

	if l == emptyList {
		return NewList(ts[1])
	}

	return cons(
		l.first,
		PApp(NewLazyFunction(appendFuncSignature, appendFunc), l.rest, ts[1]),
	)
}

func emptyListError() *Thunk {
	return ValueError("The list is empty. You cannot apply rest.")
}

func (l ListType) merge(ts ...*Thunk) Object {
	if l == emptyList {
		return PApp(Merge, ts...)
	}

	return cons(l.first, PApp(Merge, append([]*Thunk{l.rest}, ts...)...))
}

func (l ListType) less(ord ordered) bool {
	ll := ord.(ListType)

	if ll == emptyList {
		return false
	} else if l == emptyList {
		return true
	}

	// Compare firsts

	o1 := l.first.Eval()
	o2 := ll.first.Eval()

	if less(o1, o2) {
		return true
	} else if less(o2, o1) {
		return false
	}

	// Compare rests

	return less(l.rest.Eval(), ll.rest.Eval())
}

func (l ListType) string() Object {
	os, err := l.ToObjects()

	if err != nil {
		return err.Eval()
	}

	ss := make([]string, len(os))

	for i, o := range os {
		if err, ok := o.(ErrorType); ok {
			return err
		}

		o = PApp(ToString, Normal(o)).Eval()
		s, ok := o.(StringType)

		if !ok {
			return NotStringError(o)
		}

		ss[i] = string(s)
	}

	return StringType("[" + strings.Join(ss, " ") + "]")
}

// ToThunks converts a list into a slice of its elements as thunks.
func (l ListType) ToThunks() ([]*Thunk, *Thunk) {
	ts := make([]*Thunk, 0)

	for l != emptyList {
		ts = append(ts, l.first)

		o := l.rest.Eval()
		var ok bool
		l, ok = o.(ListType)

		if !ok {
			return nil, NotListError(o)
		}
	}

	return ts, nil
}

// ToObjects converts a list into a slice of its elements as objects.
func (l ListType) ToObjects() ([]Object, *Thunk) {
	ts, err := l.ToThunks()

	if err != nil {
		return nil, err
	}

	os := make([]Object, len(ts))

	for _, t := range ts {
		go t.Eval()
	}

	for i, t := range ts {
		os[i] = t.Eval()
	}

	return os, nil
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
)

func sprint(x interface{}) StringType {
	return StringType(fmt.Sprint(x))
}

type dumpable interface {
	dump() Value
}

// Dump dumps a value into a string type value.
var Dump = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value {
		v := ts[0].Eval()

		switch x := v.(type) {
		case ErrorType:
			return x
		case dumpable:
			v = x.dump()
		default:
			v = PApp(ToString, Normal(v)).Eval()
		}

		if _, ok := v.(StringType); !ok {
			return NotStringError(v)
		}

		return v
	})

// internalDumpOrFail is the same as DumpOrFail.
func internalDumpOrFail(v Value) string {
	v = ensureWHNF(v)

	switch x := v.(type) {
	case ErrorType:
		panic(x)
	case dumpable:
		v = x.dump()
	case stringable:
		v = x.string()
	default:
		panic(fmt.Sprintf("Invalid value detected: %#v", v))
	}

	if s, ok := v.(StringType); ok {
		return string(s)
	}

	panic(fmt.Sprintf("Invalid value detected: %#v", v))
}

// DumpOrFail dumps a value into a string value or fail exiting a process.
// This function should be used only to create strings of error information.
func DumpOrFail(v Value) string {
	v = PApp(Dump, Normal(v)).Eval()
	s, ok := v.(StringType)

	if !ok {
		panic(NotStringError(v).Eval().(ErrorType))
	}

	return string(s)
}

// Equal checks if 2 values are equal or not.
var Equal = NewStrictFunction(
	NewSignature(
		[]string{"x", "y"}, nil, "",
		nil, nil, "",
	),
	func(ts ...*Thunk) (v Value) {
		defer func() {
			if r := recover(); r != nil {
				v = r
			}
		}()

		return BoolType(compare(ts[0].Eval(), ts[1].Eval()) == 0)
	})

// ensureWHNF evaluates nested thunks into WHNF values.
// This function must be used with care because it prevents tail call
// elimination.
func ensureWHNF(v Value) Value {
	if t, ok := v.(*Thunk); ok {
		return t.Eval()
	}

	return v
}

var identity = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value { return ts[0] })

// TypeOf returns a type name of an argument as a string.
var TypeOf = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value {
		// No case of OutputType should be here.
		switch ts[0].Eval().(type) {
		case BoolType:
			return NewString("bool")
		case DictionaryType:
			return NewString("dict")
		case ListType:
			return NewString("list")
		case NilType:
			return NewString("nil")
		case NumberType:
			return NewString("number")
		case StringType:
			return NewString("string")

		case functionType:
			return NewString("function")
		case closureType:
			return NewString("function")

		case ErrorType:
			return NewString("error")
		}

		panic(fmt.Errorf("Invalid value: %#v", ts[0].Eval()))
	})
<commit_msg>Remove invalid case in internalDumpOrFail<commit_after>package core

import (
	"fmt"
)

func sprint(x interface{}) StringType {
	return StringType(fmt.Sprint(x))
}

type dumpable interface {
	dump() Value
}

// Dump dumps a value into a string type value.
var Dump = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value {
		v := ts[0].Eval()

		switch x := v.(type) {
		case ErrorType:
			return x
		case dumpable:
			v = x.dump()
		default:
			v = PApp(ToString, Normal(v)).Eval()
		}

		if _, ok := v.(StringType); !ok {
			return NotStringError(v)
		}

		return v
	})

// internalDumpOrFail is the same as DumpOrFail.
func internalDumpOrFail(v Value) string {
	v = ensureWHNF(v)

	switch x := v.(type) {
	case dumpable:
		v = x.dump()
	case stringable:
		v = x.string()
	default:
		panic(fmt.Sprintf("Invalid value detected: %#v", v))
	}

	if s, ok := v.(StringType); ok {
		return string(s)
	}

	panic(fmt.Sprintf("Invalid value detected: %#v", v))
}

// DumpOrFail dumps a value into a string value or fail exiting a process.
// This function should be used only to create strings of error information.
func DumpOrFail(v Value) string {
	v = PApp(Dump, Normal(v)).Eval()
	s, ok := v.(StringType)

	if !ok {
		panic(NotStringError(v).Eval().(ErrorType))
	}

	return string(s)
}

// Equal checks if 2 values are equal or not.
var Equal = NewStrictFunction(
	NewSignature(
		[]string{"x", "y"}, nil, "",
		nil, nil, "",
	),
	func(ts ...*Thunk) (v Value) {
		defer func() {
			if r := recover(); r != nil {
				v = r
			}
		}()

		return BoolType(compare(ts[0].Eval(), ts[1].Eval()) == 0)
	})

// ensureWHNF evaluates nested thunks into WHNF values.
// This function must be used with care because it prevents tail call
// elimination.
func ensureWHNF(v Value) Value {
	if t, ok := v.(*Thunk); ok {
		return t.Eval()
	}

	return v
}

var identity = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value { return ts[0] })

// TypeOf returns a type name of an argument as a string.
var TypeOf = NewLazyFunction(
	NewSignature([]string{"x"}, nil, "", nil, nil, ""),
	func(ts ...*Thunk) Value {
		// No case of OutputType should be here.
		switch ts[0].Eval().(type) {
		case BoolType:
			return NewString("bool")
		case DictionaryType:
			return NewString("dict")
		case ListType:
			return NewString("list")
		case NilType:
			return NewString("nil")
		case NumberType:
			return NewString("number")
		case StringType:
			return NewString("string")

		case functionType:
			return NewString("function")
		case closureType:
			return NewString("function")

		case ErrorType:
			return NewString("error")
		}

		panic(fmt.Errorf("Invalid value: %#v", ts[0].Eval()))
	})
<|endoftext|>


<commit_before>package docker

import (
	"context"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"log"
	"net/http"
	"os"
	"regexp"
)

const host = `DOCKER_HOST`
const version = `DOCKER_VERSION`

var containersRequest = regexp.MustCompile(`^/containers$`)

type results struct {
	Results interface{} `json:"results"`
}

var docker *client.Client

func init() {
	client, err := client.NewClient(os.Getenv(host), os.Getenv(version), nil, nil)
	if err != nil {
		log.Fatal(err)
	} else {
		docker = client
	}
}

func listContainers() []types.Container {
	containers, err := docker.ContainerList(context.Background(), types.ContainerListOptions{})
	if err != nil {
		log.Fatal(err)
		return nil
	}

	return containers
}

func containersHandler(w http.ResponseWriter) {
	jsonHttp.ResponseJSON(w, results{listContainers()})
}

func isAuthenticated(r *http.Request) bool {
	_, _, ok := r.BasicAuth()
	return ok
}

func authHandler(w http.ResponseWriter) {
	http.Error(w, `Authentication required`, http.StatusUnauthorized)
}

// Handler for Hello request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type, Authorization`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	urlPath := []byte(r.URL.Path)

	if containersRequest.Match(urlPath) && r.Method == http.MethodGet {
		containersHandler(w)
	} else if isAuthenticated(r) {
		jsonHttp.ResponseJSON(w, results{listContainers()})
	} else {
		authHandler(w)
	}
}
<commit_msg>Restoring options preflight request<commit_after>package docker

import (
	"context"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"log"
	"net/http"
	"os"
	"regexp"
)

const host = `DOCKER_HOST`
const version = `DOCKER_VERSION`

var containersRequest = regexp.MustCompile(`^/containers$`)

type results struct {
	Results interface{} `json:"results"`
}

var docker *client.Client

func init() {
	client, err := client.NewClient(os.Getenv(host), os.Getenv(version), nil, nil)
	if err != nil {
		log.Fatal(err)
	} else {
		docker = client
	}
}

func listContainers() []types.Container {
	containers, err := docker.ContainerList(context.Background(), types.ContainerListOptions{})
	if err != nil {
		log.Fatal(err)
		return nil
	}

	return containers
}

func containersHandler(w http.ResponseWriter) {
	jsonHttp.ResponseJSON(w, results{listContainers()})
}

func isAuthenticated(r *http.Request) bool {
	_, _, ok := r.BasicAuth()
	return ok
}

func authHandler(w http.ResponseWriter) {
	http.Error(w, `Authentication required`, http.StatusUnauthorized)
}

// Handler for Hello request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type, Authorization`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	if r.Method == http.MethodOptions {
		w.Write(nil)
		return
	}

	urlPath := []byte(r.URL.Path)

	if containersRequest.Match(urlPath) && r.Method == http.MethodGet {
		containersHandler(w)
	} else if isAuthenticated(r) {
		jsonHttp.ResponseJSON(w, results{listContainers()})
	} else {
		authHandler(w)
	}
}
<|endoftext|>


<commit_before><commit_msg>remove Underlying (no longer necessary)<commit_after><|endoftext|>


<commit_before><commit_msg>添加 web.NewPlugin 函数<commit_after><|endoftext|>


<commit_before>// Package quickfix provides functions for fixing Go ASTs
// that are well typed but "go build" refuses to build.
package quickfix

import (
	"fmt"
	"regexp"
	"strings"

	"go/ast"
	"go/token"

	"golang.org/x/tools/go/ast/astutil"
	_ "golang.org/x/tools/go/gcimporter"
	"golang.org/x/tools/go/types"
)

var (
	declaredNotUsed        = regexp.MustCompile(`^([a-zA-Z0-9_]+) declared but not used$`)
	importedNotUsed        = regexp.MustCompile(`^(".+") imported but not used$`)
	noNewVariablesOnDefine = "no new variables on left side of :="
)

// QuickFix rewrites AST files of same package so that they pass go build.
// For example:
//   v declared but not used             -> append `_ = v`
//   "p" imported but not used           -> rewrite to `import _ "p"`
//   no new variables on left side of := -> rewrite `:=` to `=`
//
// TODO implement hardMode, which removes errorneous code rather than adding
func QuickFix(fset *token.FileSet, files []*ast.File) (err error) {
	const maxTries = 10
	for i := 0; i < maxTries; i++ {
		var foundError bool
		foundError, err = quickFix1(fset, files)
		if !foundError {
			return nil
		}
	}

	return
}

type tracedVisitor struct {
	path  []ast.Node
	visit func(ast.Node, []ast.Node) bool
}

func (v tracedVisitor) Visit(node ast.Node) ast.Visitor {
	if v.visit(node, v.path) {
		return tracedVisitor{
			path:  append([]ast.Node{node}, v.path...),
			visit: v.visit,
		}
	}

	return nil
}

func traverseAST(node ast.Node, visit func(ast.Node, []ast.Node) bool) {
	v := tracedVisitor{
		visit: visit,
	}
	ast.Walk(v, node)
}

// pkgsWithSideEffect are set of packages which are known to provide APIs by
// blank identifier import (import _ "p").
var pkgsWithSideEffect = map[string]bool{}

func init() {
	for _, path := range []string{
		"expvar",
		"image/gif",
		"image/jpeg",
		"image/png",
		"net/http/pprof",
		"unsafe",
		"golang.org/x/image/bmp",
		"golang.org/x/image/tiff",
		"golang.org/x/image/vp8",
		"golang.org/x/image/vp81",
		"golang.org/x/image/webp",
		"golang.org/x/tools/go/gcimporter",
	} {
		pkgsWithSideEffect[`"`+path+`"`] = true
	}
}

// RevertQuickFix reverts possible quickfixes introduced by QuickFix.
// This may result to non-buildable source, and cannot reproduce the original
// code before first QuickFix.
// For example:
//   `_ = v`        -> removed
//   `import _ "p"` -> rewritten to `import "p"`
func RevertQuickFix(fset *token.FileSet, files []*ast.File) (err error) {
	nodeToRemove := map[ast.Node]bool{}

	for _, f := range files {
		ast.Inspect(f, func(node ast.Node) bool {
			if assign, ok := node.(*ast.AssignStmt); ok {
				if len(assign.Lhs) == 1 && isBlankIdent(assign.Lhs[0]) &&
					len(assign.Rhs) == 1 && isIdent(assign.Rhs[0]) {
					// The statement is `_ = v`
					nodeToRemove[node] = true
				}

				return false
			} else if imp, ok := node.(*ast.ImportSpec); ok {
				if isBlankIdent(imp.Name) && !pkgsWithSideEffect[imp.Path.Value] {
					// The spec is `import _ "p"` and p is not a package that
					// provides "side effects"
					imp.Name = nil
				}

				return false
			}

			return true
		})

		for len(nodeToRemove) > 0 {
			traverseAST(f, func(node ast.Node, nodepath []ast.Node) bool {
				if nodeToRemove[node] {
					parent := nodepath[0]
					if removeChildNode(node, parent) == false {
						err = fmt.Errorf(
							"BUG: could not remove node: %s (in: %s)",
							fset.Position(node.Pos()),
							fset.Position(parent.Pos()),
						)
					}
					delete(nodeToRemove, node)
					return false
				}

				return true
			})
		}
	}

	return
}

func quickFix1(fset *token.FileSet, files []*ast.File) (bool, error) {
	errs := []error{}
	config := &types.Config{
		Error: func(err error) {
			errs = append(errs, err)
		},
	}

	_, err := config.Check("_quickfix", fset, files, nil)
	if err == nil {
		return false, nil
	}

	// apply fixes on AST later so that we won't break funcs that inspect AST by positions
	fixes := map[error]func() bool{}
	unhandled := errorList{}

	foundError := len(errs) > 0

	for _, err := range errs {
		err, ok := err.(types.Error)
		if !ok {
			unhandled = append(unhandled, err)
			continue
		}

		f := findFile(files, err.Pos)
		if f == nil {
			e := ErrCouldNotLocate{
				Err:  err,
				Fset: fset,
			}
			unhandled = append(unhandled, e)
			continue
		}

		nodepath, _ := astutil.PathEnclosingInterval(f, err.Pos, err.Pos)

		var fix func() bool

		// - "%s declared but not used"
		// - "%q imported but not used"
		// - "label %s declared but not used" TODO
		// - "no new variables on left side of :="
		if m := declaredNotUsed.FindStringSubmatch(err.Msg); m != nil {
			identName := m[1]
			fix = func() bool {
				return fixDeclaredNotUsed(nodepath, identName)
			}
		} else if m := importedNotUsed.FindStringSubmatch(err.Msg); m != nil {
			pkgPath := m[1] // quoted string, but it's okay because this will be compared to ast.BasicLit.Value.
			fix = func() bool {
				return fixImportedNotUsed(nodepath, pkgPath)
			}
		} else if err.Msg == noNewVariablesOnDefine {
			fix = func() bool {
				return fixNoNewVariables(nodepath)
			}
		} else {
			unhandled = append(unhandled, err)
		}

		if fix != nil {
			fixes[err] = fix
		}
	}

	for err, fix := range fixes {
		if fix() == false {
			unhandled = append(unhandled, err)
		}
	}

	return foundError, unhandled.any()
}

func fixDeclaredNotUsed(nodepath []ast.Node, identName string) bool {
	// insert "_ = x" to supress "declared but not used" error
	stmt := &ast.AssignStmt{
		Lhs: []ast.Expr{ast.NewIdent("_")},
		Tok: token.ASSIGN,
		Rhs: []ast.Expr{ast.NewIdent(identName)},
	}
	return appendStmt(nodepath, stmt)
}

func fixImportedNotUsed(nodepath []ast.Node, pkgPath string) bool {
	for _, node := range nodepath {
		if f, ok := node.(*ast.File); ok {
			for _, imp := range f.Imports {
				if imp.Path.Value == pkgPath {
					// make this import spec anonymous one
					imp.Name = ast.NewIdent("_")
					return true
				}
			}
		}
	}
	return false
}

func fixNoNewVariables(nodepath []ast.Node) bool {
	for _, node := range nodepath {
		switch node := node.(type) {
		case *ast.AssignStmt:
			if node.Tok == token.DEFINE {
				node.Tok = token.ASSIGN
				return true
			}

		case *ast.RangeStmt:
			if node.Tok == token.DEFINE {
				node.Tok = token.ASSIGN
				return true
			}
		}
	}
	return false
}

type errorList []error

func (errs errorList) any() error {
	if len(errs) == 0 {
		return nil
	}

	return errs
}

func (errs errorList) Error() string {
	s := []string{fmt.Sprintf("%d error(s):", len(errs))}
	for _, e := range errs {
		s = append(s, fmt.Sprintf("- %s", e))
	}
	return strings.Join(s, "\n")
}

func appendStmt(nodepath []ast.Node, stmt ast.Stmt) bool {
	for _, node := range nodepath {
		switch node := node.(type) {
		case *ast.BlockStmt:
			if node.List == nil {
				node.List = []ast.Stmt{}
			}
			node.List = append(node.List, stmt)

		case *ast.CaseClause:
			if node.Body == nil {
				node.Body = []ast.Stmt{}
			}
			node.Body = append(node.Body, stmt)

		case *ast.CommClause:
			if node.Body == nil {
				node.Body = []ast.Stmt{}
			}
			node.Body = append(node.Body, stmt)

		case *ast.RangeStmt:
			if node.Body == nil {
				node.Body = &ast.BlockStmt{}
			}
			if node.Body.List == nil {
				node.Body.List = []ast.Stmt{}
			}
			node.Body.List = append(node.Body.List, stmt)

		default:
			continue
		}

		return true
	}

	return false
}

func removeChildNode(child, parent ast.Node) bool {
	switch parent := parent.(type) {
	case *ast.BlockStmt:
		removeFromStmtList(child, parent.List)
		return true
	case *ast.CaseClause:
		removeFromStmtList(child, parent.Body)
		return true
	case *ast.CommClause:
		removeFromStmtList(child, parent.Body)
		return true
	case *ast.RangeStmt:
		removeFromStmtList(child, parent.Body.List)
		return true
	}

	return false
}

// removeFromStmtList remove node from slice of statements list. This function
// modifies list in-place and pads rest of the slice with ast.EmptyStmt.
func removeFromStmtList(node ast.Node, list []ast.Stmt) bool {
	for i, s := range list {
		if s == node {
			for ; i < len(list)-1; i++ {
				list[i] = list[i+1]
			}
			list[len(list)-1] = &ast.EmptyStmt{}
			return true
		}
	}

	return false
}

func findFile(files []*ast.File, pos token.Pos) *ast.File {
	for _, f := range files {
		if f.Pos() <= pos && pos < f.End() {
			return f
		}
	}

	return nil
}

func isIdent(node ast.Node) bool {
	if node == nil {
		return false
	}

	_, ok := node.(*ast.Ident)
	return ok
}

func isBlankIdent(node ast.Node) bool {
	if node == nil {
		return false
	}

	ident, ok := node.(*ast.Ident)
	return ok && ident != nil && ident.Name == "_"
}

type ErrCouldNotLocate struct {
	Err  types.Error
	Fset *token.FileSet
}

func (e ErrCouldNotLocate) Error() string {
	return fmt.Sprintf("cannot find file for error %q: %s (%d)", e.Err.Error(), e.Fset.Position(e.Err.Pos), e.Err.Pos)
}
<commit_msg>introduce ErrorList<commit_after>// Package quickfix provides functions for fixing Go ASTs
// that are well typed but "go build" refuses to build.
package quickfix

import (
	"fmt"
	"regexp"
	"strings"

	"go/ast"
	"go/token"

	"golang.org/x/tools/go/ast/astutil"
	_ "golang.org/x/tools/go/gcimporter"
	"golang.org/x/tools/go/types"
)

var (
	declaredNotUsed        = regexp.MustCompile(`^([a-zA-Z0-9_]+) declared but not used$`)
	importedNotUsed        = regexp.MustCompile(`^(".+") imported but not used$`)
	noNewVariablesOnDefine = "no new variables on left side of :="
)

// QuickFix rewrites AST files of same package so that they pass go build.
// For example:
//   v declared but not used             -> append `_ = v`
//   "p" imported but not used           -> rewrite to `import _ "p"`
//   no new variables on left side of := -> rewrite `:=` to `=`
//
// TODO implement hardMode, which removes errorneous code rather than adding
func QuickFix(fset *token.FileSet, files []*ast.File) (err error) {
	const maxTries = 10
	for i := 0; i < maxTries; i++ {
		var foundError bool
		foundError, err = quickFix1(fset, files)
		if !foundError {
			return nil
		}
	}

	return
}

type tracedVisitor struct {
	path  []ast.Node
	visit func(ast.Node, []ast.Node) bool
}

func (v tracedVisitor) Visit(node ast.Node) ast.Visitor {
	if v.visit(node, v.path) {
		return tracedVisitor{
			path:  append([]ast.Node{node}, v.path...),
			visit: v.visit,
		}
	}

	return nil
}

func traverseAST(node ast.Node, visit func(ast.Node, []ast.Node) bool) {
	v := tracedVisitor{
		visit: visit,
	}
	ast.Walk(v, node)
}

// pkgsWithSideEffect are set of packages which are known to provide APIs by
// blank identifier import (import _ "p").
var pkgsWithSideEffect = map[string]bool{}

func init() {
	for _, path := range []string{
		"expvar",
		"image/gif",
		"image/jpeg",
		"image/png",
		"net/http/pprof",
		"unsafe",
		"golang.org/x/image/bmp",
		"golang.org/x/image/tiff",
		"golang.org/x/image/vp8",
		"golang.org/x/image/vp81",
		"golang.org/x/image/webp",
		"golang.org/x/tools/go/gcimporter",
	} {
		pkgsWithSideEffect[`"`+path+`"`] = true
	}
}

// RevertQuickFix reverts possible quickfixes introduced by QuickFix.
// This may result to non-buildable source, and cannot reproduce the original
// code before first QuickFix.
// For example:
//   `_ = v`        -> removed
//   `import _ "p"` -> rewritten to `import "p"`
func RevertQuickFix(fset *token.FileSet, files []*ast.File) (err error) {
	nodeToRemove := map[ast.Node]bool{}

	for _, f := range files {
		ast.Inspect(f, func(node ast.Node) bool {
			if assign, ok := node.(*ast.AssignStmt); ok {
				if len(assign.Lhs) == 1 && isBlankIdent(assign.Lhs[0]) &&
					len(assign.Rhs) == 1 && isIdent(assign.Rhs[0]) {
					// The statement is `_ = v`
					nodeToRemove[node] = true
				}

				return false
			} else if imp, ok := node.(*ast.ImportSpec); ok {
				if isBlankIdent(imp.Name) && !pkgsWithSideEffect[imp.Path.Value] {
					// The spec is `import _ "p"` and p is not a package that
					// provides "side effects"
					imp.Name = nil
				}

				return false
			}

			return true
		})

		for len(nodeToRemove) > 0 {
			traverseAST(f, func(node ast.Node, nodepath []ast.Node) bool {
				if nodeToRemove[node] {
					parent := nodepath[0]
					if removeChildNode(node, parent) == false {
						err = fmt.Errorf(
							"BUG: could not remove node: %s (in: %s)",
							fset.Position(node.Pos()),
							fset.Position(parent.Pos()),
						)
					}
					delete(nodeToRemove, node)
					return false
				}

				return true
			})
		}
	}

	return
}

func quickFix1(fset *token.FileSet, files []*ast.File) (bool, error) {
	errs := []error{}
	config := &types.Config{
		Error: func(err error) {
			errs = append(errs, err)
		},
	}

	_, err := config.Check("_quickfix", fset, files, nil)
	if err == nil {
		return false, nil
	}

	// apply fixes on AST later so that we won't break funcs that inspect AST by positions
	fixes := map[error]func() bool{}
	unhandled := ErrorList{}

	foundError := len(errs) > 0

	for _, err := range errs {
		err, ok := err.(types.Error)
		if !ok {
			unhandled = append(unhandled, err)
			continue
		}

		f := findFile(files, err.Pos)
		if f == nil {
			e := ErrCouldNotLocate{
				Err:  err,
				Fset: fset,
			}
			unhandled = append(unhandled, e)
			continue
		}

		nodepath, _ := astutil.PathEnclosingInterval(f, err.Pos, err.Pos)

		var fix func() bool

		// - "%s declared but not used"
		// - "%q imported but not used"
		// - "label %s declared but not used" TODO
		// - "no new variables on left side of :="
		if m := declaredNotUsed.FindStringSubmatch(err.Msg); m != nil {
			identName := m[1]
			fix = func() bool {
				return fixDeclaredNotUsed(nodepath, identName)
			}
		} else if m := importedNotUsed.FindStringSubmatch(err.Msg); m != nil {
			pkgPath := m[1] // quoted string, but it's okay because this will be compared to ast.BasicLit.Value.
			fix = func() bool {
				return fixImportedNotUsed(nodepath, pkgPath)
			}
		} else if err.Msg == noNewVariablesOnDefine {
			fix = func() bool {
				return fixNoNewVariables(nodepath)
			}
		} else {
			unhandled = append(unhandled, err)
		}

		if fix != nil {
			fixes[err] = fix
		}
	}

	for err, fix := range fixes {
		if fix() == false {
			unhandled = append(unhandled, err)
		}
	}

	return foundError, unhandled.any()
}

func fixDeclaredNotUsed(nodepath []ast.Node, identName string) bool {
	// insert "_ = x" to supress "declared but not used" error
	stmt := &ast.AssignStmt{
		Lhs: []ast.Expr{ast.NewIdent("_")},
		Tok: token.ASSIGN,
		Rhs: []ast.Expr{ast.NewIdent(identName)},
	}
	return appendStmt(nodepath, stmt)
}

func fixImportedNotUsed(nodepath []ast.Node, pkgPath string) bool {
	for _, node := range nodepath {
		if f, ok := node.(*ast.File); ok {
			for _, imp := range f.Imports {
				if imp.Path.Value == pkgPath {
					// make this import spec anonymous one
					imp.Name = ast.NewIdent("_")
					return true
				}
			}
		}
	}
	return false
}

func fixNoNewVariables(nodepath []ast.Node) bool {
	for _, node := range nodepath {
		switch node := node.(type) {
		case *ast.AssignStmt:
			if node.Tok == token.DEFINE {
				node.Tok = token.ASSIGN
				return true
			}

		case *ast.RangeStmt:
			if node.Tok == token.DEFINE {
				node.Tok = token.ASSIGN
				return true
			}
		}
	}
	return false
}

type ErrorList []error

func (errs ErrorList) any() error {
	if len(errs) == 0 {
		return nil
	}

	return errs
}

func (errs ErrorList) Error() string {
	s := []string{fmt.Sprintf("%d error(s):", len(errs))}
	for _, e := range errs {
		s = append(s, fmt.Sprintf("- %s", e))
	}
	return strings.Join(s, "\n")
}

func appendStmt(nodepath []ast.Node, stmt ast.Stmt) bool {
	for _, node := range nodepath {
		switch node := node.(type) {
		case *ast.BlockStmt:
			if node.List == nil {
				node.List = []ast.Stmt{}
			}
			node.List = append(node.List, stmt)

		case *ast.CaseClause:
			if node.Body == nil {
				node.Body = []ast.Stmt{}
			}
			node.Body = append(node.Body, stmt)

		case *ast.CommClause:
			if node.Body == nil {
				node.Body = []ast.Stmt{}
			}
			node.Body = append(node.Body, stmt)

		case *ast.RangeStmt:
			if node.Body == nil {
				node.Body = &ast.BlockStmt{}
			}
			if node.Body.List == nil {
				node.Body.List = []ast.Stmt{}
			}
			node.Body.List = append(node.Body.List, stmt)

		default:
			continue
		}

		return true
	}

	return false
}

func removeChildNode(child, parent ast.Node) bool {
	switch parent := parent.(type) {
	case *ast.BlockStmt:
		removeFromStmtList(child, parent.List)
		return true
	case *ast.CaseClause:
		removeFromStmtList(child, parent.Body)
		return true
	case *ast.CommClause:
		removeFromStmtList(child, parent.Body)
		return true
	case *ast.RangeStmt:
		removeFromStmtList(child, parent.Body.List)
		return true
	}

	return false
}

// removeFromStmtList remove node from slice of statements list. This function
// modifies list in-place and pads rest of the slice with ast.EmptyStmt.
func removeFromStmtList(node ast.Node, list []ast.Stmt) bool {
	for i, s := range list {
		if s == node {
			for ; i < len(list)-1; i++ {
				list[i] = list[i+1]
			}
			list[len(list)-1] = &ast.EmptyStmt{}
			return true
		}
	}

	return false
}

func findFile(files []*ast.File, pos token.Pos) *ast.File {
	for _, f := range files {
		if f.Pos() <= pos && pos < f.End() {
			return f
		}
	}

	return nil
}

func isIdent(node ast.Node) bool {
	if node == nil {
		return false
	}

	_, ok := node.(*ast.Ident)
	return ok
}

func isBlankIdent(node ast.Node) bool {
	if node == nil {
		return false
	}

	ident, ok := node.(*ast.Ident)
	return ok && ident != nil && ident.Name == "_"
}

type ErrCouldNotLocate struct {
	Err  types.Error
	Fset *token.FileSet
}

func (e ErrCouldNotLocate) Error() string {
	return fmt.Sprintf("cannot find file for error %q: %s (%d)", e.Err.Error(), e.Fset.Position(e.Err.Pos), e.Err.Pos)
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

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

func TestAccAWSAPIGatewayDocumentationVersion_basic(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_basic_%s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAPIGatewayDocumentationVersion_allFields(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_method_%s", rString)
	stageName := fmt.Sprintf("tf-acc-test_stage_%s", rString)
	description := fmt.Sprintf("Tf Acc Test description %s", rString)
	uDescription := fmt.Sprintf("Tf Acc Test description updated %s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, description),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttr(resourceName, "description", description),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, uDescription),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttr(resourceName, "description", uDescription),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
		},
	})
}

func TestAccAWSAPIGatewayDocumentationVersion_disappears(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_basic_%s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsApiGatewayDocumentationVersion(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSAPIGatewayDocumentationVersionExists(n string, res *apigateway.DocumentationVersion) 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 Documentation Version ID is set")
		}

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

		apiId, version, err := decodeApiGatewayDocumentationVersionId(rs.Primary.ID)
		if err != nil {
			return err
		}

		req := &apigateway.GetDocumentationVersionInput{
			DocumentationVersion: aws.String(version),
			RestApiId:            aws.String(apiId),
		}
		docVersion, err := conn.GetDocumentationVersion(req)
		if err != nil {
			return err
		}

		*res = *docVersion

		return nil
	}
}

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

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

		version, apiId, err := decodeApiGatewayDocumentationVersionId(rs.Primary.ID)
		if err != nil {
			return err
		}

		req := &apigateway.GetDocumentationVersionInput{
			DocumentationVersion: aws.String(version),
			RestApiId:            aws.String(apiId),
		}
		_, err = conn.GetDocumentationVersion(req)
		if err != nil {
			if isAWSErr(err, apigateway.ErrCodeNotFoundException, "") {
				return nil
			}
			return err
		}

		return fmt.Errorf("API Gateway Documentation Version %q still exists.", rs.Primary.ID)
	}
	return nil
}

func testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName string) string {
	return fmt.Sprintf(`
resource "aws_api_gateway_documentation_version" "test" {
  version     = "%s"
  rest_api_id = aws_api_gateway_rest_api.test.id
  depends_on  = [aws_api_gateway_documentation_part.test]
}

resource "aws_api_gateway_documentation_part" "test" {
  location {
    type = "API"
  }

  properties  = "{\"description\":\"Terraform Acceptance Test\"}"
  rest_api_id = aws_api_gateway_rest_api.test.id
}

resource "aws_api_gateway_rest_api" "test" {
  name = "%s"
}
`, version, apiName)
}

func testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, description string) string {
	return fmt.Sprintf(`
resource "aws_api_gateway_documentation_version" "test" {
  version     = "%s"
  rest_api_id = aws_api_gateway_rest_api.test.id
  description = "%s"
  depends_on  = [aws_api_gateway_documentation_part.test]
}

resource "aws_api_gateway_documentation_part" "test" {
  location {
    type = "API"
  }

  properties  = "{\"description\":\"Terraform Acceptance Test\"}"
  rest_api_id = aws_api_gateway_rest_api.test.id
}

resource "aws_api_gateway_resource" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  parent_id   = aws_api_gateway_rest_api.test.root_resource_id
  path_part   = "test"
}

resource "aws_api_gateway_method" "test" {
  rest_api_id   = aws_api_gateway_rest_api.test.id
  resource_id   = aws_api_gateway_resource.test.id
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_method_response" "error" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_method.test.http_method
  status_code = "400"
}

resource "aws_api_gateway_integration" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_method.test.http_method

  type                    = "HTTP"
  uri                     = "https://www.google.co.uk"
  integration_http_method = "GET"
}

resource "aws_api_gateway_integration_response" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_integration.test.http_method
  status_code = aws_api_gateway_method_response.error.status_code
}

resource "aws_api_gateway_deployment" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  stage_name  = "first"
  depends_on  = [aws_api_gateway_integration_response.test]
}

resource "aws_api_gateway_stage" "test" {
  stage_name            = "%s"
  rest_api_id           = aws_api_gateway_rest_api.test.id
  deployment_id         = aws_api_gateway_deployment.test.id
  documentation_version = aws_api_gateway_documentation_version.test.version
}

resource "aws_api_gateway_rest_api" "test" {
  name = "%s"
}
`, version, description, stageName, apiName)
}
<commit_msg>tests/provider: Add precheck for ep config type edge (API Gateway Doc Version)<commit_after>package aws

import (
	"fmt"
	"testing"

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

func TestAccAWSAPIGatewayDocumentationVersion_basic(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_basic_%s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAPIGatewayDocumentationVersion_allFields(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_method_%s", rString)
	stageName := fmt.Sprintf("tf-acc-test_stage_%s", rString)
	description := fmt.Sprintf("Tf Acc Test description %s", rString)
	uDescription := fmt.Sprintf("Tf Acc Test description updated %s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, description),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttr(resourceName, "description", description),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, uDescription),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					resource.TestCheckResourceAttr(resourceName, "version", version),
					resource.TestCheckResourceAttr(resourceName, "description", uDescription),
					resource.TestCheckResourceAttrSet(resourceName, "rest_api_id"),
				),
			},
		},
	})
}

func TestAccAWSAPIGatewayDocumentationVersion_disappears(t *testing.T) {
	var conf apigateway.DocumentationVersion

	rString := acctest.RandString(8)
	version := fmt.Sprintf("tf-acc-test_version_%s", rString)
	apiName := fmt.Sprintf("tf-acc-test_api_doc_version_basic_%s", rString)

	resourceName := "aws_api_gateway_documentation_version.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAPIGatewayDocumentationVersionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAPIGatewayDocumentationVersionExists(resourceName, &conf),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsApiGatewayDocumentationVersion(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSAPIGatewayDocumentationVersionExists(n string, res *apigateway.DocumentationVersion) 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 Documentation Version ID is set")
		}

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

		apiId, version, err := decodeApiGatewayDocumentationVersionId(rs.Primary.ID)
		if err != nil {
			return err
		}

		req := &apigateway.GetDocumentationVersionInput{
			DocumentationVersion: aws.String(version),
			RestApiId:            aws.String(apiId),
		}
		docVersion, err := conn.GetDocumentationVersion(req)
		if err != nil {
			return err
		}

		*res = *docVersion

		return nil
	}
}

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

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

		version, apiId, err := decodeApiGatewayDocumentationVersionId(rs.Primary.ID)
		if err != nil {
			return err
		}

		req := &apigateway.GetDocumentationVersionInput{
			DocumentationVersion: aws.String(version),
			RestApiId:            aws.String(apiId),
		}
		_, err = conn.GetDocumentationVersion(req)
		if err != nil {
			if isAWSErr(err, apigateway.ErrCodeNotFoundException, "") {
				return nil
			}
			return err
		}

		return fmt.Errorf("API Gateway Documentation Version %q still exists.", rs.Primary.ID)
	}
	return nil
}

func testAccAWSAPIGatewayDocumentationVersionBasicConfig(version, apiName string) string {
	return fmt.Sprintf(`
resource "aws_api_gateway_documentation_version" "test" {
  version     = "%s"
  rest_api_id = aws_api_gateway_rest_api.test.id
  depends_on  = [aws_api_gateway_documentation_part.test]
}

resource "aws_api_gateway_documentation_part" "test" {
  location {
    type = "API"
  }

  properties  = "{\"description\":\"Terraform Acceptance Test\"}"
  rest_api_id = aws_api_gateway_rest_api.test.id
}

resource "aws_api_gateway_rest_api" "test" {
  name = "%s"
}
`, version, apiName)
}

func testAccAWSAPIGatewayDocumentationVersionAllFieldsConfig(version, apiName, stageName, description string) string {
	return fmt.Sprintf(`
resource "aws_api_gateway_documentation_version" "test" {
  version     = "%s"
  rest_api_id = aws_api_gateway_rest_api.test.id
  description = "%s"
  depends_on  = [aws_api_gateway_documentation_part.test]
}

resource "aws_api_gateway_documentation_part" "test" {
  location {
    type = "API"
  }

  properties  = "{\"description\":\"Terraform Acceptance Test\"}"
  rest_api_id = aws_api_gateway_rest_api.test.id
}

resource "aws_api_gateway_resource" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  parent_id   = aws_api_gateway_rest_api.test.root_resource_id
  path_part   = "test"
}

resource "aws_api_gateway_method" "test" {
  rest_api_id   = aws_api_gateway_rest_api.test.id
  resource_id   = aws_api_gateway_resource.test.id
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_method_response" "error" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_method.test.http_method
  status_code = "400"
}

resource "aws_api_gateway_integration" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_method.test.http_method

  type                    = "HTTP"
  uri                     = "https://www.google.co.uk"
  integration_http_method = "GET"
}

resource "aws_api_gateway_integration_response" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  resource_id = aws_api_gateway_resource.test.id
  http_method = aws_api_gateway_integration.test.http_method
  status_code = aws_api_gateway_method_response.error.status_code
}

resource "aws_api_gateway_deployment" "test" {
  rest_api_id = aws_api_gateway_rest_api.test.id
  stage_name  = "first"
  depends_on  = [aws_api_gateway_integration_response.test]
}

resource "aws_api_gateway_stage" "test" {
  stage_name            = "%s"
  rest_api_id           = aws_api_gateway_rest_api.test.id
  deployment_id         = aws_api_gateway_deployment.test.id
  documentation_version = aws_api_gateway_documentation_version.test.version
}

resource "aws_api_gateway_rest_api" "test" {
  name = "%s"
}
`, version, description, stageName, apiName)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/headzoo/surf"
	"log"
	"os"
	"strings"
	"time"
)

var (
	browse           = surf.NewBrowser()
	maxTries         = 60
	tries            = 0
	registrationHost = "https://account.jetbrains.com"
)

func main() {
	serverUrl := os.Args[1]
	username := os.Args[2]
	password := os.Args[3]
	serverName := os.Args[4]

	err := openServerSite(serverUrl)
	if err != nil {
		panic(err)
	}
	login(username, password)
	customer, serverUid := parseRegistrationData(serverName)
	register(customer, serverUrl, serverUid)
}

func openServerSite(serverUrl string) error {
	var retryOrFail = func(
		serverUrl string,
		err error,
	) error {
		if tries <= maxTries {
			time.Sleep(2 * time.Second)
			tries++
			return openServerSite(serverUrl)
		} else {
			return err
		}
	}

	err := browse.Open(serverUrl)
	if err != nil {
		return retryOrFail(serverUrl, err)
	}
	err = browse.Click(".btn")
	if err != nil {
		return retryOrFail(serverUrl, err)
	}
	return nil
}

func login(
	username string,
	password string,
) {
	login, err := browse.Form("form[action='/authorize']")
	if err != nil {
		panic(err)
	}
	login.Input("username", username)
	login.Input("password", password)
	err = login.Submit()
	if err != nil {
		panic(err)
	}
	if strings.Compare(browse.Title(), "JetBrains Account") != 0 {
		panic("Could not log in - Title:" + browse.Title() + " Body:" + browse.Body())
	}
}

func parseRegistrationData(
	serverName string,
) (
	string,
	string,
) {
	var (
		customer  string
		serverUid string
	)

	browse.Find("input[name=customer]").Each(func(_ int, f *goquery.Selection) {
		customer, _ = f.Attr("value")
	})
	browse.Find("label").Each(func(_ int, l *goquery.Selection) {
		if strings.Contains(l.Text(), serverName) {
			l.Find("input").Each(func(_ int, f *goquery.Selection) {
				serverUid, _ = f.Attr("value")
			})
		}
	})
	if customer == "" || serverUid == "" {
		panic("Could not get registration data")
	}
	return customer, serverUid
}

func register(
	customer string,
	url string,
	serverUid string,
) {
	log.Printf("Registering - url(%s),serverUid(%s),customer(%s)", url, serverUid, customer)
	registrationUrl := fmt.Sprintf("%s/server-registration?customer=%s&url=%s&server_uid=%s", registrationHost, customer, url, serverUid)
	err := browse.Open(registrationUrl)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Add workaround for nonfunctional redirect during login<commit_after>package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/headzoo/surf"
	"log"
	"os"
	"strings"
	"time"
)

var (
	browse           = surf.NewBrowser()
	maxTries         = 60
	tries            = 0
	registrationHost = "https://account.jetbrains.com"
)

func main() {
	serverUrl := os.Args[1]
	username := os.Args[2]
	password := os.Args[3]
	serverName := os.Args[4]

	err := openServerSite(serverUrl)
	if err != nil {
		panic(err)
	}
	login(username, password, serverUrl)
	customer, serverUid := parseRegistrationData(serverName)
	register(customer, serverUrl, serverUid)
}

func openServerSite(serverUrl string) error {
	var retryOrFail = func(
		serverUrl string,
		err error,
	) error {
		if tries <= maxTries {
			time.Sleep(2 * time.Second)
			tries++
			return openServerSite(serverUrl)
		} else {
			return err
		}
	}

	err := browse.Open(serverUrl)
	if err != nil {
		return retryOrFail(serverUrl, err)
	}
	err = browse.Click(".btn")
	if err != nil {
		return retryOrFail(serverUrl, err)
	}
	return nil
}

func login(
	username string,
	password string,
	serverUrl string,
) {
	login, err := browse.Form("form[action='/authorize']")
	if err != nil {
		panic(err)
	}
	login.Input("username", username)
	login.Input("password", password)
	err = login.Submit()
	if err != nil {
		panic(err)
	}
	if redirectDoesNotWork() {
		err = browse.Open("https://account.jetbrains.com/server-registration?url=" + serverUrl)
		if err != nil {
			panic(err)
		}
	}
	if stillNotOnAccountPage() {
		panic("Could not log in - Title:" + browse.Title() + " Body:" + browse.Body())
	}

}

func redirectDoesNotWork() bool {
	return isOnAccountPage()
}

func stillNotOnAccountPage() bool {
	return isOnAccountPage()
}

func isOnAccountPage() bool {
	return strings.Compare(browse.Title(), "JetBrains Account") != 0
}

func parseRegistrationData(
	serverName string,
) (
	string,
	string,
) {
	var (
		customer  string
		serverUid string
	)

	browse.Find("input[name=customer]").Each(func(_ int, f *goquery.Selection) {
		customer, _ = f.Attr("value")
	})
	browse.Find("label").Each(func(_ int, l *goquery.Selection) {
		if strings.Contains(l.Text(), serverName) {
			l.Find("input").Each(func(_ int, f *goquery.Selection) {
				serverUid, _ = f.Attr("value")
			})
		}
	})
	if customer == "" || serverUid == "" {
		panic("Could not get registration data")
	}
	return customer, serverUid
}

func register(
	customer string,
	url string,
	serverUid string,
) {
	log.Printf("Registering - url(%s),serverUid(%s),customer(%s)", url, serverUid, customer)
	registrationUrl := fmt.Sprintf("%s/server-registration?customer=%s&url=%s&server_uid=%s", registrationHost, customer, url, serverUid)
	err := browse.Open(registrationUrl)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package air

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
)

// renderer is a renderer for rendering HTML templates.
type renderer struct {
	a        *Air
	template *template.Template
	watcher  *fsnotify.Watcher
	once     *sync.Once
}

// newRenderer returns a new instance of the `renderer` with the a.
func newRenderer(a *Air) *renderer {
	r := &renderer{
		a:    a,
		once: &sync.Once{},
	}

	var err error
	if r.watcher, err = fsnotify.NewWatcher(); err != nil {
		panic(fmt.Errorf(
			"air: failed to build renderer watcher: %v",
			err,
		))
	}

	go func() {
		for {
			select {
			case e := <-r.watcher.Events:
				a.DEBUG(
					"air: template file event occurs",
					map[string]interface{}{
						"file":  e.Name,
						"event": e.Op.String(),
					},
				)
				r.once = &sync.Once{}
			case err := <-r.watcher.Errors:
				a.ERROR(
					"air: renderer watcher error",
					map[string]interface{}{
						"error": err.Error(),
					},
				)
			}
		}
	}()

	return r
}

// render renders the v into the w for the HTML template name.
func (r *renderer) render(
	w io.Writer,
	name string,
	v interface{},
	locstr func(string) string,
) error {
	r.once.Do(func() {
		tr, err := filepath.Abs(r.a.TemplateRoot)
		if err != nil {
			r.a.ERROR(
				"air: failed to get absolute representation "+
					"of template root",
				map[string]interface{}{
					"error": err.Error(),
				},
			)

			return
		}

		r.template = template.
			New("template").
			Delims(r.a.TemplateLeftDelim, r.a.TemplateRightDelim).
			Funcs(template.FuncMap{
				"locstr": func(key string) string {
					return key
				},
			}).
			Funcs(r.a.TemplateFuncMap)
		if err := filepath.Walk(
			tr,
			func(p string, fi os.FileInfo, err error) error {
				if fi == nil || !fi.IsDir() {
					return err
				}

				for _, e := range r.a.TemplateExts {
					fns, err := filepath.Glob(
						filepath.Join(p, "*"+e),
					)
					if err != nil {
						return err
					}

					for _, fn := range fns {
						b, err := ioutil.ReadFile(fn)
						if err != nil {
							return err
						}

						if _, err := r.template.New(
							filepath.ToSlash(
								fn[len(tr)+1:],
							),
						).Parse(string(b)); err != nil {
							return err
						}
					}
				}

				return r.watcher.Add(p)
			},
		); err != nil {
			r.a.ERROR(
				"air: failed to walk template files",
				map[string]interface{}{
					"error": err.Error(),
				},
			)
		}
	})

	t := r.template.Lookup(name)
	if t == nil {
		fmt.Errorf("html/template: %q is undefined", name)
	}

	if r.a.I18nEnabled {
		t, err := t.Clone()
		if err != nil {
			return err
		}

		return t.Funcs(template.FuncMap{
			"locstr": locstr,
		}).Execute(w, v)
	}

	return t.Execute(w, v)
}

// strlen returns the number of characters in the s.
func strlen(s string) int {
	return len([]rune(s))
}

// substr returns the substring consisting of the characters of the s starting
// at the index i and continuing up to, but not including, the character at the
// index j.
func substr(s string, i, j int) string {
	return string([]rune(s)[i:j])
}

// timefmt returns a textual representation of the t formatted for the layout.
func timefmt(t time.Time, layout string) string {
	return t.Format(layout)
}
<commit_msg>fix: correct `renderer#render()`<commit_after>package air

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
)

// renderer is a renderer for rendering HTML templates.
type renderer struct {
	a        *Air
	template *template.Template
	watcher  *fsnotify.Watcher
	once     *sync.Once
}

// newRenderer returns a new instance of the `renderer` with the a.
func newRenderer(a *Air) *renderer {
	r := &renderer{
		a:    a,
		once: &sync.Once{},
	}

	var err error
	if r.watcher, err = fsnotify.NewWatcher(); err != nil {
		panic(fmt.Errorf(
			"air: failed to build renderer watcher: %v",
			err,
		))
	}

	go func() {
		for {
			select {
			case e := <-r.watcher.Events:
				a.DEBUG(
					"air: template file event occurs",
					map[string]interface{}{
						"file":  e.Name,
						"event": e.Op.String(),
					},
				)
				r.once = &sync.Once{}
			case err := <-r.watcher.Errors:
				a.ERROR(
					"air: renderer watcher error",
					map[string]interface{}{
						"error": err.Error(),
					},
				)
			}
		}
	}()

	return r
}

// render renders the v into the w for the HTML template name.
func (r *renderer) render(
	w io.Writer,
	name string,
	v interface{},
	locstr func(string) string,
) error {
	r.once.Do(func() {
		tr, err := filepath.Abs(r.a.TemplateRoot)
		if err != nil {
			r.a.ERROR(
				"air: failed to get absolute representation "+
					"of template root",
				map[string]interface{}{
					"error": err.Error(),
				},
			)

			return
		}

		r.template = template.
			New("template").
			Delims(r.a.TemplateLeftDelim, r.a.TemplateRightDelim).
			Funcs(template.FuncMap{
				"locstr": func(key string) string {
					return key
				},
			}).
			Funcs(r.a.TemplateFuncMap)
		if err := filepath.Walk(
			tr,
			func(p string, fi os.FileInfo, err error) error {
				if fi == nil || !fi.IsDir() {
					return err
				}

				for _, e := range r.a.TemplateExts {
					fns, err := filepath.Glob(
						filepath.Join(p, "*"+e),
					)
					if err != nil {
						return err
					}

					for _, fn := range fns {
						b, err := ioutil.ReadFile(fn)
						if err != nil {
							return err
						}

						if _, err := r.template.New(
							filepath.ToSlash(
								fn[len(tr)+1:],
							),
						).Parse(string(b)); err != nil {
							return err
						}
					}
				}

				return r.watcher.Add(p)
			},
		); err != nil {
			r.a.ERROR(
				"air: failed to walk template files",
				map[string]interface{}{
					"error": err.Error(),
				},
			)
		}
	})

	t := r.template.Lookup(name)
	if t == nil {
		return fmt.Errorf("html/template: %q is undefined", name)
	}

	if r.a.I18nEnabled {
		t, err := t.Clone()
		if err != nil {
			return err
		}

		return t.Funcs(template.FuncMap{
			"locstr": locstr,
		}).Execute(w, v)
	}

	return t.Execute(w, v)
}

// strlen returns the number of characters in the s.
func strlen(s string) int {
	return len([]rune(s))
}

// substr returns the substring consisting of the characters of the s starting
// at the index i and continuing up to, but not including, the character at the
// index j.
func substr(s string, i, j int) string {
	return string([]rune(s)[i:j])
}

// timefmt returns a textual representation of the t formatted for the layout.
func timefmt(t time.Time, layout string) string {
	return t.Format(layout)
}
<|endoftext|>


<commit_before>package just

import (
	"encoding/json"
	"encoding/xml"
	"net/http"
)

type StreamHandler func(w http.ResponseWriter, r *http.Request)

type IResponse interface {
	GetData() []byte
	GetStatus() int
	GetHeaders() map[string]string
	GetStreamHandler() (StreamHandler, bool)
}

type Response struct {
	Status  int
	Bytes   []byte
	Headers map[string]string
	Stream  StreamHandler
}

func (r *Response) GetStreamHandler() (StreamHandler, bool) {
	if r.Stream != nil && (r.Bytes == nil || len(r.Bytes) < 1) {
		return r.Stream, true
	}
	return nil, false
}

func (r *Response) GetStatus() int {
	return r.Status
}

func (r *Response) GetData() []byte {
	return r.Bytes
}

func (r *Response) GetHeaders() map[string]string {
	return r.Headers
}

// StreamResponse создание потока ответа
func StreamResponse(handler StreamHandler) IResponse {
	return &Response{Bytes: nil, Status: -1, Headers: nil, Stream: handler}
}

// JsonResponse создание ответа в формате JSON
func JsonResponse(status int, v interface{}) IResponse {
	b, err := json.Marshal(v)
	if err != nil {
		return &Response{
			Bytes:   []byte(err.Error()),
			Status:  500,
			Headers: map[string]string{"Content-Type": "plain/text"},
		}
	}
	return &Response{
		Bytes:   b,
		Status:  status,
		Headers: map[string]string{"Content-Type": "application/json"},
	}
}

// RedirectResponse создание жесткого редиректа
func RedirectResponse(status int, location string) IResponse {
	if (status < 300 || status > 308) && status != 201 {
		status = 301
	}
	return &Response{Bytes: nil, Status: status, Headers: map[string]string{"_StrongRedirect": location}}
}

// XmlResponse создание ответа в формате xml
func XmlResponse(status int, v interface{}) IResponse {
	b, err := xml.Marshal(v)
	if err != nil {
		return &Response{
			Bytes:   []byte(err.Error()),
			Status:  500,
			Headers: map[string]string{"Content-Type": "plain/text"},
		}
	}
	return &Response{
		Bytes:   b,
		Status:  status,
		Headers: map[string]string{"Content-Type": "application/xml"},
	}
}

// XmlResponse создание ответа в виде локального файла
func FileResponse(filePath string) IResponse {
	return &Response{Bytes: nil, Status: -1, Headers: map[string]string{"_FilePath": filePath}}
}
<commit_msg>- Fixes - Add support http.HandlerFunc<commit_after>package just

import (
	"encoding/json"
	"encoding/xml"
	"net/http"
)

type IResponse interface {
	GetData() []byte
	GetStatus() int
	GetHeaders() map[string]string
	GetStreamHandler() (http.HandlerFunc, bool)
}

type Response struct {
	Status  int
	Bytes   []byte
	Headers map[string]string
	Stream  http.HandlerFunc
}

func (r *Response) GetStreamHandler() (http.HandlerFunc, bool) {
	if r.Stream != nil && (r.Bytes == nil || len(r.Bytes) < 1) {
		return r.Stream, true
	}
	return nil, false
}

func (r *Response) GetStatus() int {
	return r.Status
}

func (r *Response) GetData() []byte {
	return r.Bytes
}

func (r *Response) GetHeaders() map[string]string {
	return r.Headers
}

// StreamResponse создание потока ответа
func StreamResponse(handler http.HandlerFunc) IResponse {
	return &Response{Bytes: nil, Status: -1, Headers: nil, Stream: handler}
}

// JsonResponse создание ответа в формате JSON
func JsonResponse(status int, v interface{}) IResponse {
	b, err := json.Marshal(v)
	if err != nil {
		return &Response{
			Bytes:   []byte(err.Error()),
			Status:  500,
			Headers: map[string]string{"Content-Type": "plain/text"},
		}
	}
	return &Response{
		Bytes:   b,
		Status:  status,
		Headers: map[string]string{"Content-Type": "application/json"},
	}
}

// RedirectResponse создание жесткого редиректа
func RedirectResponse(status int, location string) IResponse {
	if (status < 300 || status > 308) && status != 201 {
		status = 301
	}
	return &Response{Bytes: nil, Status: status, Headers: map[string]string{"_StrongRedirect": location}}
}

// XmlResponse создание ответа в формате xml
func XmlResponse(status int, v interface{}) IResponse {
	b, err := xml.Marshal(v)
	if err != nil {
		return &Response{
			Bytes:   []byte(err.Error()),
			Status:  500,
			Headers: map[string]string{"Content-Type": "plain/text"},
		}
	}
	return &Response{
		Bytes:   b,
		Status:  status,
		Headers: map[string]string{"Content-Type": "application/xml"},
	}
}

// XmlResponse создание ответа в виде локального файла
func FileResponse(filePath string) IResponse {
	return &Response{Bytes: nil, Status: -1, Headers: map[string]string{"_FilePath": filePath}}
}
<|endoftext|>


<commit_before>package baa

import (
	"bufio"
	"io"
	"net"
	"net/http"
)

// Response implement ResponseWriter
type Response struct {
	wroteHeader bool  // reply header has been (logically) written
	written     int64 // number of bytes written in body
	status      int   // status code passed to WriteHeader
	resp        http.ResponseWriter
	writer      io.Writer
	baa         *Baa
}

// NewResponse ...
func NewResponse(w http.ResponseWriter, b *Baa) *Response {
	r := new(Response)
	r.resp = w
	r.writer = w
	r.baa = b
	return r
}

// Header returns the header map that will be sent by
// WriteHeader. Changing the header after a call to
// WriteHeader (or Write) has no effect unless the modified
// headers were declared as trailers by setting the
// "Trailer" header before the call to WriteHeader (see example).
// To suppress implicit response headers, set their value to nil.
func (r *Response) Header() http.Header {
	return r.resp.Header()
}

// Write writes the data to the connection as part of an HTTP reply.
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
// before writing the data.  If the Header does not contain a
// Content-Type line, Write adds a Content-Type set to the result of passing
// the initial 512 bytes of written data to DetectContentType.
func (r *Response) Write(b []byte) (int, error) {
	if !r.wroteHeader {
		r.WriteHeader(http.StatusOK)
	}
	n, err := r.writer.Write(b)
	r.written += int64(n)
	return n, err
}

// WriteHeader sends an HTTP response header with status code.
// If WriteHeader is not called explicitly, the first call to Write
// will trigger an implicit WriteHeader(http.StatusOK).
// Thus explicit calls to WriteHeader are mainly used to
// send error codes.
func (r *Response) WriteHeader(code int) {
	if r.wroteHeader {
		r.baa.Logger().Println("http: multiple response.WriteHeader calls")
		return
	}
	r.wroteHeader = true
	r.status = code
	r.resp.WriteHeader(code)
}

// Flush implements the http.Flusher interface to allow an HTTP handler to flush
// buffered data to the client.
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
func (r *Response) Flush() {
	r.resp.(http.Flusher).Flush()
}

// Hijack implements the http.Hijacker interface to allow an HTTP handler to
// take over the connection.
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	return r.resp.(http.Hijacker).Hijack()
}

// CloseNotify implements the http.CloseNotifier interface to allow detecting
// when the underlying connection has gone away.
// This mechanism can be used to cancel long operations on the server if the
// client has disconnected before the response is ready.
// See [http.CloseNotifier](https://golang.org/pkg/net/http/#CloseNotifier)
func (r *Response) CloseNotify() <-chan bool {
	return r.resp.(http.CloseNotifier).CloseNotify()
}

// reset reuse response
func (r *Response) reset(w http.ResponseWriter) {
	r.resp = w
	r.writer = w
	r.wroteHeader = false
	r.written = 0
	r.status = http.StatusOK
}

// Status returns status code
func (r *Response) Status() int {
	return r.status
}

// Size returns body size
func (r *Response) Size() int64 {
	return r.written
}

// Wrote returns if writes something
func (r *Response) Wrote() bool {
	return r.wroteHeader
}

// GetWriter returns response io writer
func (r *Response) GetWriter() io.Writer {
	return r.writer
}

// SetWriter set response io writer
func (r *Response) SetWriter(w io.Writer) {
	r.writer = w
}
<commit_msg>add http2 pusher<commit_after>package baa

import (
	"bufio"
	"errors"
	"io"
	"net"
	"net/http"
)

// Response implement ResponseWriter
type Response struct {
	wroteHeader bool  // reply header has been (logically) written
	written     int64 // number of bytes written in body
	status      int   // status code passed to WriteHeader
	resp        http.ResponseWriter
	writer      io.Writer
	baa         *Baa
}

// NewResponse ...
func NewResponse(w http.ResponseWriter, b *Baa) *Response {
	r := new(Response)
	r.resp = w
	r.writer = w
	r.baa = b
	return r
}

// Header returns the header map that will be sent by
// WriteHeader. Changing the header after a call to
// WriteHeader (or Write) has no effect unless the modified
// headers were declared as trailers by setting the
// "Trailer" header before the call to WriteHeader (see example).
// To suppress implicit response headers, set their value to nil.
func (r *Response) Header() http.Header {
	return r.resp.Header()
}

// Write writes the data to the connection as part of an HTTP reply.
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
// before writing the data.  If the Header does not contain a
// Content-Type line, Write adds a Content-Type set to the result of passing
// the initial 512 bytes of written data to DetectContentType.
func (r *Response) Write(b []byte) (int, error) {
	if !r.wroteHeader {
		r.WriteHeader(http.StatusOK)
	}
	n, err := r.writer.Write(b)
	r.written += int64(n)
	return n, err
}

// WriteHeader sends an HTTP response header with status code.
// If WriteHeader is not called explicitly, the first call to Write
// will trigger an implicit WriteHeader(http.StatusOK).
// Thus explicit calls to WriteHeader are mainly used to
// send error codes.
func (r *Response) WriteHeader(code int) {
	if r.wroteHeader {
		r.baa.Logger().Println("http: multiple response.WriteHeader calls")
		return
	}
	r.wroteHeader = true
	r.status = code
	r.resp.WriteHeader(code)
}

// Flush implements the http.Flusher interface to allow an HTTP handler to flush
// buffered data to the client.
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
func (r *Response) Flush() {
	if v, ok := r.resp.(http.Flusher); ok {
		v.Flush()
	}
}

// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
func (r *Response) Pusher() (http.Pusher, bool) {
	v, ok := r.resp.(http.Pusher)
	return v, ok
}

// Hijack implements the http.Hijacker interface to allow an HTTP handler to
// take over the connection.
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	if v, ok := r.resp.(http.Hijacker); ok {
		return v.Hijack()
	}
	return nil, nil, errors.New("http.response denot implements the http.Hijacker")
}

// CloseNotify implements the http.CloseNotifier interface to allow detecting
// when the underlying connection has gone away.
// This mechanism can be used to cancel long operations on the server if the
// client has disconnected before the response is ready.
// See [http.CloseNotifier](https://golang.org/pkg/net/http/#CloseNotifier)
func (r *Response) CloseNotify() <-chan bool {
	return r.resp.(http.CloseNotifier).CloseNotify()
}

// reset reuse response
func (r *Response) reset(w http.ResponseWriter) {
	r.resp = w
	r.writer = w
	r.wroteHeader = false
	r.written = 0
	r.status = http.StatusOK
}

// Status returns status code
func (r *Response) Status() int {
	return r.status
}

// Size returns body size
func (r *Response) Size() int64 {
	return r.written
}

// Wrote returns if writes something
func (r *Response) Wrote() bool {
	return r.wroteHeader
}

// GetWriter returns response io writer
func (r *Response) GetWriter() io.Writer {
	return r.writer
}

// SetWriter set response io writer
func (r *Response) SetWriter(w io.Writer) {
	r.writer = w
}
<|endoftext|>