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

// Package googledirectpath implements a resolver that configures xds to make
// cloud to prod directpath connection.
//
// It's a combo of DNS and xDS resolvers. It delegates to DNS if
// - not on GCE, or
// - xDS bootstrap env var is set (so this client needs to do normal xDS, not
// direct path, and clients with this scheme is not part of the xDS mesh).
package googledirectpath

import (
	"fmt"
	"time"

	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/google"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/internal/googlecloud"
	internalgrpclog "google.golang.org/grpc/internal/grpclog"
	"google.golang.org/grpc/internal/grpcrand"
	"google.golang.org/grpc/internal/xds/env"
	"google.golang.org/grpc/resolver"
	_ "google.golang.org/grpc/xds" // To register xds resolvers and balancers.
	"google.golang.org/grpc/xds/internal/version"
	"google.golang.org/grpc/xds/internal/xdsclient"
	"google.golang.org/grpc/xds/internal/xdsclient/bootstrap"
	"google.golang.org/protobuf/types/known/structpb"
)

const (
	c2pScheme = "google-c2p"

	tdURL          = "directpath-trafficdirector.googleapis.com"
	httpReqTimeout = 10 * time.Second
	zoneURL        = "http://metadata.google.internal/computeMetadata/v1/instance/zone"
	ipv6URL        = "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ipv6s"

	gRPCUserAgentName               = "gRPC Go"
	clientFeatureNoOverprovisioning = "envoy.lb.does_not_support_overprovisioning"
	ipv6CapableMetadataName         = "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE"

	logPrefix = "[google-c2p-resolver]"

	dnsName, xdsName = "dns", "xds"
)

// For overriding in unittests.
var (
	onGCE = googlecloud.OnGCE

	newClientWithConfig = func(config *bootstrap.Config) (xdsclient.XDSClient, error) {
		return xdsclient.NewWithConfig(config)
	}

	logger = internalgrpclog.NewPrefixLogger(grpclog.Component("directpath"), logPrefix)
)

func init() {
	if env.C2PResolverSupport {
		resolver.Register(c2pResolverBuilder{})
	}
}

type c2pResolverBuilder struct{}

func (c2pResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
	if !runDirectPath() {
		// If not xDS, fallback to DNS.
		t.Scheme = dnsName
		return resolver.Get(dnsName).Build(t, cc, opts)
	}

	// Note that the following calls to getZone() and getIPv6Capable() does I/O,
	// and has 10 seconds timeout each.
	//
	// This should be fine in most of the cases. In certain error cases, this
	// could block Dial() for up to 10 seconds (each blocking call has its own
	// goroutine).
	zoneCh, ipv6CapableCh := make(chan string), make(chan bool)
	go func() { zoneCh <- getZone(httpReqTimeout) }()
	go func() { ipv6CapableCh <- getIPv6Capable(httpReqTimeout) }()

	balancerName := env.C2PResolverTestOnlyTrafficDirectorURI
	if balancerName == "" {
		balancerName = tdURL
	}
	config := &bootstrap.Config{
		BalancerName: balancerName,
		Creds:        grpc.WithCredentialsBundle(google.NewDefaultCredentials()),
		TransportAPI: version.TransportV3,
		NodeProto:    newNode(<-zoneCh, <-ipv6CapableCh),
	}

	// Create singleton xds client with this config. The xds client will be
	// used by the xds resolver later.
	xdsC, err := newClientWithConfig(config)
	if err != nil {
		return nil, fmt.Errorf("failed to start xDS client: %v", err)
	}

	// Create and return an xDS resolver.
	t.Scheme = xdsName
	xdsR, err := resolver.Get(xdsName).Build(t, cc, opts)
	if err != nil {
		xdsC.Close()
		return nil, err
	}
	return &c2pResolver{
		Resolver: xdsR,
		client:   xdsC,
	}, nil
}

func (c2pResolverBuilder) Scheme() string {
	return c2pScheme
}

type c2pResolver struct {
	resolver.Resolver
	client xdsclient.XDSClient
}

func (r *c2pResolver) Close() {
	r.Resolver.Close()
	r.client.Close()
}

var ipv6EnabledMetadata = &structpb.Struct{
	Fields: map[string]*structpb.Value{
		ipv6CapableMetadataName: structpb.NewBoolValue(true),
	},
}

var id = fmt.Sprintf("C2P-%d", grpcrand.Int())

// newNode makes a copy of defaultNode, and populate it's Metadata and
// Locality fields.
func newNode(zone string, ipv6Capable bool) *v3corepb.Node {
	ret := &v3corepb.Node{
		// Not all required fields are set in defaultNote. Metadata will be set
		// if ipv6 is enabled. Locality will be set to the value from metadata.
		Id:                   id,
		UserAgentName:        gRPCUserAgentName,
		UserAgentVersionType: &v3corepb.Node_UserAgentVersion{UserAgentVersion: grpc.Version},
		ClientFeatures:       []string{clientFeatureNoOverprovisioning},
	}
	ret.Locality = &v3corepb.Locality{Zone: zone}
	if ipv6Capable {
		ret.Metadata = ipv6EnabledMetadata
	}
	return ret
}

// runDirectPath returns whether this resolver should use direct path.
//
// direct path is enabled if this client is running on GCE, and the normal xDS
// is not used (bootstrap env vars are not set).
func runDirectPath() bool {
	return env.BootstrapFileName == "" && env.BootstrapFileContent == "" && onGCE()
}
<commit_msg>xds/c2p: update default XDS server name in C2P resolver (#4705)<commit_after>/*
 *
 * Copyright 2021 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package googledirectpath implements a resolver that configures xds to make
// cloud to prod directpath connection.
//
// It's a combo of DNS and xDS resolvers. It delegates to DNS if
// - not on GCE, or
// - xDS bootstrap env var is set (so this client needs to do normal xDS, not
// direct path, and clients with this scheme is not part of the xDS mesh).
package googledirectpath

import (
	"fmt"
	"time"

	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/google"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/internal/googlecloud"
	internalgrpclog "google.golang.org/grpc/internal/grpclog"
	"google.golang.org/grpc/internal/grpcrand"
	"google.golang.org/grpc/internal/xds/env"
	"google.golang.org/grpc/resolver"
	_ "google.golang.org/grpc/xds" // To register xds resolvers and balancers.
	"google.golang.org/grpc/xds/internal/version"
	"google.golang.org/grpc/xds/internal/xdsclient"
	"google.golang.org/grpc/xds/internal/xdsclient/bootstrap"
	"google.golang.org/protobuf/types/known/structpb"
)

const (
	c2pScheme = "google-c2p"

	tdURL          = "directpath-pa.googleapis.com"
	httpReqTimeout = 10 * time.Second
	zoneURL        = "http://metadata.google.internal/computeMetadata/v1/instance/zone"
	ipv6URL        = "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ipv6s"

	gRPCUserAgentName               = "gRPC Go"
	clientFeatureNoOverprovisioning = "envoy.lb.does_not_support_overprovisioning"
	ipv6CapableMetadataName         = "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE"

	logPrefix = "[google-c2p-resolver]"

	dnsName, xdsName = "dns", "xds"
)

// For overriding in unittests.
var (
	onGCE = googlecloud.OnGCE

	newClientWithConfig = func(config *bootstrap.Config) (xdsclient.XDSClient, error) {
		return xdsclient.NewWithConfig(config)
	}

	logger = internalgrpclog.NewPrefixLogger(grpclog.Component("directpath"), logPrefix)
)

func init() {
	if env.C2PResolverSupport {
		resolver.Register(c2pResolverBuilder{})
	}
}

type c2pResolverBuilder struct{}

func (c2pResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
	if !runDirectPath() {
		// If not xDS, fallback to DNS.
		t.Scheme = dnsName
		return resolver.Get(dnsName).Build(t, cc, opts)
	}

	// Note that the following calls to getZone() and getIPv6Capable() does I/O,
	// and has 10 seconds timeout each.
	//
	// This should be fine in most of the cases. In certain error cases, this
	// could block Dial() for up to 10 seconds (each blocking call has its own
	// goroutine).
	zoneCh, ipv6CapableCh := make(chan string), make(chan bool)
	go func() { zoneCh <- getZone(httpReqTimeout) }()
	go func() { ipv6CapableCh <- getIPv6Capable(httpReqTimeout) }()

	balancerName := env.C2PResolverTestOnlyTrafficDirectorURI
	if balancerName == "" {
		balancerName = tdURL
	}
	config := &bootstrap.Config{
		BalancerName: balancerName,
		Creds:        grpc.WithCredentialsBundle(google.NewDefaultCredentials()),
		TransportAPI: version.TransportV3,
		NodeProto:    newNode(<-zoneCh, <-ipv6CapableCh),
	}

	// Create singleton xds client with this config. The xds client will be
	// used by the xds resolver later.
	xdsC, err := newClientWithConfig(config)
	if err != nil {
		return nil, fmt.Errorf("failed to start xDS client: %v", err)
	}

	// Create and return an xDS resolver.
	t.Scheme = xdsName
	xdsR, err := resolver.Get(xdsName).Build(t, cc, opts)
	if err != nil {
		xdsC.Close()
		return nil, err
	}
	return &c2pResolver{
		Resolver: xdsR,
		client:   xdsC,
	}, nil
}

func (c2pResolverBuilder) Scheme() string {
	return c2pScheme
}

type c2pResolver struct {
	resolver.Resolver
	client xdsclient.XDSClient
}

func (r *c2pResolver) Close() {
	r.Resolver.Close()
	r.client.Close()
}

var ipv6EnabledMetadata = &structpb.Struct{
	Fields: map[string]*structpb.Value{
		ipv6CapableMetadataName: structpb.NewBoolValue(true),
	},
}

var id = fmt.Sprintf("C2P-%d", grpcrand.Int())

// newNode makes a copy of defaultNode, and populate it's Metadata and
// Locality fields.
func newNode(zone string, ipv6Capable bool) *v3corepb.Node {
	ret := &v3corepb.Node{
		// Not all required fields are set in defaultNote. Metadata will be set
		// if ipv6 is enabled. Locality will be set to the value from metadata.
		Id:                   id,
		UserAgentName:        gRPCUserAgentName,
		UserAgentVersionType: &v3corepb.Node_UserAgentVersion{UserAgentVersion: grpc.Version},
		ClientFeatures:       []string{clientFeatureNoOverprovisioning},
	}
	ret.Locality = &v3corepb.Locality{Zone: zone}
	if ipv6Capable {
		ret.Metadata = ipv6EnabledMetadata
	}
	return ret
}

// runDirectPath returns whether this resolver should use direct path.
//
// direct path is enabled if this client is running on GCE, and the normal xDS
// is not used (bootstrap env vars are not set).
func runDirectPath() bool {
	return env.BootstrapFileName == "" && env.BootstrapFileContent == "" && onGCE()
}
<|endoftext|>


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

// Copyright 2012 Erik Unger. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

/*
Package email provides methods surronding:

- Email storage
- User lookup by email address
- Email addess validation
- Email address verification
*/
package email

import (
	"appengine"
	"appengine/datastore"
	"errors"
	"github.com/gaego/ds"
	"regexp"
	"strings"
	"time"
)

var (
	ErrInvalidAddress      = errors.New("email: invalid address")
	ErrAddressInUse        = errors.New("email: address in use by another user")
	ErrAddressAlreadyAdded = errors.New("email: address has already been added")
)

var emailRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z0-9\-+~_%]+[a-zA-Z0-9\-+~_%.]*@([a-z]+[a-z0-9\\-]*\.)+[a-z][a-z]+$`)

// Validate returns an ErrInvalidEmail if the supplied
// string does not contains an "@" and a ".".
func Validate(address string) error {
	if !emailRegexp.MatchString(strings.TrimSpace(address)) {
		return ErrInvalidAddress
	}
	return nil
}

const (
	unverified = iota
	pending
	verified
	primary
)

type Email struct {
	Key     *datastore.Key `datastore:"-",json:"-"`
	Address string         `json:"address"`
	UserID  string         `json:"-"`
	Status  int64          `json:"status"`
	// Created is a time.Time of when the Email was first created.
	Created time.Time `json:"created"`
	// Updated is a time.Time of when the Email was last updated.
	Updated time.Time `json:"updated"`
}

// New creates a new email entity and set Created to now
func New() *Email {
	return &Email{
		Created: time.Now(),
		Updated: time.Now(),
	}
}

func (e *Email) SetKey(c appengine.Context, address string) {
	e.Key = datastore.NewKey(c, "Email", address, 0, nil)
	return
}

func (e *Email) Put(c appengine.Context) (err error) {
	e.Updated = time.Now()
	e.Address = strings.ToLower(e.Key.StringID())
	e.Key, err = ds.Put(c, e.Key, e)
	return
}

func Get(c appengine.Context, address string) (*Email, error) {
	e := New()
	key := datastore.NewKey(c, "Email", strings.ToLower(address), 0, nil)
	err := ds.Get(c, key, e)
	e.Key = key
	return e, err
}

func GetMulti(c appengine.Context, ids []string) (ee []*Email, err error) {
	key := make([]*datastore.Key, len(ids))
	for k, id := range ids {
		key[k] = datastore.NewKey(c, "Email", id, 0, nil)
	}
	ee = make([]*Email, len(ids))
	for i := range ee {
		ee[i] = new(Email)
	}
	err = ds.GetMulti(c, key, ee)
	for i := range ee {
		ee[i].Key = key[i]
	}
	return
}

func AddForUser(c appengine.Context, address, userID string, status int64) (e *Email, err error) {

	err = datastore.RunInTransaction(c, func(c appengine.Context) error {
		e, err = Get(c, address)
		if e.UserID != "" {
			if e.UserID != userID {
				return ErrAddressInUse
			}
			return ErrAddressAlreadyAdded
		}
		e = New()
		e.SetKey(c, address)
		e.UserID = userID
		e.Status = status
		return e.Put(c)
	}, nil)

	return e, err
}
<commit_msg>Fixes issue #1<commit_after>// Copyright 2012 GAEGo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Copyright 2012 Erik Unger. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

/*
Package email provides methods surronding:

- Email storage
- User lookup by email address
- Email addess validation
- Email address verification
*/
package email

import (
	"appengine"
	"appengine/datastore"
	"errors"
	"github.com/gaego/ds"
	"regexp"
	"strings"
	"time"
)

var (
	ErrInvalidAddress      = errors.New("email: invalid address")
	ErrAddressInUse        = errors.New("email: address in use by another user")
	ErrAddressAlreadyAdded = errors.New("email: address has already been added")
)

var emailRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z0-9\-+~_%]+[a-zA-Z0-9\-+~_%.]*@([a-z]+[a-z0-9\\-]*\.)+[a-z][a-z]+$`)

// Validate returns an ErrInvalidEmail if the supplied
// string does not contains an "@" and a ".".
func Validate(address string) error {
	if !emailRegexp.MatchString(strings.TrimSpace(address)) {
		return ErrInvalidAddress
	}
	return nil
}

const (
	unverified = iota
	pending
	verified
	primary
)

type Email struct {
	Key     *datastore.Key `datastore:"-" json:"-"`
	Address string         `json:"address"`
	UserID  string         `json:"-"`
	Status  int64          `json:"status"`
	// Created is a time.Time of when the Email was first created.
	Created time.Time `json:"created"`
	// Updated is a time.Time of when the Email was last updated.
	Updated time.Time `json:"updated"`
}

// New creates a new email entity and set Created to now
func New() *Email {
	return &Email{
		Created: time.Now(),
		Updated: time.Now(),
	}
}

func (e *Email) SetKey(c appengine.Context, address string) {
	e.Key = datastore.NewKey(c, "Email", address, 0, nil)
	return
}

func (e *Email) Put(c appengine.Context) (err error) {
	e.Updated = time.Now()
	e.Address = strings.ToLower(e.Key.StringID())
	e.Key, err = ds.Put(c, e.Key, e)
	return
}

func Get(c appengine.Context, address string) (*Email, error) {
	e := New()
	key := datastore.NewKey(c, "Email", strings.ToLower(address), 0, nil)
	err := ds.Get(c, key, e)
	e.Key = key
	return e, err
}

func GetMulti(c appengine.Context, ids []string) (ee []*Email, err error) {
	key := make([]*datastore.Key, len(ids))
	for k, id := range ids {
		key[k] = datastore.NewKey(c, "Email", id, 0, nil)
	}
	ee = make([]*Email, len(ids))
	for i := range ee {
		ee[i] = new(Email)
	}
	err = ds.GetMulti(c, key, ee)
	for i := range ee {
		ee[i].Key = key[i]
	}
	return
}

func AddForUser(c appengine.Context, address, userID string, status int64) (e *Email, err error) {

	err = datastore.RunInTransaction(c, func(c appengine.Context) error {
		e, err = Get(c, address)
		if e.UserID != "" {
			if e.UserID != userID {
				return ErrAddressInUse
			}
			return ErrAddressAlreadyAdded
		}
		e = New()
		e.SetKey(c, address)
		e.UserID = userID
		e.Status = status
		return e.Put(c)
	}, nil)

	return e, err
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"

	//"github.com/GreenNav/service-database/database"
	"github.com/GreenNav/service-database/database/sqlite"
	"github.com/GreenNav/service-database/importer"
)

var dbTypeFlagDescription = "Determines which database to use. Can be sqlite or postgres"
var dbFileFlagDescription = "Sets the name of the database file to import to"
var dbSchemaFlagDescription = "File with the database setup queries"
var importFlagDescription = "Pbf file to import"

var dbTypeFlag = flag.String("dbtype", "sqlite", dbTypeFlagDescription)
var dbFileFlag = flag.String("dbfile", "gn.db", dbFileFlagDescription)
var dbSchemaFlag = flag.String("dbschema", "gn.db", dbSchemaFlagDescription)
var importFlag = flag.String("import", "", importFlagDescription)

func init() {
	flag.StringVar(dbTypeFlag, "d", "sqlite", dbTypeFlagDescription+" (shorthand)")
	flag.StringVar(dbFileFlag, "f", "gn.db", dbFileFlagDescription+" (shorthand)")
	flag.StringVar(dbSchemaFlag, "s", "./schemata/sqlite.sql", dbSchemaFlagDescription+" (shorthand)")
	flag.StringVar(importFlag, "i", "", importFlagDescription+" (shorthand)")
}

func main() {
	flag.Parse()

	if *importFlag == "" {
		log.Fatal("Please use the -import flag to import a .pbf file")
	}

	fmt.Println("Creating the database")
	db, err := sqlite.CreateEmpty(*dbFileFlag, *dbSchemaFlag)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Importing the file")
	err = importer.WriteToDatabase(*importFlag, db)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Closing database")
	db.Close()
	fmt.Println("Done!")
}
<commit_msg>Fixed a bug where the schema in the long schema flag of the main program was not changed<commit_after>package main

import (
	"flag"
	"fmt"
	"log"

	//"github.com/GreenNav/service-database/database"
	"github.com/GreenNav/service-database/database/sqlite"
	"github.com/GreenNav/service-database/importer"
)

var dbTypeFlagDescription = "Determines which database to use. Can be sqlite or postgres"
var dbFileFlagDescription = "Sets the name of the database file to import to"
var dbSchemaFlagDescription = "File with the database setup queries"
var importFlagDescription = "Pbf file to import"

var dbTypeFlag = flag.String("dbtype", "sqlite", dbTypeFlagDescription)
var dbFileFlag = flag.String("dbfile", "gn.db", dbFileFlagDescription)
var dbSchemaFlag = flag.String("dbschema", "./schemata/sqlite.sql", dbSchemaFlagDescription)
var importFlag = flag.String("import", "", importFlagDescription)

func init() {
	flag.StringVar(dbTypeFlag, "d", "sqlite", dbTypeFlagDescription+" (shorthand)")
	flag.StringVar(dbFileFlag, "f", "gn.db", dbFileFlagDescription+" (shorthand)")
	flag.StringVar(dbSchemaFlag, "s", "./schemata/sqlite.sql", dbSchemaFlagDescription+" (shorthand)")
	flag.StringVar(importFlag, "i", "", importFlagDescription+" (shorthand)")
}

func main() {
	flag.Parse()

	if *importFlag == "" {
		log.Fatal("Please use the -import flag to import a .pbf file")
	}

	fmt.Println("Creating the database")
	db, err := sqlite.CreateEmpty(*dbFileFlag, *dbSchemaFlag)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Importing the file")
	err = importer.WriteToDatabase(*importFlag, db)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Closing database")
	db.Close()
	fmt.Println("Done!")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/nlopes/slack"
)

func main() {
	api := slack.New("YOUR_TOKEN_HERE")
	channels, err := api.GetChannels(false)
	if err != nil {
		fmt.Printf("%s\n", err)
		return
	}
	for _, channel := range channels {
		fmt.Println(channel.ID)
	}
}
<commit_msg>Print readable names for example 👀<commit_after>package main

import (
	"fmt"

	"github.com/nlopes/slack"
)

func main() {
	api := slack.New("YOUR_TOKEN_HERE")
	channels, err := api.GetChannels(false)
	if err != nil {
		fmt.Printf("%s\n", err)
		return
	}
	for _, channel := range channels {
		fmt.Println(channel.Name)
		// channel is of type conversation & groupConversation
		// see all available methods in `conversation.go`
	}
}
<|endoftext|>


<commit_before>package slave

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"fmt"

	"sync"

	"github.com/inimei/backup/log"
	"github.com/inimei/ddns/config"
	"github.com/inimei/ddns/data"
	"github.com/inimei/ddns/data/model"
	"github.com/inimei/ddns/errs"
	"github.com/inimei/ddns/web"
	"github.com/inimei/ddns/web/signature"
)

type SlaveServer struct {
	db data.IDatabase

	sync.RWMutex
	updating bool
}

type recode struct {
	Id      int64            `json:"id"`
	Type    model.RecodeType `json:"type"`
	Name    string           `json:"name"`
	Dynamic bool             `json:"dynamic"`
	Value   string           `json:"value"`
	Ttl     int              `json:"ttl"`
	Key     string           `json:"key"`
	domian  string
	userid  int64
}

func (ss *SlaveServer) Init(db data.IDatabase) error {

	if db == nil {
		log.Error(errs.ErrInvalidParam.Error())
		return errs.ErrInvalidParam
	}

	if len(config.Data.Slave.MasterHost) == 0 {
		log.Error("master host can't be empty")
		return errors.New("master host can't be empty")
	}

	if len(config.Data.Slave.Accesskey) == 0 || len(config.Data.Slave.SecretKey) == 0 {
		log.Error("accesskey & secretKey  host can't be empty")
		return errors.New("accesskey & secretKey  host can't be empty")
	}

	ss.db = db
	ss.updating = false

	return nil
}

func (ss *SlaveServer) IsUpdating() bool {
	ss.RLock()
	defer ss.RUnlock()
	return ss.updating
}

func (ss *SlaveServer) setStatus(b bool) {
	ss.Lock()
	defer ss.Unlock()
	ss.updating = b
}

func (ss *SlaveServer) Start() {
	ticker := time.NewTicker(time.Second * time.Duration(config.Data.Slave.UpdateTime))

	go ss.checkUpdate(true)

	go func() {
		for {
			ss.checkUpdate(false)
			<-ticker.C
		}
	}()
}

func (ss *SlaveServer) checkUpdate(force bool) {

	if ss.IsUpdating() {
		return
	}

	ss.setStatus(true)
	defer ss.setStatus(false)

	v, err := ss.getVersion()
	if err != nil {
		log.Error(err.Error())
		return
	}

	if v.SchemaVersion != model.CurrentVersion {
		log.Error("schema version not match, need update...")
		return
	}

	if !force && v.DataVersion == ss.db.GetVersion() {
		log.Debug("the same data version....")
		return
	}

	recodes, err := ss.getRecodes()
	if err != nil {
		log.Error(err.Error())
		return
	}

	if len(recodes) == 0 {
		return
	}

	db, err := ss.db.BeginTransaction()
	if err != nil {
		log.Error(err.Error())
		return
	}

	defer func() {
		if err == nil {
			db.Commit()
		} else {
			db.Rollback()
		}
	}()

	err = db.ClearRecodes(true)
	if err != nil {
		log.Error(err.Error())
		return
	}

	for _, r := range recodes {
		d, err := db.FindDomainByName(r.domian)
		if err != nil {
			log.Warn("find domain [%v] failed: %v", r.domian, err)

			d = &model.Domain{}
			d.Synced = true
			d.DomainName = r.domian

			id, err := db.NewDomain(r.userid, d)
			if err != nil {
				log.Error(err.Error())
				continue
			}
			d.UserID = id
		}

		_r := model.Recode{}
		_r.Dynamic = r.Dynamic
		_r.RecodeValue = r.Value
		_r.RecordHost = r.Name
		_r.RecordType = r.Type
		_r.TTL = r.Ttl
		_r.Synced = true
		if len(r.Key) > 0 {
			_r.UpdateKey.String = r.Key
			_r.UpdateKey.Valid = true
		}
		if _, err = db.NewRecode(d.ID, &_r); err != nil {
			log.Error(err.Error())
			return
		}
	}

	//jast ss.db
	ss.db.SetVersion(v.DataVersion)
}

func (ss *SlaveServer) getRecodes() ([]recode, error) {

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives: true,
		},
	}

	url := "/api/recodes"
	req, err := http.NewRequest("GET", config.Data.Slave.MasterHost+url, strings.NewReader(""))
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	signature.SignRequest(req, url, config.Data.Slave.Accesskey, config.Data.Slave.SecretKey, "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	bodyData, err := ioutil.ReadAll(resp.Body)

	var data = struct {
		Code    string `json:"code"`
		Msg     string `json:"msg"`
		Domains []struct {
			ID      int64    `json:"id"`
			Domain  string   `json:"domain"`
			UserID  int64    `json:"userid"`
			Recodes []recode `json:"recodes"`
		} `json:"domains"`
	}{}

	err = json.Unmarshal(bodyData, &data)
	if err != nil {
		log.Error("Unmarshal recodes failed: %v", err)
		return nil, err
	}

	if data.Code != web.CodeOK {
		err = fmt.Errorf("get recodes failed: %v, msg: %v", data.Code, data.Msg)
		log.Error(err.Error())
		return nil, err
	}

	rs := []recode{}
	for _, d := range data.Domains {
		_rs := []recode{}
		for _, r := range d.Recodes {
			r.domian = d.Domain
			r.userid = d.UserID
			_rs = append(_rs, r)
		}
		rs = append(rs, _rs...)
	}

	return rs, nil
}

func (ss *SlaveServer) getVersion() (*model.Version, error) {

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives: true,
		},
	}

	url := "/api/dataversion"
	req, err := http.NewRequest("GET", config.Data.Slave.MasterHost+url, strings.NewReader(""))
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	signature.SignRequest(req, url, config.Data.Slave.Accesskey, config.Data.Slave.SecretKey, "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	bodyData, err := ioutil.ReadAll(resp.Body)

	var version = struct {
		Code    string        `json:"code"`
		Msg     string        `json:"msg"`
		Version model.Version `json:"version"`
	}{}

	err = json.Unmarshal(bodyData, &version)
	if err != nil {
		log.Error("Unmarshal version failed: %v", err.Error())
		return nil, err
	}

	if version.Code != web.CodeOK {
		err = fmt.Errorf("get version failed: %v, msg: %v", version.Code, version.Msg)
		log.Error(err.Error())
		return nil, err
	}

	return &version.Version, nil
}
<commit_msg>fix slave update<commit_after>package slave

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"fmt"

	"sync"

	"github.com/inimei/backup/log"
	"github.com/inimei/ddns/config"
	"github.com/inimei/ddns/data"
	"github.com/inimei/ddns/data/model"
	"github.com/inimei/ddns/errs"
	"github.com/inimei/ddns/web"
	"github.com/inimei/ddns/web/signature"
)

type SlaveServer struct {
	db data.IDatabase

	sync.RWMutex
	updating bool
}

type recode struct {
	Id      int64            `json:"id"`
	Type    model.RecodeType `json:"type"`
	Name    string           `json:"name"`
	Dynamic bool             `json:"dynamic"`
	Value   string           `json:"value"`
	Ttl     int              `json:"ttl"`
	Key     string           `json:"key"`
	domian  string
	userid  int64
}

func (ss *SlaveServer) Init(db data.IDatabase) error {

	if db == nil {
		log.Error(errs.ErrInvalidParam.Error())
		return errs.ErrInvalidParam
	}

	if len(config.Data.Slave.MasterHost) == 0 {
		log.Error("master host can't be empty")
		return errors.New("master host can't be empty")
	}

	if len(config.Data.Slave.Accesskey) == 0 || len(config.Data.Slave.SecretKey) == 0 {
		log.Error("accesskey & secretKey  host can't be empty")
		return errors.New("accesskey & secretKey  host can't be empty")
	}

	ss.db = db
	ss.updating = false

	return nil
}

func (ss *SlaveServer) IsUpdating() bool {
	ss.RLock()
	defer ss.RUnlock()
	return ss.updating
}

func (ss *SlaveServer) setStatus(b bool) {
	ss.Lock()
	defer ss.Unlock()
	ss.updating = b
}

func (ss *SlaveServer) Start() {
	ticker := time.NewTicker(time.Second * time.Duration(config.Data.Slave.UpdateTime))

	go ss.checkUpdate(true)

	go func() {
		for {
			<-ticker.C
			ss.checkUpdate(false)
		}
	}()
}

func (ss *SlaveServer) checkUpdate(force bool) {

	if ss.IsUpdating() {
		return
	}

	ss.setStatus(true)
	defer ss.setStatus(false)

	v, err := ss.getVersion()
	if err != nil {
		log.Error(err.Error())
		return
	}

	if v.SchemaVersion != model.CurrentVersion {
		log.Error("schema version not match, need update...")
		return
	}

	if !force && v.DataVersion == ss.db.GetVersion() {
		log.Debug("the same data version....")
		return
	}

	recodes, err := ss.getRecodes()
	if err != nil {
		log.Error(err.Error())
		return
	}

	if len(recodes) == 0 {
		return
	}

	db, err := ss.db.BeginTransaction()
	if err != nil {
		log.Error(err.Error())
		return
	}

	defer func() {
		if err == nil {
			db.Commit()
		} else {
			db.Rollback()
		}
	}()

	err = db.ClearRecodes(true)
	if err != nil {
		log.Error(err.Error())
		return
	}

	for _, r := range recodes {
		d, err := db.FindDomainByName(r.domian)
		if err != nil {
			log.Warn("find domain [%v] failed: %v", r.domian, err)

			d = &model.Domain{}
			d.Synced = true
			d.DomainName = r.domian

			id, err := db.NewDomain(r.userid, d)
			if err != nil {
				log.Error(err.Error())
				continue
			}
			d.UserID = id
		}

		_r := model.Recode{}
		_r.Dynamic = r.Dynamic
		_r.RecodeValue = r.Value
		_r.RecordHost = r.Name
		_r.RecordType = r.Type
		_r.TTL = r.Ttl
		_r.Synced = true
		if len(r.Key) > 0 {
			_r.UpdateKey.String = r.Key
			_r.UpdateKey.Valid = true
		}
		if _, err = db.NewRecode(d.ID, &_r); err != nil {
			log.Error(err.Error())
			return
		}
	}

	//jast ss.db
	ss.db.SetVersion(v.DataVersion)
}

func (ss *SlaveServer) getRecodes() ([]recode, error) {

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives: true,
		},
	}

	url := "/api/recodes"
	req, err := http.NewRequest("GET", config.Data.Slave.MasterHost+url, strings.NewReader(""))
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	signature.SignRequest(req, url, config.Data.Slave.Accesskey, config.Data.Slave.SecretKey, "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	bodyData, err := ioutil.ReadAll(resp.Body)

	var data = struct {
		Code    string `json:"code"`
		Msg     string `json:"msg"`
		Domains []struct {
			ID      int64    `json:"id"`
			Domain  string   `json:"domain"`
			UserID  int64    `json:"userid"`
			Recodes []recode `json:"recodes"`
		} `json:"domains"`
	}{}

	err = json.Unmarshal(bodyData, &data)
	if err != nil {
		log.Error("Unmarshal recodes failed: %v", err)
		return nil, err
	}

	if data.Code != web.CodeOK {
		err = fmt.Errorf("get recodes failed: %v, msg: %v", data.Code, data.Msg)
		log.Error(err.Error())
		return nil, err
	}

	rs := []recode{}
	for _, d := range data.Domains {
		_rs := []recode{}
		for _, r := range d.Recodes {
			r.domian = d.Domain
			r.userid = d.UserID
			_rs = append(_rs, r)
		}
		rs = append(rs, _rs...)
	}

	return rs, nil
}

func (ss *SlaveServer) getVersion() (*model.Version, error) {

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives: true,
		},
	}

	url := "/api/dataversion"
	req, err := http.NewRequest("GET", config.Data.Slave.MasterHost+url, strings.NewReader(""))
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	signature.SignRequest(req, url, config.Data.Slave.Accesskey, config.Data.Slave.SecretKey, "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Error(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	bodyData, err := ioutil.ReadAll(resp.Body)

	var version = struct {
		Code    string        `json:"code"`
		Msg     string        `json:"msg"`
		Version model.Version `json:"version"`
	}{}

	err = json.Unmarshal(bodyData, &version)
	if err != nil {
		log.Error("Unmarshal version failed: %v", err.Error())
		return nil, err
	}

	if version.Code != web.CodeOK {
		err = fmt.Errorf("get version failed: %v, msg: %v", version.Code, version.Msg)
		log.Error(err.Error())
		return nil, err
	}

	return &version.Version, nil
}
<|endoftext|>


<commit_before>package godescribe

import (
	"fmt"
	"strings"
)

type defaultReporter struct {
	noColor              bool
	slowSpecThreshold    float64
	randomSeed           int64
	randomizeAllExamples bool
	lastExampleWasABlock bool
}

func newDefaultReporter(noColor bool, slowSpecThreshold float64) *defaultReporter {
	return &defaultReporter{
		noColor:           noColor,
		slowSpecThreshold: slowSpecThreshold,
	}
}

const defaultStyle = "\x1b[0m"
const boldStyle = "\x1b[1m"
const redColor = "\x1b[91m"
const greenColor = "\x1b[32m"
const yellowColor = "\x1b[33m"
const cyanColor = "\x1b[36m"
const grayColor = "\x1b[90m"
const blueColor = "\x1b[94m"

func (reporter *defaultReporter) colorize(colorCode string, format string, args ...interface{}) string {
	s := fmt.Sprintf(format, args...)
	if reporter.noColor {
		return s
	} else {
		return fmt.Sprintf("%s%s%s", colorCode, s, defaultStyle)
	}
}

func (reporter *defaultReporter) printBanner(s string, bannerCharacter string) {
	fmt.Println(s)
	fmt.Println(strings.Repeat(bannerCharacter, len(s)))
}

func (reporter *defaultReporter) printNewLine() {
	fmt.Println("")
}

func (reporter *defaultReporter) printDelimiter() {
	fmt.Println(reporter.colorize(grayColor, "%s", strings.Repeat("-", 30)))
}

func (reporter *defaultReporter) indent(indentation int, format string, args ...interface{}) string {
	text := fmt.Sprintf(format, args...)

	stringArray := strings.Split(text, "\n")
	padding := strings.Repeat("  ", indentation)
	for i, s := range stringArray {
		stringArray[i] = fmt.Sprintf("%s%s", padding, s)
	}

	return strings.Join(stringArray, "\n")
}

func (reporter *defaultReporter) print(indentation int, format string, args ...interface{}) {
	fmt.Print(reporter.indent(indentation, format, args...))
}

func (reporter *defaultReporter) println(indentation int, format string, args ...interface{}) {
	fmt.Println(reporter.indent(indentation, format, args...))
}

func (reporter *defaultReporter) RandomizationStrategy(randomSeed int64, randomizeAllExamples bool) {
	reporter.randomSeed = randomSeed
	reporter.randomizeAllExamples = randomizeAllExamples
}

func (reporter *defaultReporter) SpecSuiteWillBegin(summary *SuiteSummary) {
	reporter.printNewLine()
	reporter.printBanner(fmt.Sprintf("Running Suite: %s", summary.SuiteDescription), "=")
	randomSeedReport := fmt.Sprintf("Random Seed: %s", reporter.colorize(boldStyle, "%d", reporter.randomSeed))
	if reporter.randomizeAllExamples {
		randomSeedReport += " - Will randomize all examples"
	}
	reporter.println(0, randomSeedReport)
	reporter.printNewLine()

	reporter.println(0,
		"Will run %s of %s specs",
		reporter.colorize(boldStyle, "%d", summary.NumberOfExamplesThatWillBeRun),
		reporter.colorize(boldStyle, "%d", summary.NumberOfTotalExamples))

	reporter.printNewLine()
}

func (reporter *defaultReporter) ExampleDidComplete(exampleSummary *ExampleSummary) {
	if exampleSummary.State == ExampleStatePassed {
		reporter.printStatus(greenColor, "•", exampleSummary)
	} else if exampleSummary.State == ExampleStatePending {
		reporter.printStatus(yellowColor, "P", exampleSummary)
	} else if exampleSummary.State == ExampleStateSkipped {
		reporter.printStatus(cyanColor, "S", exampleSummary)
	} else if exampleSummary.State == ExampleStateTimedOut {
		reporter.printFailure("•... Timeout", exampleSummary)
	} else if exampleSummary.State == ExampleStatePanicked {
		reporter.printFailure("•! Panic", exampleSummary)
	} else if exampleSummary.State == ExampleStateFailed {
		reporter.printFailure("• Failure", exampleSummary)
	}
}

func (reporter *defaultReporter) SpecSuiteDidEnd(summary *SuiteSummary) {
	reporter.printNewLine()
	color := greenColor
	if summary.NumberOfFailedExamples > 0 {
		color = redColor
	}
	reporter.println(0, reporter.colorize(boldStyle+color, "Ran %d of %d Specs in %.3f seconds", summary.NumberOfExamplesThatWillBeRun, summary.NumberOfTotalExamples, summary.RunTime.Seconds()))

	status := ""
	if summary.NumberOfFailedExamples == 0 {
		status = fmt.Sprintf(reporter.colorize(boldStyle+greenColor, "SUCCESS!"))
	} else {
		status = fmt.Sprintf(reporter.colorize(boldStyle+redColor, "FAIL!"))
	}

	reporter.println(0,
		"%s -- %s | %s | %s | %s",
		status,
		reporter.colorize(greenColor+boldStyle, "%d Passed", summary.NumberOfPassedExamples),
		reporter.colorize(redColor+boldStyle, "%d Failed", summary.NumberOfFailedExamples),
		reporter.colorize(yellowColor+boldStyle, "%d Pending", summary.NumberOfPendingExamples),
		reporter.colorize(cyanColor+boldStyle, "%d Skipped", summary.NumberOfSkippedExamples),
	)
	reporter.printNewLine()
}

func (reporter *defaultReporter) printStatus(color string, message string, exampleSummary *ExampleSummary) {
	if exampleSummary.RunTime.Seconds() >= reporter.slowSpecThreshold {
		if !reporter.lastExampleWasABlock {
			reporter.printNewLine()
			reporter.printDelimiter()
		}
		reporter.println(0, reporter.colorize(color, "%s [SLOW TEST:%.3f seconds]", message, exampleSummary.RunTime.Seconds()))

		for i := 1; i < len(exampleSummary.ComponentTexts); i++ {
			reporter.println(i-1, "%s", exampleSummary.ComponentTexts[i])
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		}

		reporter.printDelimiter()
		reporter.lastExampleWasABlock = true
	} else {
		reporter.print(0, reporter.colorize(color, message))
		reporter.lastExampleWasABlock = false
	}
}

func (reporter *defaultReporter) printFailure(message string, exampleSummary *ExampleSummary) {
	if !reporter.lastExampleWasABlock {
		reporter.printNewLine()
		reporter.printDelimiter()
	}
	reporter.println(0, reporter.colorize(redColor+boldStyle, "%s [%.3f seconds]", message, exampleSummary.RunTime.Seconds()))
	for i := 1; i < len(exampleSummary.ComponentTexts); i++ {
		if i == exampleSummary.Failure.ComponentIndex {
			blockType := ""
			switch exampleSummary.Failure.ComponentType {
			case ExampleComponentTypeBeforeEach:
				blockType = "BeforeEach"
			case ExampleComponentTypeJustBeforeEach:
				blockType = "JustBeforeEach"
			case ExampleComponentTypeAfterEach:
				blockType = "AfterEach"
			case ExampleComponentTypeIt:
				blockType = "It"
			}
			reporter.println(i-1, reporter.colorize(redColor+boldStyle, "%s [%s]", exampleSummary.ComponentTexts[i], blockType))
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		} else {
			reporter.println(i-1, exampleSummary.ComponentTexts[i])
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		}
	}

	indentation := exampleSummary.Failure.ComponentIndex - 1

	reporter.printNewLine()
	if exampleSummary.State == ExampleStatePanicked {
		reporter.println(indentation, reporter.colorize(redColor+boldStyle, exampleSummary.Failure.Message))
		reporter.println(indentation, reporter.colorize(redColor, "> %s", exampleSummary.Failure.ForwardedPanic))
		reporter.println(indentation, exampleSummary.Failure.Location.String())
		reporter.printNewLine()
		reporter.println(indentation, reporter.colorize(redColor, "Full Stack Trace"))
		reporter.println(indentation, exampleSummary.Failure.Location.FullStackTrace)
	} else {
		reporter.println(indentation, reporter.colorize(redColor, "> %s", exampleSummary.Failure.Message))
		reporter.println(indentation, exampleSummary.Failure.Location.String())
	}

	reporter.printDelimiter()
	reporter.lastExampleWasABlock = true
}
<commit_msg>tweak reporter<commit_after>package godescribe

import (
	"fmt"
	"strings"
)

type defaultReporter struct {
	noColor              bool
	slowSpecThreshold    float64
	randomSeed           int64
	randomizeAllExamples bool
	lastExampleWasABlock bool
}

func newDefaultReporter(noColor bool, slowSpecThreshold float64) *defaultReporter {
	return &defaultReporter{
		noColor:           noColor,
		slowSpecThreshold: slowSpecThreshold,
	}
}

const defaultStyle = "\x1b[0m"
const boldStyle = "\x1b[1m"
const redColor = "\x1b[91m"
const greenColor = "\x1b[32m"
const yellowColor = "\x1b[33m"
const cyanColor = "\x1b[36m"
const grayColor = "\x1b[90m"
const blueColor = "\x1b[94m"

func (reporter *defaultReporter) colorize(colorCode string, format string, args ...interface{}) string {
	s := fmt.Sprintf(format, args...)
	if reporter.noColor {
		return s
	} else {
		return fmt.Sprintf("%s%s%s", colorCode, s, defaultStyle)
	}
}

func (reporter *defaultReporter) printBanner(s string, bannerCharacter string) {
	fmt.Println(s)
	fmt.Println(strings.Repeat(bannerCharacter, len(s)))
}

func (reporter *defaultReporter) printNewLine() {
	fmt.Println("")
}

func (reporter *defaultReporter) printDelimiter() {
	fmt.Println(reporter.colorize(grayColor, "%s", strings.Repeat("-", 30)))
}

func (reporter *defaultReporter) indent(indentation int, format string, args ...interface{}) string {
	text := fmt.Sprintf(format, args...)

	stringArray := strings.Split(text, "\n")
	padding := strings.Repeat("  ", indentation)
	for i, s := range stringArray {
		stringArray[i] = fmt.Sprintf("%s%s", padding, s)
	}

	return strings.Join(stringArray, "\n")
}

func (reporter *defaultReporter) print(indentation int, format string, args ...interface{}) {
	fmt.Print(reporter.indent(indentation, format, args...))
}

func (reporter *defaultReporter) println(indentation int, format string, args ...interface{}) {
	fmt.Println(reporter.indent(indentation, format, args...))
}

func (reporter *defaultReporter) RandomizationStrategy(randomSeed int64, randomizeAllExamples bool) {
	reporter.randomSeed = randomSeed
	reporter.randomizeAllExamples = randomizeAllExamples
}

func (reporter *defaultReporter) SpecSuiteWillBegin(summary *SuiteSummary) {
	reporter.printNewLine()
	reporter.printBanner(fmt.Sprintf("Running Suite: %s", summary.SuiteDescription), "=")
	randomSeedReport := fmt.Sprintf("Random Seed: %s", reporter.colorize(boldStyle, "%d", reporter.randomSeed))
	if reporter.randomizeAllExamples {
		randomSeedReport += " - Will randomize all examples"
	}
	reporter.println(0, randomSeedReport)
	reporter.printNewLine()

	reporter.println(0,
		"Will run %s of %s specs",
		reporter.colorize(boldStyle, "%d", summary.NumberOfExamplesThatWillBeRun),
		reporter.colorize(boldStyle, "%d", summary.NumberOfTotalExamples))

	reporter.printNewLine()
}

func (reporter *defaultReporter) ExampleDidComplete(exampleSummary *ExampleSummary) {
	if exampleSummary.State == ExampleStatePassed {
		reporter.printStatus(greenColor, "•", exampleSummary)
	} else if exampleSummary.State == ExampleStatePending {
		reporter.printStatus(yellowColor, "P", exampleSummary)
	} else if exampleSummary.State == ExampleStateSkipped {
		reporter.printStatus(cyanColor, "S", exampleSummary)
	} else if exampleSummary.State == ExampleStateTimedOut {
		reporter.printFailure("•... Timeout", exampleSummary)
	} else if exampleSummary.State == ExampleStatePanicked {
		reporter.printFailure("•! Panic", exampleSummary)
	} else if exampleSummary.State == ExampleStateFailed {
		reporter.printFailure("• Failure", exampleSummary)
	}
}

func (reporter *defaultReporter) SpecSuiteDidEnd(summary *SuiteSummary) {
	reporter.printNewLine()
	color := greenColor
	if summary.NumberOfFailedExamples > 0 {
		color = redColor
	}
	reporter.println(0, reporter.colorize(boldStyle+color, "Ran %d of %d Specs in %.3f seconds", summary.NumberOfExamplesThatWillBeRun, summary.NumberOfTotalExamples, summary.RunTime.Seconds()))

	status := ""
	if summary.NumberOfFailedExamples == 0 {
		status = fmt.Sprintf(reporter.colorize(boldStyle+greenColor, "SUCCESS!"))
	} else {
		status = fmt.Sprintf(reporter.colorize(boldStyle+redColor, "FAIL!"))
	}

	reporter.println(0,
		"%s -- %s | %s | %s | %s",
		status,
		reporter.colorize(greenColor+boldStyle, "%d Passed", summary.NumberOfPassedExamples),
		reporter.colorize(redColor+boldStyle, "%d Failed", summary.NumberOfFailedExamples),
		reporter.colorize(yellowColor+boldStyle, "%d Pending", summary.NumberOfPendingExamples),
		reporter.colorize(cyanColor+boldStyle, "%d Skipped", summary.NumberOfSkippedExamples),
	)
	reporter.printNewLine()
}

func (reporter *defaultReporter) printStatus(color string, message string, exampleSummary *ExampleSummary) {
	if exampleSummary.RunTime.Seconds() >= reporter.slowSpecThreshold {
		if !reporter.lastExampleWasABlock {
			reporter.printNewLine()
			reporter.printDelimiter()
		}
		reporter.println(0, reporter.colorize(color, "%s [SLOW TEST:%.3f seconds]", message, exampleSummary.RunTime.Seconds()))

		for i := 1; i < len(exampleSummary.ComponentTexts); i++ {
			reporter.println(i-1, "%s", exampleSummary.ComponentTexts[i])
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		}

		reporter.printDelimiter()
		reporter.lastExampleWasABlock = true
	} else {
		reporter.print(0, reporter.colorize(color, message))
		reporter.lastExampleWasABlock = false
	}
}

func (reporter *defaultReporter) printFailure(message string, exampleSummary *ExampleSummary) {
	if !reporter.lastExampleWasABlock {
		reporter.printNewLine()
		reporter.printDelimiter()
	}
	reporter.println(0, reporter.colorize(redColor+boldStyle, "%s [%.3f seconds]", message, exampleSummary.RunTime.Seconds()))
	for i := 1; i < len(exampleSummary.ComponentTexts); i++ {
		if i == exampleSummary.Failure.ComponentIndex {
			blockType := ""
			switch exampleSummary.Failure.ComponentType {
			case ExampleComponentTypeBeforeEach:
				blockType = "BeforeEach"
			case ExampleComponentTypeJustBeforeEach:
				blockType = "JustBeforeEach"
			case ExampleComponentTypeAfterEach:
				blockType = "AfterEach"
			case ExampleComponentTypeIt:
				blockType = "It"
			}
			reporter.println(i-1, reporter.colorize(redColor+boldStyle, "%s [%s]", exampleSummary.ComponentTexts[i], blockType))
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		} else {
			reporter.println(i-1, exampleSummary.ComponentTexts[i])
			reporter.println(i-1, reporter.colorize(grayColor, "(%s)", exampleSummary.ComponentCodeLocations[i]))
		}
	}

	indentation := exampleSummary.Failure.ComponentIndex - 1

	reporter.printNewLine()
	if exampleSummary.State == ExampleStatePanicked {
		reporter.println(indentation, reporter.colorize(redColor+boldStyle, exampleSummary.Failure.Message))
		reporter.println(indentation, reporter.colorize(redColor, "%s", exampleSummary.Failure.ForwardedPanic))
		reporter.println(indentation, exampleSummary.Failure.Location.String())
		reporter.printNewLine()
		reporter.println(indentation, reporter.colorize(redColor, "Full Stack Trace"))
		reporter.println(indentation, exampleSummary.Failure.Location.FullStackTrace)
	} else {
		reporter.println(indentation, reporter.colorize(redColor, exampleSummary.Failure.Message))
		reporter.printNewLine()
		reporter.println(indentation, exampleSummary.Failure.Location.String())
	}

	reporter.printDelimiter()
	reporter.lastExampleWasABlock = true
}
<|endoftext|>


<commit_before>package restful

import (
	"github.com/emicklei/go-restful/swagger"
	"log"
	"net/http"
)

type SwaggerConfig struct {
	WebServicesUrl  string // url where the services are available, e.g. http://localhost:8080
	ApiPath         string // path where the JSON api is avaiable , e.g. /apidocs
	SwaggerPath     string // path where the swagger UI will be served, e.g. /swagger
	SwaggerFilePath string // location of folder containing Swagger HTML5 application index.html
}

var webServicesBasePath string
var swaggerServiceApiPath string

// InstallSwaggerService add the WebService that provides the API documentation of all services
// conform the Swagger documentation specifcation. (https://github.com/wordnik/swagger-core/wiki).
func InstallSwaggerService(config SwaggerConfig) {
	// TODO just keep config around
	webServicesBasePath = config.WebServicesUrl
	swaggerServiceApiPath = config.ApiPath

	ws := new(WebService)
	ws.Path(config.ApiPath)
	ws.Produces(MIME_JSON)
	ws.Route(ws.GET("/").To(getListing))
	ws.Route(ws.GET("/{a}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}/{c}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}/{c}/{d}").To(getDeclarations)) // TODO maybe support * in the path spec?
	log.Printf("[restful/swagger] listing is available at %v%v", config.WebServicesUrl, config.ApiPath)
	Add(ws)

	// Install FileServer
	log.Printf("[restful/swagger] %v%v is mapped to folder %v", config.WebServicesUrl, config.SwaggerPath, config.SwaggerFilePath)
	http.Handle(config.SwaggerPath, http.StripPrefix(config.SwaggerPath, http.FileServer(http.Dir(config.SwaggerFilePath))))
}

func getListing(req *Request, resp *Response) {
	listing := swagger.ResourceListing{SwaggerVersion: "1.1", BasePath: webServicesBasePath}
	for _, each := range webServices {
		// skip the api service itself
		if each.RootPath() != swaggerServiceApiPath {
			api := swagger.Api{
				Path: swaggerServiceApiPath + each.RootPath()}
			//Description: each.Doc}
			listing.Apis = append(listing.Apis, api)
		}
	}
	resp.WriteAsJson(listing)
}

func getDeclarations(req *Request, resp *Response) {
	rootPath := composeRootPath(req)
	// log.Printf("rootPath:%V", rootPath)
	decl := swagger.ApiDeclaration{SwaggerVersion: "1.1", BasePath: webServicesBasePath, ResourcePath: rootPath}
	for _, each := range webServices {
		// find the webservice
		if each.RootPath() == rootPath {
			// collect any path parameters
			rootParams := []swagger.Parameter{}
			for _, param := range each.PathParameters() {
				rootParams = append(rootParams, asSwaggerParameter(param))
			}
			// aggregate by path
			pathToRoutes := map[string][]Route{}
			for _, other := range each.Routes() {
				routes := pathToRoutes[other.Path]
				pathToRoutes[other.Path] = append(routes, other)
			}
			for path, routes := range pathToRoutes {
				api := swagger.Api{Path: path}
				for _, route := range routes {
					operation := swagger.Operation{HttpMethod: route.Method, Summary: route.Doc}
					// share root params if any
					for _, swparam := range rootParams {
						operation.Parameters = append(operation.Parameters, swparam)
					}
					// route specific params
					for _, param := range route.parameterDocs {
						operation.Parameters = append(operation.Parameters, asSwaggerParameter(param))
					}
					api.Operations = append(api.Operations, operation)
				}
				decl.Apis = append(decl.Apis, api)
			}
		}
	}
	resp.WriteAsJson(decl)
}

func asSwaggerParameter(param *Parameter) swagger.Parameter {
	return swagger.Parameter{
		Name:        param.name,
		Description: param.description,
		ParamType:   asParamType(param.kind),
		DataType:    "String",
		Required:    param.required}
}

// Between 1..4 path parameters supported
func composeRootPath(req *Request) string {
	path := "/" + req.PathParameter("a")
	b := req.PathParameter("b")
	if b == "" {
		return path
	}
	path = path + "/" + b
	c := req.PathParameter("c")
	if c == "" {
		return path
	}
	path = path + "/" + c
	d := req.PathParameter("d")
	if d == "" {
		return path
	}
	return path + "/" + d
}

func asParamType(kind int) string {
	switch {
	case kind == PATH_PARAMETER:
		return "path"
	case kind == QUERY_PARAMETER:
		return "query"
	case kind == BODY_PARAMETER:
		return "body"
	}
	return ""
}
<commit_msg>Use Parameter.dataType for Swagger type<commit_after>package restful

import (
	"github.com/emicklei/go-restful/swagger"
	"log"
	"net/http"
)

type SwaggerConfig struct {
	WebServicesUrl  string // url where the services are available, e.g. http://localhost:8080
	ApiPath         string // path where the JSON api is avaiable , e.g. /apidocs
	SwaggerPath     string // path where the swagger UI will be served, e.g. /swagger
	SwaggerFilePath string // location of folder containing Swagger HTML5 application index.html
}

var webServicesBasePath string
var swaggerServiceApiPath string

// InstallSwaggerService add the WebService that provides the API documentation of all services
// conform the Swagger documentation specifcation. (https://github.com/wordnik/swagger-core/wiki).
func InstallSwaggerService(config SwaggerConfig) {
	// TODO just keep config around
	webServicesBasePath = config.WebServicesUrl
	swaggerServiceApiPath = config.ApiPath

	ws := new(WebService)
	ws.Path(config.ApiPath)
	ws.Produces(MIME_JSON)
	ws.Route(ws.GET("/").To(getListing))
	ws.Route(ws.GET("/{a}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}/{c}").To(getDeclarations))
	ws.Route(ws.GET("/{a}/{b}/{c}/{d}").To(getDeclarations)) // TODO maybe support * in the path spec?
	log.Printf("[restful/swagger] listing is available at %v%v", config.WebServicesUrl, config.ApiPath)
	Add(ws)

	// Install FileServer
	log.Printf("[restful/swagger] %v%v is mapped to folder %v", config.WebServicesUrl, config.SwaggerPath, config.SwaggerFilePath)
	http.Handle(config.SwaggerPath, http.StripPrefix(config.SwaggerPath, http.FileServer(http.Dir(config.SwaggerFilePath))))
}

func getListing(req *Request, resp *Response) {
	listing := swagger.ResourceListing{SwaggerVersion: "1.1", BasePath: webServicesBasePath}
	for _, each := range webServices {
		// skip the api service itself
		if each.RootPath() != swaggerServiceApiPath {
			api := swagger.Api{
				Path: swaggerServiceApiPath + each.RootPath()}
			//Description: each.Doc}
			listing.Apis = append(listing.Apis, api)
		}
	}
	resp.WriteAsJson(listing)
}

func getDeclarations(req *Request, resp *Response) {
	rootPath := composeRootPath(req)
	// log.Printf("rootPath:%V", rootPath)
	decl := swagger.ApiDeclaration{SwaggerVersion: "1.1", BasePath: webServicesBasePath, ResourcePath: rootPath}
	for _, each := range webServices {
		// find the webservice
		if each.RootPath() == rootPath {
			// collect any path parameters
			rootParams := []swagger.Parameter{}
			for _, param := range each.PathParameters() {
				rootParams = append(rootParams, asSwaggerParameter(param))
			}
			// aggregate by path
			pathToRoutes := map[string][]Route{}
			for _, other := range each.Routes() {
				routes := pathToRoutes[other.Path]
				pathToRoutes[other.Path] = append(routes, other)
			}
			for path, routes := range pathToRoutes {
				api := swagger.Api{Path: path}
				for _, route := range routes {
					operation := swagger.Operation{HttpMethod: route.Method, Summary: route.Doc}
					// share root params if any
					for _, swparam := range rootParams {
						operation.Parameters = append(operation.Parameters, swparam)
					}
					// route specific params
					for _, param := range route.parameterDocs {
						operation.Parameters = append(operation.Parameters, asSwaggerParameter(param))
					}
					api.Operations = append(api.Operations, operation)
				}
				decl.Apis = append(decl.Apis, api)
			}
		}
	}
	resp.WriteAsJson(decl)
}

func asSwaggerParameter(param *Parameter) swagger.Parameter {
	return swagger.Parameter{
		Name:        param.name,
		Description: param.description,
		ParamType:   asParamType(param.kind),
		DataType:    param.dataType,
		Required:    param.required}
}

// Between 1..4 path parameters supported
func composeRootPath(req *Request) string {
	path := "/" + req.PathParameter("a")
	b := req.PathParameter("b")
	if b == "" {
		return path
	}
	path = path + "/" + b
	c := req.PathParameter("c")
	if c == "" {
		return path
	}
	path = path + "/" + c
	d := req.PathParameter("d")
	if d == "" {
		return path
	}
	return path + "/" + d
}

func asParamType(kind int) string {
	switch {
	case kind == PATH_PARAMETER:
		return "path"
	case kind == QUERY_PARAMETER:
		return "query"
	case kind == BODY_PARAMETER:
		return "body"
	}
	return ""
}
<|endoftext|>


<commit_before>package gen

import (
	"fmt"
	"path"
	"strconv"
	"strings"
	"text/template"
)

var (
	defaultFuncs = template.FuncMap{
		"greaterThanEqualF": func(b, a float64) bool {
			return b >= a
		},
		"lessThanEqualF": func(b, a float64) bool {
			return b <= a
		},
		"greaterThanEqual": func(b, a int) bool {
			return b >= a
		},
		"capitalize": func(b string) string {
			if len(b) == 0 {
				return b
			}

			return strings.ToUpper(b[:1]) + b[1:]
		},
		"title": func(b string) string {
			return strings.ToTitle(b)
		},
		"trim": func(b, suff string) string {
			return strings.Trim(b, suff)
		},
		"trimSuffix": func(b, suff string) string {
			return strings.TrimSuffix(b, suff)
		},
		"trimPrefix": func(b, pre string) string {
			return strings.TrimPrefix(b, pre)
		},
		"hasSuffix": func(b, suff string) bool {
			return strings.HasSuffix(b, suff)
		},
		"hasPrefix": func(b, pre string) bool {
			return strings.HasPrefix(b, pre)
		},
		"lower": func(b string) string {
			return strings.ToLower(b)
		},
		"upper": func(b string) string {
			return strings.ToUpper(b)
		},
		"joinPath": func(b ...string) string {
			return path.Join(b...)
		},
		"basePathName": func(b string) string {
			return path.Base(b)
		},
		"joinSlice": func(jn string, vals []string) string {
			return strings.Join(vals, jn)
		},
		"join": func(jn string, vals ...string) string {
			return strings.Join(vals, jn)
		},
		"splitAfter": func(b string, sp string, n int) []string {
			return strings.SplitAfterN(b, sp, n)
		},
		"split": func(b string, sp string) []string {
			return strings.Split(b, sp)
		},
		"indent": func(b string) string {
			return strings.Join(strings.Split(b, "\n"), "\n\t")
		},
		"lessThanEqual": func(b, a int) bool {
			return b <= a
		},
		"greaterThanF": func(b, a float64) bool {
			return b > a
		},
		"lessThanF": func(b, a float64) bool {
			return b < a
		},
		"greaterThan": func(b, a int) bool {
			return b > a
		},
		"lessThan": func(b, a int) bool {
			return b < a
		},
		"trimspace": func(b string) string {
			return strings.TrimSpace(b)
		},
		"equal": func(b, a interface{}) bool {
			return b == a
		},
		"not": func(b bool) bool {
			return !!b
		},
		"notequal": func(b, a interface{}) bool {
			return b != a
		},
		"quote": func(b interface{}) string {
			switch bo := b.(type) {
			case string:
				return strconv.Quote(bo)
			case int:
				return strconv.Quote(strconv.Itoa(bo))
			case bool:
				return strconv.Quote(strconv.FormatBool(bo))
			case int64:
				return strconv.Quote(strconv.Itoa(int(bo)))
			case float32:
				mo := strconv.FormatFloat(float64(bo), 'f', 4, 32)
				return strconv.Quote(mo)
			case float64:
				mo := strconv.FormatFloat(bo, 'f', 4, 32)
				return strconv.Quote(mo)
			case byte:
				return strconv.QuoteRune(rune(bo))
			case rune:
				return strconv.QuoteRune(bo)
			default:
				return "Unconvertible Type"
			}
		},
		"prefixInt": func(prefix string, b int) string {
			return fmt.Sprintf("%s%d", prefix, b)
		},
		"stub": func(count int) string {
			var vals []string

			for i := count; i > 0; i-- {
				vals = append(vals, "_")
			}

			return strings.Join(vals, ",")
		},
		"subs": func(word string, b int) string {
			return word[:b]
		},
		"add": func(a, b int) int {
			return a + b
		},
		"multiply": func(a, b int) int {
			return a * b
		},
		"subtract": func(a, b int) int {
			return a - b
		},
		"divide": func(a, b int) int {
			return a / b
		},
		"len": func(b interface{}) int {
			switch bo := b.(type) {
			case []string:
				return len(bo)
			case string:
				return len(bo)
			case []int:
				return len(bo)
			case []bool:
				return len(bo)
			case []int64:
				return len(bo)
			case []float32:
				return len(bo)
			case []float64:
				return len(bo)
			case []byte:
				return len(bo)
			default:
				return 0
			}
		},
		"percentage": func(a, b float64) float64 {
			return (a / b) * 100
		},
	}
)

// ToTemplateFuncs returns a template.FuncMap which is a union of all key and values
// from the provided map. It does not check for function type and will override any previos
// key values.
func ToTemplateFuncs(funcs ...map[string]interface{}) template.FuncMap {
	tfuncs := make(map[string]interface{})

	for _, item := range funcs {
		for k, v := range item {
			tfuncs[k] = v
		}
	}

	return template.FuncMap(tfuncs)
}

// ToTemplate returns a template instance with the giving templ string and functions.
func ToTemplate(name string, templ string, mx template.FuncMap) (*template.Template, error) {
	tml, err := template.New(name).Funcs(defaultFuncs).Funcs(mx).Parse(templ)
	if err != nil {
		return nil, err
	}

	return tml, nil
}
<commit_msg>Add empty/notempty to template funcs<commit_after>package gen

import (
	"fmt"
	"path"
	"strconv"
	"strings"
	"text/template"
)

var (
	defaultFuncs = template.FuncMap{
		"greaterThanEqualF": func(b, a float64) bool {
			return b >= a
		},
		"lessThanEqualF": func(b, a float64) bool {
			return b <= a
		},
		"greaterThanEqual": func(b, a int) bool {
			return b >= a
		},
		"capitalize": func(b string) string {
			if len(b) == 0 {
				return b
			}

			return strings.ToUpper(b[:1]) + b[1:]
		},
		"notempty": func(b string) bool {
			return strings.TrimSpace(b) != ""
		},
		"empty": func(b string) bool {
			return strings.TrimSpace(b) == ""
		},
		"title": func(b string) string {
			return strings.ToTitle(b)
		},
		"trim": func(b, suff string) string {
			return strings.Trim(b, suff)
		},
		"trimSuffix": func(b, suff string) string {
			return strings.TrimSuffix(b, suff)
		},
		"trimPrefix": func(b, pre string) string {
			return strings.TrimPrefix(b, pre)
		},
		"hasSuffix": func(b, suff string) bool {
			return strings.HasSuffix(b, suff)
		},
		"hasPrefix": func(b, pre string) bool {
			return strings.HasPrefix(b, pre)
		},
		"lower": func(b string) string {
			return strings.ToLower(b)
		},
		"upper": func(b string) string {
			return strings.ToUpper(b)
		},
		"joinPath": func(b ...string) string {
			return path.Join(b...)
		},
		"basePathName": func(b string) string {
			return path.Base(b)
		},
		"joinSlice": func(jn string, vals []string) string {
			return strings.Join(vals, jn)
		},
		"join": func(jn string, vals ...string) string {
			return strings.Join(vals, jn)
		},
		"splitAfter": func(b string, sp string, n int) []string {
			return strings.SplitAfterN(b, sp, n)
		},
		"split": func(b string, sp string) []string {
			return strings.Split(b, sp)
		},
		"indent": func(b string) string {
			return strings.Join(strings.Split(b, "\n"), "\n\t")
		},
		"lessThanEqual": func(b, a int) bool {
			return b <= a
		},
		"greaterThanF": func(b, a float64) bool {
			return b > a
		},
		"lessThanF": func(b, a float64) bool {
			return b < a
		},
		"greaterThan": func(b, a int) bool {
			return b > a
		},
		"lessThan": func(b, a int) bool {
			return b < a
		},
		"trimspace": func(b string) string {
			return strings.TrimSpace(b)
		},
		"equal": func(b, a interface{}) bool {
			return b == a
		},
		"not": func(b bool) bool {
			return !!b
		},
		"notequal": func(b, a interface{}) bool {
			return b != a
		},
		"quote": func(b interface{}) string {
			switch bo := b.(type) {
			case string:
				return strconv.Quote(bo)
			case int:
				return strconv.Quote(strconv.Itoa(bo))
			case bool:
				return strconv.Quote(strconv.FormatBool(bo))
			case int64:
				return strconv.Quote(strconv.Itoa(int(bo)))
			case float32:
				mo := strconv.FormatFloat(float64(bo), 'f', 4, 32)
				return strconv.Quote(mo)
			case float64:
				mo := strconv.FormatFloat(bo, 'f', 4, 32)
				return strconv.Quote(mo)
			case byte:
				return strconv.QuoteRune(rune(bo))
			case rune:
				return strconv.QuoteRune(bo)
			default:
				return "Unconvertible Type"
			}
		},
		"prefixInt": func(prefix string, b int) string {
			return fmt.Sprintf("%s%d", prefix, b)
		},
		"stub": func(count int) string {
			var vals []string

			for i := count; i > 0; i-- {
				vals = append(vals, "_")
			}

			return strings.Join(vals, ",")
		},
		"subs": func(word string, b int) string {
			return word[:b]
		},
		"add": func(a, b int) int {
			return a + b
		},
		"multiply": func(a, b int) int {
			return a * b
		},
		"subtract": func(a, b int) int {
			return a - b
		},
		"divide": func(a, b int) int {
			return a / b
		},
		"len": func(b interface{}) int {
			switch bo := b.(type) {
			case []string:
				return len(bo)
			case string:
				return len(bo)
			case []int:
				return len(bo)
			case []bool:
				return len(bo)
			case []int64:
				return len(bo)
			case []float32:
				return len(bo)
			case []float64:
				return len(bo)
			case []byte:
				return len(bo)
			default:
				return 0
			}
		},
		"percentage": func(a, b float64) float64 {
			return (a / b) * 100
		},
	}
)

// ToTemplateFuncs returns a template.FuncMap which is a union of all key and values
// from the provided map. It does not check for function type and will override any previos
// key values.
func ToTemplateFuncs(funcs ...map[string]interface{}) template.FuncMap {
	tfuncs := make(map[string]interface{})

	for _, item := range funcs {
		for k, v := range item {
			tfuncs[k] = v
		}
	}

	return template.FuncMap(tfuncs)
}

// ToTemplate returns a template instance with the giving templ string and functions.
func ToTemplate(name string, templ string, mx template.FuncMap) (*template.Template, error) {
	tml, err := template.New(name).Funcs(defaultFuncs).Funcs(mx).Parse(templ)
	if err != nil {
		return nil, err
	}

	return tml, nil
}
<|endoftext|>


<commit_before>package main

import "fmt"

func xxx() {

	fmt.Println("aaa")

}
<commit_msg>generics: rm abc.go<commit_after><|endoftext|>


<commit_before>package maas

import (
	"errors"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/schema"
	"strings"
)

var maasConfigChecker = schema.StrictFieldMap(
	schema.Fields{
		"maas-server": schema.String(),
		// maas-oauth is a colon-separated triplet of:
		// consumer-key:resource-token:resource-secret
		"maas-oauth": schema.String(),
	},
	schema.Defaults{
		"maas-server": "",
		"maas-oauth":  "",
	},
)

type maasEnvironConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (cfg *maasEnvironConfig) MAASServer() string {
	value, ok := cfg.attrs["maas-server"]
	if !ok {
		return ""
	}
	return value.(string)
}

func (cfg *maasEnvironConfig) MAASOAuth() string {
	value, ok := cfg.attrs["maas-oauth"]
	if !ok {
		return ""
	}
	return value.(string)
}

func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {
	validCfg, err := prov.Validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	result := new(maasEnvironConfig)
	result.Config = validCfg
	result.attrs = validCfg.UnknownAttrs()
	return result, nil
}

var noMaasServer = errors.New("No maas-server configured.")
var noMaasOAuth = errors.New("No maas-oauth configured.")
var malformedMaasOAuth = errors.New("Malformed maas-oauth (3 items separated by colons).")
var noAdminSecret = errors.New("No admin-secret configured.")

func (prov maasEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) {
	v, err := maasConfigChecker.Coerce(cfg.UnknownAttrs(), nil)
	if err != nil {
		return nil, err
	}
	envCfg := new(maasEnvironConfig)
	envCfg.Config = cfg
	envCfg.attrs = v.(map[string]interface{})
	if envCfg.MAASServer() == "" {
		return nil, noMaasServer
	}
	oauth := envCfg.MAASOAuth()
	if oauth == "" {
		return nil, noMaasOAuth
	}
	if strings.Count(oauth, ":") != 2 {
		return nil, malformedMaasOAuth
	}
	if envCfg.AdminSecret() == "" {
		return nil, noAdminSecret
	}
	return cfg.Apply(envCfg.attrs)
}
<commit_msg>To make a field required, just leave out the default.<commit_after>package maas

import (
	"errors"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/schema"
	"strings"
)

var maasConfigChecker = schema.StrictFieldMap(
	schema.Fields{
		"maas-server": schema.String(),
		// maas-oauth is a colon-separated triplet of:
		// consumer-key:resource-token:resource-secret
		"maas-oauth": schema.String(),
	},
	schema.Defaults{},
)

type maasEnvironConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (cfg *maasEnvironConfig) MAASServer() string {
	value, ok := cfg.attrs["maas-server"]
	if !ok {
		return ""
	}
	return value.(string)
}

func (cfg *maasEnvironConfig) MAASOAuth() string {
	value, ok := cfg.attrs["maas-oauth"]
	if !ok {
		return ""
	}
	return value.(string)
}

func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {
	validCfg, err := prov.Validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	result := new(maasEnvironConfig)
	result.Config = validCfg
	result.attrs = validCfg.UnknownAttrs()
	return result, nil
}

var noMaasServer = errors.New("No maas-server configured.")
var noMaasOAuth = errors.New("No maas-oauth configured.")
var malformedMaasOAuth = errors.New("Malformed maas-oauth (3 items separated by colons).")
var noAdminSecret = errors.New("No admin-secret configured.")

func (prov maasEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) {
	v, err := maasConfigChecker.Coerce(cfg.UnknownAttrs(), nil)
	if err != nil {
		return nil, err
	}
	envCfg := new(maasEnvironConfig)
	envCfg.Config = cfg
	envCfg.attrs = v.(map[string]interface{})
	oauth := envCfg.MAASOAuth()
	if strings.Count(oauth, ":") != 2 {
		return nil, malformedMaasOAuth
	}
	return cfg.Apply(envCfg.attrs)
}
<|endoftext|>


<commit_before>// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by BSD-style
// license that can be found in the LICENSE file.

package github

import (
	"fmt"
	"time"
)

// GistsService handles communication with the Gist related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/gists/
type GistsService struct {
	client *Client
}

// Gist represents a GitHub's gist.
type Gist struct {
	ID          *string                   `json:"id,omitempty"`
	Description *string                   `json:"description,omitempty"`
	Public      *bool                     `json:"public,omitempty"`
	Owner       *User                     `json:"owner,omitempty"`
	Files       map[GistFilename]GistFile `json:"files,omitempty"`
	Comments    *int                      `json:"comments,omitempty"`
	HTMLURL     *string                   `json:"html_url,omitempty"`
	GitPullURL  *string                   `json:"git_pull_url,omitempty"`
	GitPushURL  *string                   `json:"git_push_url,omitempty"`
	CreatedAt   *time.Time                `json:"created_at,omitempty"`
}

func (g Gist) String() string {
	return Stringify(g)
}

// GistFilename represents filename on a gist.
type GistFilename string

// GistFile represents a file on a gist.
type GistFile struct {
	Size     *int    `json:"size,omitempty"`
	Filename *string `json:"filename,omitempty"`
	RawURL   *string `json:"raw_url,omitempty"`
	Content  *string `json:"content,omitempty"`
}

func (g GistFile) String() string {
	return Stringify(g)
}

// GistListOptions specifies the optional parameters to the
// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods.
type GistListOptions struct {
	// Since filters Gists by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// List gists for a user. Passing the empty string will list
// all public gists if called anonymously. However, if the call
// is authenticated, it will returns all gists for the authenticated
// user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) List(user string, opt *GistListOptions) ([]Gist, *Response, error) {
	var u string
	if user != "" {
		u = fmt.Sprintf("users/%v/gists", user)
	} else {
		u = "gists"
	}
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// ListAll lists all public gists.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListAll(opt *GistListOptions) ([]Gist, *Response, error) {
	u, err := addOptions("gists/public", opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// ListStarred lists starred gists of authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListStarred(opt *GistListOptions) ([]Gist, *Response, error) {
	u, err := addOptions("gists/starred", opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// Get a single gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#get-a-single-gist
func (s *GistsService) Get(id string) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	gist := new(Gist)
	resp, err := s.client.Do(req, gist)
	if err != nil {
		return nil, resp, err
	}

	return gist, resp, err
}

// Create a gist for authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#create-a-gist
func (s *GistsService) Create(gist *Gist) (*Gist, *Response, error) {
	u := "gists"
	req, err := s.client.NewRequest("POST", u, gist)
	if err != nil {
		return nil, nil, err
	}
	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// Edit a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#edit-a-gist
func (s *GistsService) Edit(id string, gist *Gist) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("PATCH", u, gist)
	if err != nil {
		return nil, nil, err
	}
	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// Delete a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#delete-a-gist
func (s *GistsService) Delete(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// Star a gist on behalf of authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#star-a-gist
func (s *GistsService) Star(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("PUT", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// Unstar a gist on a behalf of authenticated user.
//
// Github API docs: http://developer.github.com/v3/gists/#unstar-a-gist
func (s *GistsService) Unstar(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// IsStarred checks if a gist is starred by authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#check-if-a-gist-is-starred
func (s *GistsService) IsStarred(id string) (bool, *Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return false, nil, err
	}
	resp, err := s.client.Do(req, nil)
	starred, err := parseBoolResponse(err)
	return starred, resp, err
}

// Fork a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#fork-a-gist
func (s *GistsService) Fork(id string) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v/forks", id)
	req, err := s.client.NewRequest("POST", u, nil)
	if err != nil {
		return nil, nil, err
	}

	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}
<commit_msg>Added missing fields in Gist class<commit_after>// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by BSD-style
// license that can be found in the LICENSE file.

package github

import (
	"fmt"
	"time"
)

// GistsService handles communication with the Gist related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/gists/
type GistsService struct {
	client *Client
}

// Gist represents a GitHub's gist.
type Gist struct {
	ID          *string                   `json:"id,omitempty"`
	Description *string                   `json:"description,omitempty"`
	Public      *bool                     `json:"public,omitempty"`
	Owner       *User                     `json:"owner,omitempty"`
	Files       map[GistFilename]GistFile `json:"files,omitempty"`
	Comments    *int                      `json:"comments,omitempty"`
	HTMLURL     *string                   `json:"html_url,omitempty"`
	GitPullURL  *string                   `json:"git_pull_url,omitempty"`
	GitPushURL  *string                   `json:"git_push_url,omitempty"`
	CreatedAt   *time.Time                `json:"created_at,omitempty"`
	UpdatedAt   *time.Time                `json:"updated_at,omitempty"`
}

func (g Gist) String() string {
	return Stringify(g)
}

// GistFilename represents filename on a gist.
type GistFilename string

// GistFile represents a file on a gist.
type GistFile struct {
	Size     *int    `json:"size,omitempty"`
	Filename *string `json:"filename,omitempty"`
	RawURL   *string `json:"raw_url,omitempty"`
	Content  *string `json:"content,omitempty"`
}

func (g GistFile) String() string {
	return Stringify(g)
}

// GistListOptions specifies the optional parameters to the
// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods.
type GistListOptions struct {
	// Since filters Gists by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// List gists for a user. Passing the empty string will list
// all public gists if called anonymously. However, if the call
// is authenticated, it will returns all gists for the authenticated
// user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) List(user string, opt *GistListOptions) ([]Gist, *Response, error) {
	var u string
	if user != "" {
		u = fmt.Sprintf("users/%v/gists", user)
	} else {
		u = "gists"
	}
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// ListAll lists all public gists.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListAll(opt *GistListOptions) ([]Gist, *Response, error) {
	u, err := addOptions("gists/public", opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// ListStarred lists starred gists of authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListStarred(opt *GistListOptions) ([]Gist, *Response, error) {
	u, err := addOptions("gists/starred", opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	gists := new([]Gist)
	resp, err := s.client.Do(req, gists)
	if err != nil {
		return nil, resp, err
	}

	return *gists, resp, err
}

// Get a single gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#get-a-single-gist
func (s *GistsService) Get(id string) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	gist := new(Gist)
	resp, err := s.client.Do(req, gist)
	if err != nil {
		return nil, resp, err
	}

	return gist, resp, err
}

// Create a gist for authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#create-a-gist
func (s *GistsService) Create(gist *Gist) (*Gist, *Response, error) {
	u := "gists"
	req, err := s.client.NewRequest("POST", u, gist)
	if err != nil {
		return nil, nil, err
	}
	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// Edit a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#edit-a-gist
func (s *GistsService) Edit(id string, gist *Gist) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("PATCH", u, gist)
	if err != nil {
		return nil, nil, err
	}
	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// Delete a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#delete-a-gist
func (s *GistsService) Delete(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v", id)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// Star a gist on behalf of authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#star-a-gist
func (s *GistsService) Star(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("PUT", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// Unstar a gist on a behalf of authenticated user.
//
// Github API docs: http://developer.github.com/v3/gists/#unstar-a-gist
func (s *GistsService) Unstar(id string) (*Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}
	return s.client.Do(req, nil)
}

// IsStarred checks if a gist is starred by authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/gists/#check-if-a-gist-is-starred
func (s *GistsService) IsStarred(id string) (bool, *Response, error) {
	u := fmt.Sprintf("gists/%v/star", id)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return false, nil, err
	}
	resp, err := s.client.Do(req, nil)
	starred, err := parseBoolResponse(err)
	return starred, resp, err
}

// Fork a gist.
//
// GitHub API docs: http://developer.github.com/v3/gists/#fork-a-gist
func (s *GistsService) Fork(id string) (*Gist, *Response, error) {
	u := fmt.Sprintf("gists/%v/forks", id)
	req, err := s.client.NewRequest("POST", u, nil)
	if err != nil {
		return nil, nil, err
	}

	g := new(Gist)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}
<|endoftext|>


<commit_before>package glacier

import (
	"bytes"
	"encoding/json"
	"github.com/rdwilliamson/aws"
	"io/ioutil"
	"net/http"
)

type job struct {
	Type        string
	ArchiveId   string `json:",omitempty"` // archive retrieval only
	Description string
	Format      string `json:",omitempty"` // inventory retrieval only
	SNSTopic    string
}

func (c *Connection) InitiateRetrievalJob(vault, archive, topic string) error {
	return nil
}

func (c *Connection) InitiateInventoryJob(vault, description,
	topic string) (string, error) {
	j := job{Type: "inventory-retrieval", Description: description,
		SNSTopic: topic}
	rawBody, err := json.Marshal(j)
	if err != nil {
		return "", err
	}
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) DescribeJob() error {
	return nil
}

func (c *Connection) GetRetrievalJob(vault, job string, start, end uint) error {
	return nil
}

func (c *Connection) GetInventoryJob(vault, job string) error {
	return nil
}

func (c *Connection) ListJobs(vault string) error {
	return nil
}
<commit_msg>Added retrieval of jobs list and jobs inventory.<commit_after>package glacier

import (
	"bytes"
	"encoding/json"
	"github.com/rdwilliamson/aws"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

type jobRequest struct {
	Type        string
	ArchiveId   string `json:",omitempty"` // archive retrieval only
	Description string
	Format      string `json:",omitempty"` // inventory retrieval only
	SNSTopic    string
}

type Archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       time.Time
	Size               uint64
	SHA256TreeHash     string
}

type Inventory struct {
	VaultARN      string
	InventoryDate time.Time
	ArchiveList   []Archive
}

// TODO write unmarshaler instead of using these structs
type archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       string
	Size               uint64
	SHA256TreeHash     string
}
type inventory struct {
	VaultARN      string
	InventoryDate string
	ArchiveList   []archive
}

type Job struct {
	Action               string
	ArchiveId            string
	ArchiveSizeInBytes   uint64
	Completed            bool
	CompletionDate       time.Time
	CreationDate         time.Time
	InventorySizeInBytes uint
	JobDescription       string
	JobId                string
	SHA256TreeHash       string
	SNSTopic             string
	StatusCode           string
	StatusMessage        string
	VaultARN             string
}

// TODO write unmarshaler instead of using these structs
type job struct {
	Action               string
	ArchiveId            *string
	ArchiveSizeInBytes   *uint64
	Completed            bool
	CompletionDate       string
	CreationDate         string
	InventorySizeInBytes *uint
	JobDescription       string
	JobId                string
	SHA256TreeHash       *string
	SNSTopic             string
	StatusCode           string
	StatusMessage        string
	VaultARN             string
}
type jobList struct {
	Marker  *string
	JobList []job
}

func (c *Connection) InitiateRetrievalJob(vault, archive, topic string) error {
	return nil
}

func (c *Connection) InitiateInventoryJob(vault, description,
	topic string) (string, error) {
	j := jobRequest{Type: "inventory-retrieval", Description: description,
		SNSTopic: topic}
	rawBody, err := json.Marshal(j)
	if err != nil {
		return "", err
	}
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) DescribeJob() error {
	return nil
}

func (c *Connection) GetRetrievalJob(vault, job string, start, end uint) error {
	return nil
}

func (c *Connection) GetInventoryJob(vault, job string) (Inventory, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+job+"/output",
		nil)
	if err != nil {
		return Inventory{}, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, nil, nil)
	if err != nil {
		return Inventory{}, err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return Inventory{}, err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return Inventory{}, err
	}
	err = response.Body.Close()
	if err != nil {
		return Inventory{}, err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return Inventory{}, err
		}
		return Inventory{}, e
	}

	var i inventory
	err = json.Unmarshal(body, &i)
	if err != nil {
		return Inventory{}, err
	}

	var result Inventory
	result.VaultARN = i.VaultARN
	result.InventoryDate, err = time.Parse(time.RFC3339, i.InventoryDate)
	if err != nil {
		return Inventory{}, err
	}
	result.ArchiveList = make([]Archive, len(i.ArchiveList))
	for j, v := range i.ArchiveList {
		result.ArchiveList[j].ArchiveId = v.ArchiveId
		result.ArchiveList[j].ArchiveDescription = v.ArchiveDescription
		result.ArchiveList[j].CreationDate, err = time.Parse(time.RFC3339,
			v.CreationDate)
		if err != nil {
			return Inventory{}, err
		}
		result.ArchiveList[j].Size = v.Size
		result.ArchiveList[j].SHA256TreeHash = v.SHA256TreeHash
	}

	return result, nil
}

func (c *Connection) ListJobs(vault, completed, limit, marker,
	statusCode string) ([]Job, string, error) {
	get, err := url.Parse("https://" + c.Signature.Region.Glacier +
		"/-/vaults/" + vault + "/jobs")
	if err != nil {
		return nil, "", err
	}

	query := get.Query()
	if completed != "" {
		// TODO validate, true or false
		query.Add("completed", completed)
	}
	if limit != "" {
		// TODO validate, 1 - 1000
		query.Add("limit", limit)
	}
	if marker != "" {
		// TODO validate
		query.Add("marker", marker)
	}
	if statusCode != "" {
		// TODO validate, InProgress, Succeeded, or Failed
		query.Add("statuscode", statusCode)
	}
	get.RawQuery = query.Encode()

	request, err := http.NewRequest("GET", get.String(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, nil, nil)
	if err != nil {
		return nil, "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, "", err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}
	err = response.Body.Close()
	if err != nil {
		return nil, "", err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, "", err
		}
		return nil, "", e
	}

	var jl jobList
	err = json.Unmarshal(body, &jl)
	if err != nil {
		return nil, "", err
	}

	jobs := make([]Job, len(jl.JobList))
	for i, v := range jl.JobList {
		jobs[i].Action = v.Action
		if v.ArchiveId != nil {
			jobs[i].ArchiveId = *v.ArchiveId
		}
		if v.ArchiveSizeInBytes != nil {
			jobs[i].ArchiveSizeInBytes = *v.ArchiveSizeInBytes
		}
		jobs[i].Completed = v.Completed
		jobs[i].CompletionDate, err = time.Parse(time.RFC3339, v.CompletionDate)
		if err != nil {
			return nil, "", err
		}
		jobs[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			return nil, "", err
		}
		if v.InventorySizeInBytes != nil {
			jobs[i].InventorySizeInBytes = *v.InventorySizeInBytes
		}
		jobs[i].JobDescription = v.JobDescription
		jobs[i].JobId = v.JobId
		if v.SHA256TreeHash != nil {
			jobs[i].SHA256TreeHash = *v.SHA256TreeHash
		}
		jobs[i].SNSTopic = v.SNSTopic
		jobs[i].StatusCode = v.StatusCode
		jobs[i].StatusMessage = v.StatusMessage
		jobs[i].VaultARN = v.VaultARN
	}

	var m string
	if jl.Marker != nil {
		m = *jl.Marker
	}

	return jobs, m, nil
}
<|endoftext|>


<commit_before>/*
 * pingpong.go
 *
 * Copyright 2017 Bill Zissimopoulos
 */
/*
 * This file is part of netchan.
 *
 * It is licensed under the MIT license. The full license text can be found
 * in the License.txt file at the root of this project.
 */

package main

import (
	"fmt"
	"net/url"
	"os"
	"strconv"
	"sync"
	"time"

	"github.com/billziss-gh/netchan/netchan"
)

var mainWG = &sync.WaitGroup{}

func ping(uri string, count int) {
	chch := make(chan chan struct{})

	err := netchan.Connect(uri, chch, nil)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := make(chan struct{})
		chch <- ch
		fmt.Println("ping")
		_ = <-ch
	}

	close(chch)

	mainWG.Done()
}

func pong(id string, count int) {
	chch := make(chan chan struct{})

	err := netchan.Publish(id, chch)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := <-chch
		fmt.Println("pong")
		ch <- struct{}{}
		close(ch)
	}

	netchan.Unpublish(id, chch)

	time.Sleep(100 * time.Millisecond)

	mainWG.Done()
}

func main() {
	args := os.Args

	cmd := args[1]
	lnu, _ := url.Parse(args[2])
	uri := args[3]
	cnt, _ := strconv.Atoi(args[4])

	netchan.RegisterTransport("tcp",
		netchan.NewNetTransport(netchan.DefaultMarshaler, lnu))

	if "ping" == cmd {
		mainWG.Add(1)
		go ping(uri, cnt)
	} else if "pong" == cmd {
		mainWG.Add(1)
		go pong(uri, cnt)
	}

	mainWG.Wait()
}
<commit_msg>pingpong: iping/ipong<commit_after>/*
 * pingpong.go
 *
 * Copyright 2017 Bill Zissimopoulos
 */
/*
 * This file is part of netchan.
 *
 * It is licensed under the MIT license. The full license text can be found
 * in the License.txt file at the root of this project.
 */

package main

import (
	"fmt"
	"net/url"
	"os"
	"strconv"
	"sync"
	"time"

	"github.com/billziss-gh/netchan/netchan"
)

var mainWG = &sync.WaitGroup{}

func ping(uri string, count int) {
	chch := make(chan chan struct{})

	err := netchan.Connect(uri, chch, nil)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := make(chan struct{})
		chch <- ch
		fmt.Println("ping")
		_ = <-ch
	}

	close(chch)

	mainWG.Done()
}

func pong(id string, count int) {
	chch := make(chan chan struct{})

	err := netchan.Publish(id, chch)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := <-chch
		fmt.Println("pong")
		ch <- struct{}{}
		close(ch)
	}

	netchan.Unpublish(id, chch)

	time.Sleep(100 * time.Millisecond)

	mainWG.Done()
}

func iping(uri string, count int) {
	chch := make(chan interface{})

	err := netchan.Connect(uri, chch, nil)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := make(chan interface{})
		chch <- ch
		fmt.Println("iping")
		close(chch)
		chch = (<-ch).(chan interface{})
	}

	close(chch)

	mainWG.Done()
}

func ipong(id string, count int) {
	chch := make(chan interface{})

	err := netchan.Publish(id, chch)
	if nil != err {
		panic(err)
	}

	for i := 0; count > i; i++ {
		ch := (<-chch).(chan interface{})
		fmt.Println("ipong")
		if 0 == i {
			netchan.Unpublish(id, chch)
		}
		chch = make(chan interface{})
		ch <- chch
		close(ch)
	}

	time.Sleep(100 * time.Millisecond)

	mainWG.Done()
}

func main() {
	args := os.Args

	cmd := args[1]
	lnu, _ := url.Parse(args[2])
	uri := args[3]
	cnt, _ := strconv.Atoi(args[4])

	netchan.RegisterTransport("tcp",
		netchan.NewNetTransport(netchan.DefaultMarshaler, lnu))

	if "ping" == cmd {
		mainWG.Add(1)
		go ping(uri, cnt)
	} else if "pong" == cmd {
		mainWG.Add(1)
		go pong(uri, cnt)
	} else if "iping" == cmd {
		mainWG.Add(1)
		go iping(uri, cnt)
	} else if "ipong" == cmd {
		mainWG.Add(1)
		go ipong(uri, cnt)
	}

	mainWG.Wait()
}
<|endoftext|>