<commit_before>package main

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

	"github.com/cihangir/gene/example/tinder/workers/account"
	"github.com/cihangir/gene/example/tinder/workers/kitworker"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"

	"github.com/go-kit/kit/loadbalancer"
	"github.com/go-kit/kit/loadbalancer/static"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/metrics"
	kitprometheus "github.com/go-kit/kit/metrics/prometheus"
	"github.com/go-kit/kit/tracing/zipkin"
)

func main() {
	var (
		listen = flag.String("listen", ":8080", "HTTP listen address")
	)
	flag.Parse()

	logger := log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("listen", *listen).With("caller", log.DefaultCaller)

	transportLogger := log.NewContext(logger).With("transport", "HTTP/JSON")
	tracingLogger := log.NewContext(transportLogger).With("component", "tracing")
	zipkinLogger := log.NewContext(tracingLogger).With("component", "zipkin")

	ctx := context.Background()

	zipkinCollectorAddr := ":5000"
	zipkinCollectorTimeout := time.Second

	zipkinCollectorBatchSize := 10
	zipkinCollectorBatchInterval := time.Second

	var collector zipkin.Collector
	collector = loggingCollector{zipkinLogger}

	{

		var err error
		if collector, err = zipkin.NewScribeCollector(
			zipkinCollectorAddr,
			zipkinCollectorTimeout,
			zipkin.ScribeBatchSize(zipkinCollectorBatchSize),
			zipkin.ScribeBatchInterval(zipkinCollectorBatchInterval),
			zipkin.ScribeLogger(zipkinLogger),
		); err != nil {
			_ = zipkinLogger.Log("err", err)
		}
	}

	fieldKeys := []string{"method", "error"}
	requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{
		Namespace: "tinder_api",
		Subsystem: "account_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)

	requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "tinder_api",
		Subsystem: "account_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys))

	serverOpts := &kitworker.ServerOption{
		Host:            "localhost:3000",
		ZipkinCollector: collector,

		LogErrors:   true,
		LogRequests: true,

		Latency: requestLatency,
		Counter: requestCount,
	}

	profileApiEndpoints := []string{
		"profile1.tinder_api.tinder.com",
		"profile2.tinder_api.tinder.com",
	}

	lbCreator := func(factory loadbalancer.Factory) loadbalancer.LoadBalancer {
		publisher := static.NewPublisher(
			profileApiEndpoints,
			factory,
			logger,
		)

		return loadbalancer.NewRoundRobin(publisher)
	}

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

	clientOpts := &kitworker.ClientOption{
		Host:                hostName + ":" + *listen,
		ZipkinCollector:     collector,
		QPS:                 100,
		LoadBalancerCreator: lbCreator,
	}

	profileService := account.NewAccountClient(
		clientOpts,
		logger,
	)

	ctx = context.WithValue(ctx, "profileService", profileService)

	var svc account.AccountService
	svc = account.NewAccount()

	http.Handle(account.NewByIDsHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewCreateHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewDeleteHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewOneHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewUpdateHandler(ctx, svc, serverOpts, logger))
	http.Handle("/metrics", stdprometheus.Handler())

	_ = logger.Log("msg", "HTTP", "addr", *listen)
	_ = logger.Log("err", http.ListenAndServe(*listen, nil))
}

type loggingCollector struct{ log.Logger }

func (c loggingCollector) Collect(s *zipkin.Span) error {
	annotations := s.Encode().GetAnnotations()
	values := make([]string, len(annotations))
	for i, a := range annotations {
		values[i] = a.Value
	}
	_ = c.Logger.Log(
		"trace_id", s.TraceID(),
		"span_id", s.SpanID(),
		"parent_span_id", s.ParentSpanID(),
		"annotations", strings.Join(values, " "),
	)
	return nil
}
<commit_msg>example: fix service name<commit_after>package main

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

	"github.com/cihangir/gene/example/tinder/workers/account"
	"github.com/cihangir/gene/example/tinder/workers/kitworker"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
	"golang.org/x/net/context"

	"github.com/go-kit/kit/loadbalancer"
	"github.com/go-kit/kit/loadbalancer/static"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/metrics"
	kitprometheus "github.com/go-kit/kit/metrics/prometheus"
	"github.com/go-kit/kit/tracing/zipkin"
)

func main() {
	var (
		listen = flag.String("listen", ":8080", "HTTP listen address")
	)
	flag.Parse()

	logger := log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("listen", *listen).With("caller", log.DefaultCaller)

	transportLogger := log.NewContext(logger).With("transport", "HTTP/JSON")
	tracingLogger := log.NewContext(transportLogger).With("component", "tracing")
	zipkinLogger := log.NewContext(tracingLogger).With("component", "zipkin")

	ctx := context.Background()

	zipkinCollectorAddr := ":5000"
	zipkinCollectorTimeout := time.Second

	zipkinCollectorBatchSize := 10
	zipkinCollectorBatchInterval := time.Second

	var collector zipkin.Collector
	collector = loggingCollector{zipkinLogger}

	{

		var err error
		if collector, err = zipkin.NewScribeCollector(
			zipkinCollectorAddr,
			zipkinCollectorTimeout,
			zipkin.ScribeBatchSize(zipkinCollectorBatchSize),
			zipkin.ScribeBatchInterval(zipkinCollectorBatchInterval),
			zipkin.ScribeLogger(zipkinLogger),
		); err != nil {
			_ = zipkinLogger.Log("err", err)
		}
	}

	fieldKeys := []string{"method", "error"}
	requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{
		Namespace: "tinder_api",
		Subsystem: "account_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)

	requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "tinder_api",
		Subsystem: "account_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys))

	serverOpts := &kitworker.ServerOption{
		Host:            "localhost:3000",
		ZipkinCollector: collector,

		LogErrors:   true,
		LogRequests: true,

		Latency: requestLatency,
		Counter: requestCount,
	}

	profileApiEndpoints := []string{
		"profile1.tinder_api.tinder.com",
		"profile2.tinder_api.tinder.com",
	}

	lbCreator := func(factory loadbalancer.Factory) loadbalancer.LoadBalancer {
		publisher := static.NewPublisher(
			profileApiEndpoints,
			factory,
			logger,
		)

		return loadbalancer.NewRoundRobin(publisher)
	}

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

	clientOpts := &kitworker.ClientOption{
		Host:                hostName + ":" + *listen,
		ZipkinCollector:     collector,
		QPS:                 100,
		LoadBalancerCreator: lbCreator,
	}

	profileService := account.NewAccountClient(
		clientOpts,
		logger,
	)

	ctx = context.WithValue(ctx, "accountService", profileService)

	var svc account.AccountService
	svc = account.NewAccount()

	http.Handle(account.NewByIDsHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewCreateHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewDeleteHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewOneHandler(ctx, svc, serverOpts, logger))
	http.Handle(account.NewUpdateHandler(ctx, svc, serverOpts, logger))
	http.Handle("/metrics", stdprometheus.Handler())

	_ = logger.Log("msg", "HTTP", "addr", *listen)
	_ = logger.Log("err", http.ListenAndServe(*listen, nil))
}

type loggingCollector struct{ log.Logger }

func (c loggingCollector) Collect(s *zipkin.Span) error {
	annotations := s.Encode().GetAnnotations()
	values := make([]string, len(annotations))
	for i, a := range annotations {
		values[i] = a.Value
	}
	_ = c.Logger.Log(
		"trace_id", s.TraceID(),
		"span_id", s.SpanID(),
		"parent_span_id", s.ParentSpanID(),
		"annotations", strings.Join(values, " "),
	)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/foize/go.sgr"
	"github.com/howeyc/fsnotify"
	"go/build"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

var (
	wd string // working directory

	pkg *build.Package

	monAngo *exec.Cmd // command builds ango on file change (uses gomon)

	// watcher on the ango binary
	watcher *fsnotify.Watcher

	// closed on stop
	stopCh = make(chan bool)
	stopWg sync.WaitGroup
)

const exampleAngoFile = "example/chatService.ango"

type CheckWriter struct {
	wr     io.Writer
	filter string
	action func()
}

func (c *CheckWriter) Write(b []byte) (n int, err error) {
	n, err = c.wr.Write(b)
	if strings.Contains(string(b), c.filter) {
		c.action()
	}
	return n, err
}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var err error
	fmt.Println("Starting ango dev tool.")

	wd, err = os.Getwd()
	if err != nil {
		fmt.Printf("Error getting wd: %s\n", err)
		stop(1)
		select {}
	}

	pkg, err = build.ImportDir(wd, 0)
	if err != nil {
		fmt.Printf("Error loading package: %s\n", err)
		stop(1)
		select {}
	}

	if pkg.Name != "main" || !pkg.IsCommand() || filepath.Base(wd) != "ango" {
		fmt.Println("Is tool executed from the right directory? (github.com/GeertJohan/ango or a fork)?")
		fmt.Printf("Current package (%s) is invalid.\n", pkg.Name)
		stop(1)
		select {}
	}

	go rerunExample()

	go rerunAngo()

	go watchExampleAngo()

	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, os.Kill, os.Interrupt)
	sig := <-sigChan
	signal.Stop(sigChan)

	fmt.Printf("Received %s, closing...\n", sig)
	if sig == os.Interrupt {
		stop(0)
	} else {
		stop(1)
	}
	select {}
}

func stop(exitCode int) {
	go func() {
		// synced stop
		close(stopCh)
		stopWg.Wait()

		// os.Exit(..)
		os.Exit(exitCode)
	}()
}

func rerunExample() {
	stopWg.Add(1)
	defer stopWg.Done()

	cmdRerun := exec.Command("rerun", filepath.Join(pkg.ImportPath, "example"))
	cmdRerun.Stdin = os.Stdin
	cmdRerun.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgYellow, false)
	cmdRerun.Stderr = sgr.NewColorWriter(os.Stderr, sgr.FgYellow, false)
	err := cmdRerun.Start()
	if err != nil {
		fmt.Printf("Error running rerun example: %s\n", err)
		stop(1)
		return
	}
	<-stopCh
	if cmdRerun.Process != nil {
		cmdRerun.Process.Signal(os.Interrupt)
	}
	err = cmdRerun.Wait()
	if err != nil && err.Error() != "exit status 2" {
		fmt.Printf("Error stopping rerun example: %s\n", err)
		return
	}
}

func rerunAngo() {
	stopWg.Add(1)
	defer stopWg.Done()

	cmdRerun := exec.Command("rerun", "-build-only", pkg.ImportPath)
	cmdRerun.Stdin = os.Stdin
	cw := &CheckWriter{
		wr:     os.Stderr,
		filter: "build passed",
		action: func() {
			angoExample()
		},
	}
	cmdRerun.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgCyan, false)
	cmdRerun.Stderr = sgr.NewColorWriter(cw, sgr.FgCyan, false)
	err := cmdRerun.Start()
	if err != nil {
		fmt.Printf("Error running rerun ango build: %s\n", err)
		stop(1)
		return
	}
	<-stopCh
	if cmdRerun.Process != nil {
		cmdRerun.Process.Signal(os.Interrupt)
	}
	err = cmdRerun.Wait()
	if err != nil && err.Error() != "exit status 2" {
		fmt.Printf("Error stopping rerun ango build: %s\n", err)
		return
	}
}

func watchExampleAngo() {
	stopWg.Add(1)
	defer stopWg.Done()

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		fmt.Printf("Error starting watcher: %s\n", err)
		stop(1)
		return
	}
	defer watcher.Close()
	err = watcher.WatchFlags(exampleAngoFile, fsnotify.FSN_MODIFY)
	if err != nil {
		fmt.Printf("Error starting watch on example ango file: %s\n", err)
		stop(1)
		return
	}
	for {
		select {
		case <-stopCh:
			return
		case <-watcher.Event:
			angoExample()
		case err := <-watcher.Error:
			if err != nil {
				fmt.Printf("Error watching example ango file: %s\n", err)
				stop(1)
				return
			}
		}
	}
}

func angoExample() {
	stopWg.Add(1)
	defer stopWg.Done()
	fmt.Println("Running ango tool for example/chatService.ango")
	cmdAngoExample := exec.Command(filepath.Join(wd, "ango"), "--verbose", "-i", exampleAngoFile, "--js", "example/http-files", "--force-overwrite") // "--go", "example",
	cmdAngoExample.Stdin = os.Stdin
	cmdAngoExample.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgBlue, false)
	cmdAngoExample.Stderr = sgr.NewColorWriter(os.Stderr, sgr.FgBlue, false)
	err := cmdAngoExample.Run()
	if err != nil {
		fmt.Printf("Error running ango tool: %s\n", err)
	}
}
<commit_msg>Update devtool to ignore false positive changes on modified files<commit_after>package main

import (
	"fmt"
	"github.com/foize/go.sgr"
	"github.com/howeyc/fsnotify"
	"go/build"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"
)

var (
	wd string // working directory

	pkg *build.Package

	monAngo *exec.Cmd // command builds ango on file change (uses gomon)

	// watcher on the ango binary
	watcher *fsnotify.Watcher

	// closed on stop
	stopCh = make(chan bool)
	stopWg sync.WaitGroup
)

const exampleAngoFile = "example/chatService.ango"

type CheckWriter struct {
	wr     io.Writer
	filter string
	action func()
}

func (c *CheckWriter) Write(b []byte) (n int, err error) {
	n, err = c.wr.Write(b)
	if strings.Contains(string(b), c.filter) {
		c.action()
	}
	return n, err
}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var err error
	fmt.Println("Starting ango dev tool.")

	wd, err = os.Getwd()
	if err != nil {
		fmt.Printf("Error getting wd: %s\n", err)
		stop(1)
		select {}
	}

	pkg, err = build.ImportDir(wd, 0)
	if err != nil {
		fmt.Printf("Error loading package: %s\n", err)
		stop(1)
		select {}
	}

	if pkg.Name != "main" || !pkg.IsCommand() || filepath.Base(wd) != "ango" {
		fmt.Println("Is tool executed from the right directory? (github.com/GeertJohan/ango or a fork)?")
		fmt.Printf("Current package (%s) is invalid.\n", pkg.Name)
		stop(1)
		select {}
	}

	go rerunExample()

	go rerunAngo()

	go watchExampleAngo()

	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, os.Kill, os.Interrupt)
	sig := <-sigChan
	signal.Stop(sigChan)

	fmt.Printf("Received %s, closing...\n", sig)
	if sig == os.Interrupt {
		stop(0)
	} else {
		stop(1)
	}
	select {}
}

func stop(exitCode int) {
	go func() {
		// synced stop
		close(stopCh)
		stopWg.Wait()

		// os.Exit(..)
		os.Exit(exitCode)
	}()
}

func rerunExample() {
	stopWg.Add(1)
	defer stopWg.Done()

	cmdRerun := exec.Command("rerun", filepath.Join(pkg.ImportPath, "example"))
	cmdRerun.Stdin = os.Stdin
	cmdRerun.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgYellow, false)
	cmdRerun.Stderr = sgr.NewColorWriter(os.Stderr, sgr.FgYellow, false)
	err := cmdRerun.Start()
	if err != nil {
		fmt.Printf("Error running rerun example: %s\n", err)
		stop(1)
		return
	}
	<-stopCh
	if cmdRerun.Process != nil {
		cmdRerun.Process.Signal(os.Interrupt)
	}
	err = cmdRerun.Wait()
	if err != nil && err.Error() != "exit status 2" {
		fmt.Printf("Error stopping rerun example: %s\n", err)
		return
	}
}

func rerunAngo() {
	stopWg.Add(1)
	defer stopWg.Done()

	cmdRerun := exec.Command("rerun", "-build-only", pkg.ImportPath)
	cmdRerun.Stdin = os.Stdin
	cw := &CheckWriter{
		wr:     os.Stderr,
		filter: "build passed",
		action: func() {
			angoExample()
		},
	}
	cmdRerun.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgCyan, false)
	cmdRerun.Stderr = sgr.NewColorWriter(cw, sgr.FgCyan, false)
	err := cmdRerun.Start()
	if err != nil {
		fmt.Printf("Error running rerun ango build: %s\n", err)
		stop(1)
		return
	}
	<-stopCh
	if cmdRerun.Process != nil {
		cmdRerun.Process.Signal(os.Interrupt)
	}
	err = cmdRerun.Wait()
	if err != nil && err.Error() != "exit status 2" {
		fmt.Printf("Error stopping rerun ango build: %s\n", err)
		return
	}
}

func watchExampleAngo() {
	stopWg.Add(1)
	defer stopWg.Done()

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		fmt.Printf("Error starting watcher: %s\n", err)
		stop(1)
		return
	}
	defer watcher.Close()
	err = watcher.WatchFlags(exampleAngoFile, fsnotify.FSN_MODIFY)
	if err != nil {
		fmt.Printf("Error starting watch on example ango file: %s\n", err)
		stop(1)
		return
	}
	err = watcher.WatchFlags(`templates/ango-service.tmpl.go`, fsnotify.FSN_MODIFY)
	if err != nil {
		fmt.Printf("Error starting watch on go template file: %s\n", err)
		stop(1)
		return
	}
	err = watcher.WatchFlags(`templates/ango-service.tmpl.js`, fsnotify.FSN_MODIFY)
	if err != nil {
		fmt.Printf("Error starting watch on js template file: %s\n", err)
		stop(1)
		return
	}
	for {
		select {
		case <-stopCh:
			return
		case <-watcher.Event:
			// short timeout consuming another event becuase sublime sometimes saves (modifies) the file twice
			select {
			case <-time.After(100 * time.Millisecond):
			case <-watcher.Event:
			}
			angoExample()
			// short timeout consuming another event because somehow ango modifies the template files!?!?!?!?
			select {
			case <-time.After(100 * time.Millisecond):
			case <-watcher.Event:
			}
		case err := <-watcher.Error:
			if err != nil {
				fmt.Printf("Error watching example ango file: %s\n", err)
				stop(1)
				return
			}
		}
	}
}

func angoExample() {
	stopWg.Add(1)
	defer stopWg.Done()
	fmt.Println("Running ango tool for example/chatService.ango")
	cmdAngoExample := exec.Command(filepath.Join(wd, "ango"), "--verbose", "-i", exampleAngoFile, "--js", "example/http-files", "--force-overwrite") // "--go", "example",
	cmdAngoExample.Stdin = os.Stdin
	cmdAngoExample.Stdout = sgr.NewColorWriter(os.Stdout, sgr.FgBlue, false)
	cmdAngoExample.Stderr = sgr.NewColorWriter(os.Stderr, sgr.FgBlue, false)
	err := cmdAngoExample.Run()
	if err != nil {
		fmt.Printf("Error running ango tool: %s\n", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// The resource package provides the functionality of the "resources"
// feature in Juju.
package resource

import (
	"fmt"
	"reflect"
	"time"

	"github.com/juju/errors"
	"github.com/juju/names"
	"gopkg.in/juju/charm.v6-unstable/resource"
)

// Resource defines a single resource within a Juju model.
//
// Each service will have have exactly the same resources associated
// with it as are defined in the charm's metadata, no more, no less.
// When associated with the service the resource may have additional
// information associated with it.
//
// A resource may be a "placeholder", meaning it is only partially
// populated before an upload (whether local or from the charm store).
// In that case the following fields are not set:
//
//   Timestamp
//   Username
//
// For "upload" placeholders, the following additional fields are
// not set:
//
//   Fingerprint
//   Size
//
// A resource may also be added to the model as "pending", meaning it
// is queued up to be used as a resource for the service. Until it is
// "activated", a pending resources is virtually invisible. There may
// be more that one pending resource for a given resource ID.
type Resource struct {
	resource.Resource

	// ID uniquely identifies a resource-service pair within the model.
	// Note that the model ignores pending resources (those with a
	// pending ID) except for in a few clearly pending-related places.
	// ID may be empty if the ID (assigned by the model) is not known.
	ID string

	// PendingID identifies that this resource is pending and
	// distinguishes it from other pending resources with the same model
	// ID (and from the active resource). The active resource for the
	// services will not have PendingID set.
	PendingID string

	// TODO(ericsnow) Use names.ServiceTag for ServiceID?

	// ServiceID identifies the service for the resource.
	ServiceID string

	// TODO(ericsnow) Use names.UserTag for Username?

	// Username is the ID of the user that added the revision
	// to the model (whether implicitly or explicitly).
	Username string

	// Timestamp indicates when the resource was added to the model.
	Timestamp time.Time
}

// Validate ensures that the spec is valid.
func (res Resource) Validate() error {
	// TODO(ericsnow) Ensure that the "placeholder" fields are not set
	// if IsLocalPlaceholder() returns true (and that they *are* set
	// otherwise)? Also ensure an "upload" origin in the "placeholder"
	// case?

	if err := res.Resource.Validate(); err != nil {
		return errors.Annotate(err, "bad info")
	}

	if res.ServiceID == "" {
		return errors.NewNotValid(nil, "missing service ID")
	}

	// TODO(ericsnow) Require that Username be set if timestamp is?

	if res.Timestamp.IsZero() && res.Username != "" {
		return errors.NewNotValid(nil, "missing timestamp")
	}

	return nil
}

// IsPlaceholder indicates whether or not the resource is a
// "placeholder" (partially populated pending an upload).
func (res Resource) IsPlaceholder() bool {
	return res.Timestamp.IsZero()
}

// TimestampGranular returns the timestamp at a resolution of 1 second.
func (res Resource) TimestampGranular() time.Time {
	return time.Unix(res.Timestamp.Unix(), 0)
}

// RevisionString returns the human-readable revision for the resource.
func (res Resource) RevisionString() string {
	switch res.Origin {
	case resource.OriginUpload:
		if res.IsPlaceholder() {
			return "-"
		}
		return res.TimestampGranular().UTC().String()
	case resource.OriginStore:
		return fmt.Sprintf("%d", res.Revision)
	default:
		// note: this should probably never happen.
		return "-"
	}
}

// ServiceResources contains the list of resources for the service and all its
// units.
type ServiceResources struct {
	// Resources are the current version of the resource for the service that
	// resource-get will retrieve.
	Resources []Resource

	// CharmStoreResources provides the resource info from the charm
	// store for each of the service's resources. The information from
	// the charm store is current as of the last time the charm store
	// was polled. Each entry here corresponds to the same indexed entry
	// in the Resources field.
	CharmStoreResources []resource.Resource

	// UnitResources reports the currenly-in-use version of resources for each
	// unit.
	UnitResources []UnitResources
}

// Outdated returns the list of names for the service's resources which
// do not match the ones in the charm store.
func (sr ServiceResources) Outdated() []string {
	var outdated []string
	for i, res := range sr.Resources {
		if res.Origin != resource.OriginStore {
			continue
		}
		csRes := sr.CharmStoreResources[i]
		if reflect.DeepEqual(res.Resource, csRes) {
			continue
		}
		outdated = append(outdated, res.Name)
	}
	return outdated
}

// UnitResources conains the list of resources used by a unit.
type UnitResources struct {
	// Tag is the tag of the unit.
	Tag names.UnitTag

	// Resources are the resource versions currently in use by this unit.
	Resources []Resource
}
<commit_msg>Only compare the revisions in Outdated().<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// The resource package provides the functionality of the "resources"
// feature in Juju.
package resource

import (
	"fmt"
	"time"

	"github.com/juju/errors"
	"github.com/juju/names"
	"gopkg.in/juju/charm.v6-unstable/resource"
)

// Resource defines a single resource within a Juju model.
//
// Each service will have have exactly the same resources associated
// with it as are defined in the charm's metadata, no more, no less.
// When associated with the service the resource may have additional
// information associated with it.
//
// A resource may be a "placeholder", meaning it is only partially
// populated before an upload (whether local or from the charm store).
// In that case the following fields are not set:
//
//   Timestamp
//   Username
//
// For "upload" placeholders, the following additional fields are
// not set:
//
//   Fingerprint
//   Size
//
// A resource may also be added to the model as "pending", meaning it
// is queued up to be used as a resource for the service. Until it is
// "activated", a pending resources is virtually invisible. There may
// be more that one pending resource for a given resource ID.
type Resource struct {
	resource.Resource

	// ID uniquely identifies a resource-service pair within the model.
	// Note that the model ignores pending resources (those with a
	// pending ID) except for in a few clearly pending-related places.
	// ID may be empty if the ID (assigned by the model) is not known.
	ID string

	// PendingID identifies that this resource is pending and
	// distinguishes it from other pending resources with the same model
	// ID (and from the active resource). The active resource for the
	// services will not have PendingID set.
	PendingID string

	// TODO(ericsnow) Use names.ServiceTag for ServiceID?

	// ServiceID identifies the service for the resource.
	ServiceID string

	// TODO(ericsnow) Use names.UserTag for Username?

	// Username is the ID of the user that added the revision
	// to the model (whether implicitly or explicitly).
	Username string

	// Timestamp indicates when the resource was added to the model.
	Timestamp time.Time
}

// Validate ensures that the spec is valid.
func (res Resource) Validate() error {
	// TODO(ericsnow) Ensure that the "placeholder" fields are not set
	// if IsLocalPlaceholder() returns true (and that they *are* set
	// otherwise)? Also ensure an "upload" origin in the "placeholder"
	// case?

	if err := res.Resource.Validate(); err != nil {
		return errors.Annotate(err, "bad info")
	}

	if res.ServiceID == "" {
		return errors.NewNotValid(nil, "missing service ID")
	}

	// TODO(ericsnow) Require that Username be set if timestamp is?

	if res.Timestamp.IsZero() && res.Username != "" {
		return errors.NewNotValid(nil, "missing timestamp")
	}

	return nil
}

// IsPlaceholder indicates whether or not the resource is a
// "placeholder" (partially populated pending an upload).
func (res Resource) IsPlaceholder() bool {
	return res.Timestamp.IsZero()
}

// TimestampGranular returns the timestamp at a resolution of 1 second.
func (res Resource) TimestampGranular() time.Time {
	return time.Unix(res.Timestamp.Unix(), 0)
}

// RevisionString returns the human-readable revision for the resource.
func (res Resource) RevisionString() string {
	switch res.Origin {
	case resource.OriginUpload:
		if res.IsPlaceholder() {
			return "-"
		}
		return res.TimestampGranular().UTC().String()
	case resource.OriginStore:
		return fmt.Sprintf("%d", res.Revision)
	default:
		// note: this should probably never happen.
		return "-"
	}
}

// ServiceResources contains the list of resources for the service and all its
// units.
type ServiceResources struct {
	// Resources are the current version of the resource for the service that
	// resource-get will retrieve.
	Resources []Resource

	// CharmStoreResources provides the resource info from the charm
	// store for each of the service's resources. The information from
	// the charm store is current as of the last time the charm store
	// was polled. Each entry here corresponds to the same indexed entry
	// in the Resources field.
	CharmStoreResources []resource.Resource

	// UnitResources reports the currenly-in-use version of resources for each
	// unit.
	UnitResources []UnitResources
}

// Outdated returns the list of names for the service's resources which
// do not match the ones in the charm store.
func (sr ServiceResources) Outdated() []string {
	var outdated []string
	for i, res := range sr.Resources {
		if res.Origin != resource.OriginStore {
			continue
		}
		csRes := sr.CharmStoreResources[i]
		// If the revision is the same then all the other info must be.
		if res.Revision == csRes.Revision {
			continue
		}
		outdated = append(outdated, res.Name)
	}
	return outdated
}

// UnitResources conains the list of resources used by a unit.
type UnitResources struct {
	// Tag is the tag of the unit.
	Tag names.UnitTag

	// Resources are the resource versions currently in use by this unit.
	Resources []Resource
}
<|endoftext|>


<commit_before>package bolt

import (
	"context"
	"fmt"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure OrganizationsStore implements chronograf.OrganizationsStore.
var _ chronograf.OrganizationsStore = &OrganizationsStore{}

// OrganizationsStore is used to store organizations local to chronograf
var OrganizationsBucket = []byte("OrganizationsV1")

// OrganizationsStore uses bolt to store and retrieve Organizations
type OrganizationsStore struct {
	client *Client
}

func (s *OrganizationsStore) Migrate(ctx context.Context) error {
	o := chronograf.Organization{
		ID:   0,
		Name: "__default",
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(OrganizationsBucket)
		if v, err := internal.MarshalOrganization(&o); err != nil {
			return err
		} else if err := b.Put(u64tob(o.ID), v); err != nil {
			return err
		}

		return nil
	})
}

func (s *OrganizationsStore) Add(ctx context.Context, o *chronograf.Organization) (*chronograf.Organization, error) {
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(OrganizationsBucket)
		seq, err := b.NextSequence()
		if err != nil {
			return err
		}
		o.ID = seq
		if v, err := internal.MarshalOrganization(o); err != nil {
			return err
		} else if err := b.Put(u64tob(seq), v); err != nil {
			return err
		}

		return nil
	}); err != nil {
		return nil, err
	}

	return o, nil
}

func (s *OrganizationsStore) All(ctx context.Context) ([]chronograf.Organization, error) {
	var orgs []chronograf.Organization
	err := s.each(ctx, func(o *chronograf.Organization) {
		orgs = append(orgs, *o)
	})

	if err != nil {
		return nil, err
	}

	return orgs, nil
}

func (s *OrganizationsStore) Delete(ctx context.Context, o *chronograf.Organization) error {
	_, err := s.get(ctx, o.ID)
	if err != nil {
		return err
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket(OrganizationsBucket).Delete(u64tob(o.ID))
	})
}

func (s *OrganizationsStore) get(ctx context.Context, id uint64) (*chronograf.Organization, error) {
	var o chronograf.Organization
	err := s.client.db.View(func(tx *bolt.Tx) error {
		v := tx.Bucket(OrganizationsBucket).Get(u64tob(id))
		if v == nil {
			return chronograf.ErrOrganizationNotFound
		}
		return internal.UnmarshalOrganization(v, &o)
	})

	if err != nil {
		return nil, err
	}

	return &o, nil
}

func (s *OrganizationsStore) each(ctx context.Context, fn func(*chronograf.Organization)) error {
	return s.client.db.View(func(tx *bolt.Tx) error {
		return tx.Bucket(OrganizationsBucket).ForEach(func(k, v []byte) error {
			var org chronograf.Organization
			if err := internal.UnmarshalOrganization(v, &org); err != nil {
				return err
			}
			fn(&org)
			return nil
		})
	})
	return nil
}

func (s *OrganizationsStore) Get(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
	if q.ID != nil {
		return s.get(ctx, *q.ID)
	}

	if q.Name != nil {
		var org *chronograf.Organization
		err := s.each(ctx, func(o *chronograf.Organization) {
			if org != nil {
				return
			}

			if o.Name == *q.Name {
				org = o
			}
		})

		if err != nil {
			return nil, err
		}

		if org == nil {
			return nil, chronograf.ErrOrganizationNotFound
		}

		return org, nil
	}
	return nil, fmt.Errorf("must specify either ID, or Name in OrganizationQuery")
}

func (s *OrganizationsStore) Update(ctx context.Context, o *chronograf.Organization) error {
	org, err := s.get(ctx, o.ID)
	if err != nil {
		return err
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		org.Name = o.Name
		if v, err := internal.MarshalOrganization(org); err != nil {
			return err
		} else if err := tx.Bucket(OrganizationsBucket).Put(u64tob(org.ID), v); err != nil {
			return err
		}
		return nil
	})
}
<commit_msg>Fix Migrate Organizations to not overwrite name<commit_after>package bolt

import (
	"context"
	"fmt"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure OrganizationsStore implements chronograf.OrganizationsStore.
var _ chronograf.OrganizationsStore = &OrganizationsStore{}

// OrganizationsStore is used to store organizations local to chronograf
var OrganizationsBucket = []byte("OrganizationsV1")

// OrganizationsStore uses bolt to store and retrieve Organizations
type OrganizationsStore struct {
	client *Client
}

// Migrate sets the default organization at runtime
func (s *OrganizationsStore) Migrate(ctx context.Context) error {
	o := chronograf.Organization{
		ID:   0,
		Name: "__default",
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(OrganizationsBucket)
		v := b.Get(u64tob(o.ID))
		if v != nil {
			return nil
		}
		if v, err := internal.MarshalOrganization(&o); err != nil {
			return err
		} else if err := b.Put(u64tob(o.ID), v); err != nil {
			return err
		}

		return nil
	})
}

func (s *OrganizationsStore) Add(ctx context.Context, o *chronograf.Organization) (*chronograf.Organization, error) {
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(OrganizationsBucket)
		seq, err := b.NextSequence()
		if err != nil {
			return err
		}
		o.ID = seq
		if v, err := internal.MarshalOrganization(o); err != nil {
			return err
		} else if err := b.Put(u64tob(seq), v); err != nil {
			return err
		}

		return nil
	}); err != nil {
		return nil, err
	}

	return o, nil
}

func (s *OrganizationsStore) All(ctx context.Context) ([]chronograf.Organization, error) {
	var orgs []chronograf.Organization
	err := s.each(ctx, func(o *chronograf.Organization) {
		orgs = append(orgs, *o)
	})

	if err != nil {
		return nil, err
	}

	return orgs, nil
}

func (s *OrganizationsStore) Delete(ctx context.Context, o *chronograf.Organization) error {
	_, err := s.get(ctx, o.ID)
	if err != nil {
		return err
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket(OrganizationsBucket).Delete(u64tob(o.ID))
	})
}

func (s *OrganizationsStore) get(ctx context.Context, id uint64) (*chronograf.Organization, error) {
	var o chronograf.Organization
	err := s.client.db.View(func(tx *bolt.Tx) error {
		v := tx.Bucket(OrganizationsBucket).Get(u64tob(id))
		if v == nil {
			return chronograf.ErrOrganizationNotFound
		}
		return internal.UnmarshalOrganization(v, &o)
	})

	if err != nil {
		return nil, err
	}

	return &o, nil
}

func (s *OrganizationsStore) each(ctx context.Context, fn func(*chronograf.Organization)) error {
	return s.client.db.View(func(tx *bolt.Tx) error {
		return tx.Bucket(OrganizationsBucket).ForEach(func(k, v []byte) error {
			var org chronograf.Organization
			if err := internal.UnmarshalOrganization(v, &org); err != nil {
				return err
			}
			fn(&org)
			return nil
		})
	})
	return nil
}

func (s *OrganizationsStore) Get(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
	if q.ID != nil {
		return s.get(ctx, *q.ID)
	}

	if q.Name != nil {
		var org *chronograf.Organization
		err := s.each(ctx, func(o *chronograf.Organization) {
			if org != nil {
				return
			}

			if o.Name == *q.Name {
				org = o
			}
		})

		if err != nil {
			return nil, err
		}

		if org == nil {
			return nil, chronograf.ErrOrganizationNotFound
		}

		return org, nil
	}
	return nil, fmt.Errorf("must specify either ID, or Name in OrganizationQuery")
}

func (s *OrganizationsStore) Update(ctx context.Context, o *chronograf.Organization) error {
	org, err := s.get(ctx, o.ID)
	if err != nil {
		return err
	}
	return s.client.db.Update(func(tx *bolt.Tx) error {
		org.Name = o.Name
		if v, err := internal.MarshalOrganization(org); err != nil {
			return err
		} else if err := tx.Bucket(OrganizationsBucket).Put(u64tob(org.ID), v); err != nil {
			return err
		}
		return nil
	})
}
<|endoftext|>


<commit_before>package torrent

import (
	"math"
)

// Stats contains statistics about Torrent.
type Stats struct {
	// Status of the torrent.
	Status Status

	// Bytes that are downloaded and passed hash check.
	BytesComplete int64

	// BytesLeft is the number of bytes that is needed to complete all missing pieces.
	BytesIncomplete int64

	// BytesTotal is the number of total bytes of files in torrent.
	//
	// BytesTotal = BytesComplete + BytesIncomplete
	BytesTotal int64

	// BytesDownloaded is the number of bytes downloaded from swarm.
	// Because some pieces may be downloaded more than once, this number may be greater than BytesCompleted returns.
	// TODO BytesDownloaded int64

	// BytesUploaded is the number of bytes uploaded to the swarm.
	// TODO BytesUploaded   int64

	// Number of peers that are connected, handshaked and ready to send and receive messages.
	// ConnectedPeers = IncomingPeers + OutgoingPeers
	ConnectedPeers int

	// Number of peers that have connected to us.
	IncomingPeers int

	// Number of peers that we have connected to.
	OutgoingPeers int

	// Number of active piece downloads.
	ActiveDownloads int

	// Number of peers that uploading too slow.
	SnubbedDownloads int

	// Number of active piece downloads in choked state.
	ChokedDownloads int

	// Number of active metadata downloads.
	ActiveMetadataDownloads int

	// Number of peer addresses that are ready to be connected.
	ReadyPeerAddresses int

	// Number of incoming peers in handshake state.
	IncomingHandshakes int

	// Number of outgoing peers in handshake state.
	OutgoingHandshakes int
}

func (t *Torrent) stats() Stats {
	stats := Stats{
		Status:                  t.status(),
		ConnectedPeers:          len(t.peers),
		IncomingPeers:           len(t.incomingPeers),
		OutgoingPeers:           len(t.outgoingPeers),
		ActiveDownloads:         len(t.pieceDownloaders),
		ActiveMetadataDownloads: len(t.infoDownloaders),
		SnubbedDownloads:        len(t.snubbedDownloaders),
		ChokedDownloads:         len(t.chokedDownloaders),
		ReadyPeerAddresses:      t.addrList.Len(),
		IncomingHandshakes:      len(t.incomingHandshakers),
		OutgoingHandshakes:      len(t.outgoingHandshakers),
	}
	if t.info != nil {
		stats.BytesTotal = t.info.TotalLength
		stats.BytesComplete = t.bytesComplete()
		stats.BytesIncomplete = stats.BytesTotal - stats.BytesComplete
	} else {
		// Some trackers don't send any peer address if don't tell we have missing bytes.
		stats.BytesIncomplete = math.MaxUint32
	}
	return stats
}

func (t *Torrent) bytesComplete() int64 {
	if t.bitfield == nil {
		return 0
	}
	n := int64(t.info.PieceLength) * int64(t.bitfield.Count())
	if t.bitfield.Test(t.bitfield.Len() - 1) {
		n -= int64(t.info.PieceLength)
		n += int64(t.pieces[t.bitfield.Len()-1].Length)
	}
	return n
}
<commit_msg>show running downloads count<commit_after>package torrent

import (
	"math"
)

// Stats contains statistics about Torrent.
type Stats struct {
	// Status of the torrent.
	Status Status

	// Bytes that are downloaded and passed hash check.
	BytesComplete int64

	// BytesLeft is the number of bytes that is needed to complete all missing pieces.
	BytesIncomplete int64

	// BytesTotal is the number of total bytes of files in torrent.
	//
	// BytesTotal = BytesComplete + BytesIncomplete
	BytesTotal int64

	// BytesDownloaded is the number of bytes downloaded from swarm.
	// Because some pieces may be downloaded more than once, this number may be greater than BytesCompleted returns.
	// TODO BytesDownloaded int64

	// BytesUploaded is the number of bytes uploaded to the swarm.
	// TODO BytesUploaded   int64

	// Number of peers that are connected, handshaked and ready to send and receive messages.
	// ConnectedPeers = IncomingPeers + OutgoingPeers
	ConnectedPeers int

	// Number of peers that have connected to us.
	IncomingPeers int

	// Number of peers that we have connected to.
	OutgoingPeers int

	// Number of active piece downloads.
	ActiveDownloads int

	// Number of pieces that are being downloaded normally.
	RunningDownloads int

	// Number of peers that uploading too slow.
	SnubbedDownloads int

	// Number of active piece downloads in choked state.
	ChokedDownloads int

	// Number of active metadata downloads.
	ActiveMetadataDownloads int

	// Number of peer addresses that are ready to be connected.
	ReadyPeerAddresses int

	// Number of incoming peers in handshake state.
	IncomingHandshakes int

	// Number of outgoing peers in handshake state.
	OutgoingHandshakes int
}

func (t *Torrent) stats() Stats {
	stats := Stats{
		Status:                  t.status(),
		ConnectedPeers:          len(t.peers),
		IncomingPeers:           len(t.incomingPeers),
		OutgoingPeers:           len(t.outgoingPeers),
		ActiveDownloads:         len(t.pieceDownloaders),
		ActiveMetadataDownloads: len(t.infoDownloaders),
		RunningDownloads:        len(t.pieceDownloaders) - len(t.chokedDownloaders) - len(t.snubbedDownloaders),
		SnubbedDownloads:        len(t.snubbedDownloaders),
		ChokedDownloads:         len(t.chokedDownloaders),
		ReadyPeerAddresses:      t.addrList.Len(),
		IncomingHandshakes:      len(t.incomingHandshakers),
		OutgoingHandshakes:      len(t.outgoingHandshakers),
	}
	if t.info != nil {
		stats.BytesTotal = t.info.TotalLength
		stats.BytesComplete = t.bytesComplete()
		stats.BytesIncomplete = stats.BytesTotal - stats.BytesComplete
	} else {
		// Some trackers don't send any peer address if don't tell we have missing bytes.
		stats.BytesIncomplete = math.MaxUint32
	}
	return stats
}

func (t *Torrent) bytesComplete() int64 {
	if t.bitfield == nil {
		return 0
	}
	n := int64(t.info.PieceLength) * int64(t.bitfield.Count())
	if t.bitfield.Test(t.bitfield.Len() - 1) {
		n -= int64(t.info.PieceLength)
		n += int64(t.pieces[t.bitfield.Len()-1].Length)
	}
	return n
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"

	"github.com/SlyMarbo/spdy"
)

func handle(err error) {
	if err != nil {
		panic(err)
	}
}

func handleProxy(conn spdy.Conn) {
	url := "http://" + conn.Conn().RemoteAddr().String() + "/"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}

	res, err := conn.RequestResponse(req, nil, 1)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, res.Body)
	if err != nil {
		panic(err)
	}

	res.Body.Close()

	fmt.Println(buf.String())
}

func main() {
	handler := spdy.ProxyConnHandlerFunc(handleProxy)
	http.Handle("/", spdy.ProxyConnections(handler))
	handle(http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil))
}
<commit_msg>Updated proxy server example to new API<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"

	"github.com/SlyMarbo/spdy"
	"github.com/SlyMarbo/spdy/common"
)

func handle(err error) {
	if err != nil {
		panic(err)
	}
}

func handleProxy(conn common.Conn) {
	url := "http://" + conn.Conn().RemoteAddr().String() + "/"

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}

	res, err := conn.RequestResponse(req, nil, 1)
	if err != nil {
		panic(err)
	}

	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, res.Body)
	if err != nil {
		panic(err)
	}

	res.Body.Close()

	fmt.Println(buf.String())
}

func main() {
	handler := spdy.ProxyConnHandlerFunc(handleProxy)
	http.Handle("/", spdy.ProxyConnections(handler))
	handle(http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"os/exec"
	"strings"
	"time"

	"github.com/go-check/check"
)

// non-blocking wait with 0 exit code
func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "true")
	containerID := strings.TrimSpace(out)

	if err := waitInspect(containerID, "{{.State.Running}}", "false", 1*time.Second); err != nil {
		c.Fatal("Container should have stopped by now")
	}

	out, _ = dockerCmd(c, "wait", containerID)
	if strings.TrimSpace(out) != "0" {
		c.Fatal("failed to set up container", out)
	}

}

// blocking wait with 0 exit code
func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' TERM; while true; do sleep 0.01; done")
	containerID := strings.TrimSpace(out)

	c.Assert(waitRun(containerID), check.IsNil)

	chWait := make(chan string)
	go func() {
		out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID))
		chWait <- out
	}()

	time.Sleep(100 * time.Millisecond)
	dockerCmd(c, "stop", containerID)

	select {
	case status := <-chWait:
		if strings.TrimSpace(status) != "0" {
			c.Fatalf("expected exit 0, got %s", status)
		}
	case <-time.After(2 * time.Second):
		c.Fatal("timeout waiting for `docker wait` to exit")
	}

}

// non-blocking wait with random exit code
func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "exit 99")
	containerID := strings.TrimSpace(out)

	if err := waitInspect(containerID, "{{.State.Running}}", "false", 1*time.Second); err != nil {
		c.Fatal("Container should have stopped by now")
	}

	out, _ = dockerCmd(c, "wait", containerID)
	if strings.TrimSpace(out) != "99" {
		c.Fatal("failed to set up container", out)
	}

}

// blocking wait with random exit code
func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 99' TERM; while true; do sleep 0.01; done")
	containerID := strings.TrimSpace(out)
	c.Assert(waitRun(containerID), check.IsNil)

	chWait := make(chan error)
	waitCmd := exec.Command(dockerBinary, "wait", containerID)
	waitCmdOut := bytes.NewBuffer(nil)
	waitCmd.Stdout = waitCmdOut
	if err := waitCmd.Start(); err != nil {
		c.Fatal(err)
	}

	go func() {
		chWait <- waitCmd.Wait()
	}()

	dockerCmd(c, "stop", containerID)

	select {
	case err := <-chWait:
		if err != nil {
			c.Fatal(err)
		}
		status, err := waitCmdOut.ReadString('\n')
		if err != nil {
			c.Fatal(err)
		}
		if strings.TrimSpace(status) != "99" {
			c.Fatalf("expected exit 99, got %s", status)
		}
	case <-time.After(2 * time.Second):
		waitCmd.Process.Kill()
		c.Fatal("timeout waiting for `docker wait` to exit")
	}
}
<commit_msg>Windows CI: Fix cli_wait_test<commit_after>package main

import (
	"bytes"
	"os/exec"
	"strings"
	"time"

	"github.com/go-check/check"
)

// non-blocking wait with 0 exit code
func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
	out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "true")
	containerID := strings.TrimSpace(out)

	if err := waitInspect(containerID, "{{.State.Running}}", "false", 30*time.Second); err != nil {
		c.Fatal("Container should have stopped by now")
	}

	out, _ = dockerCmd(c, "wait", containerID)
	if strings.TrimSpace(out) != "0" {
		c.Fatal("failed to set up container", out)
	}

}

// blocking wait with 0 exit code
func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
	// Windows busybox does not support trap in this way, not sleep with sub-second
	// granularity. It will always exit 0x40010004.
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' TERM; while true; do usleep 10; done")
	containerID := strings.TrimSpace(out)

	c.Assert(waitRun(containerID), check.IsNil)

	chWait := make(chan string)
	go func() {
		out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID))
		chWait <- out
	}()

	time.Sleep(100 * time.Millisecond)
	dockerCmd(c, "stop", containerID)

	select {
	case status := <-chWait:
		if strings.TrimSpace(status) != "0" {
			c.Fatalf("expected exit 0, got %s", status)
		}
	case <-time.After(2 * time.Second):
		c.Fatal("timeout waiting for `docker wait` to exit")
	}

}

// non-blocking wait with random exit code
func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
	out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "exit 99")
	containerID := strings.TrimSpace(out)

	if err := waitInspect(containerID, "{{.State.Running}}", "false", 30*time.Second); err != nil {
		c.Fatal("Container should have stopped by now")
	}

	out, _ = dockerCmd(c, "wait", containerID)
	if strings.TrimSpace(out) != "99" {
		c.Fatal("failed to set up container", out)
	}

}

// blocking wait with random exit code
func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
	// Cannot run on Windows as trap in Windows busybox does not support trap in this way.
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 99' TERM; while true; do usleep 10; done")
	containerID := strings.TrimSpace(out)
	c.Assert(waitRun(containerID), check.IsNil)

	chWait := make(chan error)
	waitCmd := exec.Command(dockerBinary, "wait", containerID)
	waitCmdOut := bytes.NewBuffer(nil)
	waitCmd.Stdout = waitCmdOut
	if err := waitCmd.Start(); err != nil {
		c.Fatal(err)
	}

	go func() {
		chWait <- waitCmd.Wait()
	}()

	dockerCmd(c, "stop", containerID)

	select {
	case err := <-chWait:
		if err != nil {
			c.Fatal(err)
		}
		status, err := waitCmdOut.ReadString('\n')
		if err != nil {
			c.Fatal(err)
		}
		if strings.TrimSpace(status) != "99" {
			c.Fatalf("expected exit 99, got %s", status)
		}
	case <-time.After(2 * time.Second):
		waitCmd.Process.Kill()
		c.Fatal("timeout waiting for `docker wait` to exit")
	}
}
<|endoftext|>


<commit_before>package frontend

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aukbit/pluto"
	"github.com/aukbit/pluto/client"
	pb "github.com/aukbit/pluto/examples/user/proto"
	"github.com/aukbit/pluto/reply"
	"github.com/aukbit/pluto/server/router"
	"github.com/golang/protobuf/jsonpb"
	"github.com/google/uuid"
	"github.com/rs/zerolog/log"
)

var (
	errClientUserNotAvailable = errors.New("Client user not available")
)

// PostHandler ...
func PostHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// new user
	nu := &pb.NewUser{}
	if err := json.NewDecoder(r.Body).Decode(nu); err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer r.Body.Close()
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial(client.Timeout(2 * time.Second))
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make call
	user, err := c.Stub(conn).(pb.UserServiceClient).CreateUser(ctx, nu)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(ctx).Info().Msg(fmt.Sprintf("POST user %s created", user.Id))
	// set header location
	w.Header().Set("Location", r.URL.Path+"/"+user.Id)
	reply.Json(w, r, http.StatusCreated, user)
	return nil
}

// GetHandlerDetail ...
func GetHandlerDetail(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return &router.HandlerErr{
			Error:   fmt.Errorf("Id %v not found", id),
			Message: fmt.Errorf("Id %v not found", id).Error(),
			Code:    http.StatusNotFound,
		}
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).ReadUser(ctx, user)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET user %s", user.Id))
	// set header location
	w.Header().Add("Location", r.URL.Path)
	reply.Json(w, r, http.StatusOK, user)
	return nil
}

// PutHandler ...
func PutHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return router.NewHandlerErr(
			fmt.Errorf("Id %v not found", id),
			http.StatusNotFound,
		)
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// unmarshal body
	if err = jsonpb.Unmarshal(r.Body, user); err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return router.NewHandlerErr(
			errClientUserNotAvailable,
			http.StatusInternalServerError,
		)
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).UpdateUser(ctx, user)
	if err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("PUT user %s updated", user.Id))
	// set header location
	w.Header().Set("Location", r.URL.Path)
	reply.Json(w, r, http.StatusOK, user)
	return nil
}

// DeleteHandler ...
func DeleteHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return &router.HandlerErr{
			Error:   fmt.Errorf("Id %v not found", id),
			Message: fmt.Errorf("Id %v not found", id).Error(),
			Code:    http.StatusNotFound,
		}
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).DeleteUser(ctx, user)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("DELETE user %s deleted", user.Id))
	reply.Json(w, r, http.StatusOK, user)
	return nil
}

// GetHandler ...
func GetHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get parameters
	n := r.URL.Query().Get("name")
	// set proto filter
	filter := &pb.Filter{Name: n}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	users, err := c.Stub(conn).(pb.UserServiceClient).FilterUsers(ctx, filter)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET users %v", users))
	reply.Json(w, r, http.StatusOK, users)
	return nil
}

// GetStreamHandler ...
func GetStreamHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get parameters
	n := r.URL.Query().Get("name")
	// set proto filter
	filter := &pb.Filter{Name: n}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make call
	stream, err := c.Stub(conn).(pb.UserServiceClient).StreamUsers(ctx, filter)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	users := &pb.Users{}
	for {
		u, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			return &router.HandlerErr{
				Error:   fmt.Errorf("%v.StreamUsers(_) = _, %v", c.Stub(conn), err),
				Message: fmt.Errorf("%v.StreamUsers(_) = _, %v", c.Stub(conn), err).Error(),
				Code:    http.StatusInternalServerError,
			}
		}
		users.Data = append(users.Data, u)
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET Stream users %v", users))
	reply.Json(w, r, http.StatusOK, users)
	return nil
}
<commit_msg>test jsonpb func reply<commit_after>package frontend

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aukbit/pluto"
	"github.com/aukbit/pluto/client"
	pb "github.com/aukbit/pluto/examples/user/proto"
	"github.com/aukbit/pluto/reply"
	"github.com/aukbit/pluto/server/router"
	"github.com/golang/protobuf/jsonpb"
	"github.com/google/uuid"
	"github.com/rs/zerolog/log"
)

var (
	errClientUserNotAvailable = errors.New("Client user not available")
)

// PostHandler ...
func PostHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// new user
	nu := &pb.NewUser{}
	if err := json.NewDecoder(r.Body).Decode(nu); err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer r.Body.Close()
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial(client.Timeout(2 * time.Second))
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make call
	user, err := c.Stub(conn).(pb.UserServiceClient).CreateUser(ctx, nu)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(ctx).Info().Msg(fmt.Sprintf("POST user %s created", user.Id))
	// set header location
	w.Header().Set("Location", r.URL.Path+"/"+user.Id)
	reply.Jsonpb(w, r, http.StatusCreated, &jsonpb.Marshaler{}, user)
	return nil
}

// GetHandlerDetail ...
func GetHandlerDetail(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return &router.HandlerErr{
			Error:   fmt.Errorf("Id %v not found", id),
			Message: fmt.Errorf("Id %v not found", id).Error(),
			Code:    http.StatusNotFound,
		}
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).ReadUser(ctx, user)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET user %s", user.Id))
	// set header location
	w.Header().Add("Location", r.URL.Path)
	reply.Jsonpb(w, r, http.StatusOK, &jsonpb.Marshaler{}, user)
	return nil
}

// PutHandler ...
func PutHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return router.NewHandlerErr(
			fmt.Errorf("Id %v not found", id),
			http.StatusNotFound,
		)
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// unmarshal body
	if err = jsonpb.Unmarshal(r.Body, user); err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return router.NewHandlerErr(
			errClientUserNotAvailable,
			http.StatusInternalServerError,
		)
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).UpdateUser(ctx, user)
	if err != nil {
		return router.NewHandlerErr(
			err,
			http.StatusInternalServerError,
		)
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("PUT user %s updated", user.Id))
	// set header location
	w.Header().Set("Location", r.URL.Path)
	reply.Jsonpb(w, r, http.StatusOK, &jsonpb.Marshaler{}, user)
	return nil
}

// DeleteHandler ...
func DeleteHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get id context
	id := router.FromContext(ctx, "id")
	validID, err := uuid.Parse(id)
	if err != nil {
		return &router.HandlerErr{
			Error:   fmt.Errorf("Id %v not found", id),
			Message: fmt.Errorf("Id %v not found", id).Error(),
			Code:    http.StatusNotFound,
		}
	}
	// set proto user
	user := &pb.User{Id: validID.String()}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	user, err = c.Stub(conn).(pb.UserServiceClient).DeleteUser(ctx, user)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("DELETE user %s deleted", user.Id))
	reply.Jsonpb(w, r, http.StatusOK, &jsonpb.Marshaler{}, user)
	return nil
}

// GetHandler ...
func GetHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get parameters
	n := r.URL.Query().Get("name")
	// set proto filter
	filter := &pb.Filter{Name: n}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make a call the backend service
	users, err := c.Stub(conn).(pb.UserServiceClient).FilterUsers(ctx, filter)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET users %v", users))
	reply.Jsonpb(w, r, http.StatusOK, &jsonpb.Marshaler{}, users)
	return nil
}

// GetStreamHandler ...
func GetStreamHandler(w http.ResponseWriter, r *http.Request) *router.HandlerErr {
	// get context
	ctx := r.Context()
	// get parameters
	n := r.URL.Query().Get("name")
	// set proto filter
	filter := &pb.Filter{Name: n}
	// get gRPC client from service
	c, ok := pluto.FromContext(ctx).Client("user")
	if !ok {
		return &router.HandlerErr{
			Error:   errClientUserNotAvailable,
			Message: errClientUserNotAvailable.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	// dial
	conn, err := c.Dial()
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	defer conn.Close()
	// make call
	stream, err := c.Stub(conn).(pb.UserServiceClient).StreamUsers(ctx, filter)
	if err != nil {
		return &router.HandlerErr{
			Error:   err,
			Message: err.Error(),
			Code:    http.StatusInternalServerError,
		}
	}
	users := &pb.Users{}
	for {
		u, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			return &router.HandlerErr{
				Error:   fmt.Errorf("%v.StreamUsers(_) = _, %v", c.Stub(conn), err),
				Message: fmt.Errorf("%v.StreamUsers(_) = _, %v", c.Stub(conn), err).Error(),
				Code:    http.StatusInternalServerError,
			}
		}
		users.Data = append(users.Data, u)
	}
	log.Ctx(r.Context()).Info().Msg(fmt.Sprintf("GET Stream users %v", users))
	reply.Jsonpb(w, r, http.StatusOK, &jsonpb.Marshaler{}, users)
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2019 The Ebiten 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.

// +build darwin

package metal

import (
	"sort"
	"unsafe"

	"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
)

// #cgo LDFLAGS: -framework CoreFoundation
//
// #import <CoreFoundation/CoreFoundation.h>
//
// static int count(void* obj) {
//   return CFGetRetainCount(obj);
// }
import "C"

type buffer struct {
	b   mtl.Buffer
	len uintptr
}

func (b *buffer) used() bool {
	// If the count is 2 or more, the buffer is actually retained outside.
	// If the count is 1, the buffer is retained only by the buffer pool.
	// The count cannot be 0 since the object is already freed in this case.
	return C.count(b.b.Native()) > 1
}

var bufferPool = map[*buffer]struct{}{}

func getBuffer(device mtl.Device, data unsafe.Pointer, lengthInBytes uintptr) *buffer {
	for buf := range bufferPool {
		if buf.used() {
			continue
		}
		if buf.len < lengthInBytes {
			continue
		}
		buf.b.CopyToContents(data, lengthInBytes)
		buf.b.Retain()
		return buf
	}

	gcBufferPool()

	buf := &buffer{
		b:   device.MakeBufferWithBytes(data, lengthInBytes, mtl.ResourceStorageModeManaged),
		len: lengthInBytes,
	}
	buf.b.Retain()
	bufferPool[buf] = struct{}{}
	return buf
}

func putBuffer(buf *buffer) {
	buf.b.Release()
	gcBufferPool()
}

func gcBufferPool() {
	const threshold = 16

	if len(bufferPool) < threshold {
		return
	}

	toRemove := []*buffer{}
	for buf := range bufferPool {
		if buf.used() {
			continue
		}
		toRemove = append(toRemove, buf)
	}
	sort.Slice(toRemove, func(a, b int) bool {
		return toRemove[a].len < toRemove[b].len
	})

	l := len(toRemove)
	if l > len(bufferPool)-threshold {
		l = len(bufferPool) - threshold
	}
	for _, buf := range toRemove[:l] {
		buf.b.Release()
		delete(bufferPool, buf)
	}
}
<commit_msg>graphicsdriver/metal: Add comments<commit_after>// Copyright 2019 The Ebiten 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.

// +build darwin

package metal

import (
	"sort"
	"unsafe"

	"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
)

// #cgo LDFLAGS: -framework CoreFoundation
//
// #import <CoreFoundation/CoreFoundation.h>
//
// static int count(void* obj) {
//   // TODO: Don't rely on the number of ref counts. CFGetRetainCount should be used only for debugging.
//   return CFGetRetainCount(obj);
// }
import "C"

type buffer struct {
	b   mtl.Buffer
	len uintptr
}

func (b *buffer) used() bool {
	// If the count is 2 or more, the buffer is actually retained outside.
	// If the count is 1, the buffer is retained only by the buffer pool.
	// The count cannot be 0 since the object is already freed in this case.
	return C.count(b.b.Native()) > 1
}

var bufferPool = map[*buffer]struct{}{}

func getBuffer(device mtl.Device, data unsafe.Pointer, lengthInBytes uintptr) *buffer {
	for buf := range bufferPool {
		if buf.used() {
			continue
		}
		if buf.len < lengthInBytes {
			continue
		}
		buf.b.CopyToContents(data, lengthInBytes)
		buf.b.Retain()
		return buf
	}

	gcBufferPool()

	buf := &buffer{
		b:   device.MakeBufferWithBytes(data, lengthInBytes, mtl.ResourceStorageModeManaged),
		len: lengthInBytes,
	}
	buf.b.Retain()
	bufferPool[buf] = struct{}{}
	return buf
}

func putBuffer(buf *buffer) {
	buf.b.Release()
	// The buffer will be actually released after all the current command buffers are finished.
	gcBufferPool()
}

func gcBufferPool() {
	const threshold = 16

	if len(bufferPool) < threshold {
		return
	}

	toRemove := []*buffer{}
	for buf := range bufferPool {
		if buf.used() {
			continue
		}
		toRemove = append(toRemove, buf)
	}
	sort.Slice(toRemove, func(a, b int) bool {
		return toRemove[a].len < toRemove[b].len
	})

	l := len(toRemove)
	if l > len(bufferPool)-threshold {
		l = len(bufferPool) - threshold
	}
	for _, buf := range toRemove[:l] {
		buf.b.Release()
		delete(bufferPool, buf)
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsDynamoDbGlobalTable() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsDynamoDbGlobalTableCreate,
		Read:   resourceAwsDynamoDbGlobalTableRead,
		Update: resourceAwsDynamoDbGlobalTableUpdate,
		Delete: resourceAwsDynamoDbGlobalTableDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(1 * time.Minute),
			Update: schema.DefaultTimeout(1 * time.Minute),
			Delete: schema.DefaultTimeout(1 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateAwsDynamoDbGlobalTableName,
			},

			"replica": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"region_name": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},

			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsDynamoDbGlobalTableCreate(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	globalTableName := d.Get("name").(string)

	input := &dynamodb.CreateGlobalTableInput{
		GlobalTableName:  aws.String(globalTableName),
		ReplicationGroup: expandAwsDynamoDbReplicas(d.Get("replica").(*schema.Set).List()),
	}

	log.Printf("[DEBUG] Creating DynamoDB Global Table: %#v", input)
	_, err := dynamodbconn.CreateGlobalTable(input)
	if err != nil {
		return err
	}

	d.SetId(globalTableName)

	log.Println("[INFO] Waiting for DynamoDB Global Table to be created")
	stateConf := &resource.StateChangeConf{
		Pending: []string{
			dynamodb.GlobalTableStatusCreating,
			dynamodb.GlobalTableStatusDeleting,
			dynamodb.GlobalTableStatusUpdating,
		},
		Target: []string{
			dynamodb.GlobalTableStatusActive,
		},
		Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		MinTimeout: 10 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	return resourceAwsDynamoDbGlobalTableRead(d, meta)
}

func resourceAwsDynamoDbGlobalTableRead(d *schema.ResourceData, meta interface{}) error {
	globalTableDescription, err := resourceAwsDynamoDbGlobalTableRetrieve(d, meta)

	if err != nil {
		return err
	}
	if globalTableDescription == nil {
		log.Printf("[WARN] DynamoDB Global Table %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	return flattenAwsDynamoDbGlobalTable(d, globalTableDescription)
}

func resourceAwsDynamoDbGlobalTableUpdate(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	if d.HasChange("replica") {
		o, n := d.GetChange("replica")
		if o == nil {
			o = new(schema.Set)
		}
		if n == nil {
			n = new(schema.Set)
		}

		os := o.(*schema.Set)
		ns := n.(*schema.Set)
		replicaUpdateCreateReplicas := expandAwsDynamoDbReplicaUpdateCreateReplicas(ns.Difference(os).List())
		replicaUpdateDeleteReplicas := expandAwsDynamoDbReplicaUpdateDeleteReplicas(os.Difference(ns).List())

		replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, (len(replicaUpdateCreateReplicas) + len(replicaUpdateDeleteReplicas)))
		for _, replicaUpdate := range replicaUpdateCreateReplicas {
			replicaUpdates = append(replicaUpdates, replicaUpdate)
		}
		for _, replicaUpdate := range replicaUpdateDeleteReplicas {
			replicaUpdates = append(replicaUpdates, replicaUpdate)
		}

		input := &dynamodb.UpdateGlobalTableInput{
			GlobalTableName: aws.String(d.Id()),
			ReplicaUpdates:  replicaUpdates,
		}
		log.Printf("[DEBUG] Updating DynamoDB Global Table: %#v", input)
		if _, err := dynamodbconn.UpdateGlobalTable(input); err != nil {
			return err
		}

		log.Println("[INFO] Waiting for DynamoDB Global Table to be updated")
		stateConf := &resource.StateChangeConf{
			Pending: []string{
				dynamodb.GlobalTableStatusCreating,
				dynamodb.GlobalTableStatusDeleting,
				dynamodb.GlobalTableStatusUpdating,
			},
			Target: []string{
				dynamodb.GlobalTableStatusActive,
			},
			Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
			Timeout:    d.Timeout(schema.TimeoutUpdate),
			MinTimeout: 10 * time.Second,
		}
		_, err := stateConf.WaitForState()
		if err != nil {
			return err
		}
	}

	return nil
}

// Deleting a DynamoDB Global Table is represented by removing all replicas.
func resourceAwsDynamoDbGlobalTableDelete(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	input := &dynamodb.UpdateGlobalTableInput{
		GlobalTableName: aws.String(d.Id()),
		ReplicaUpdates:  expandAwsDynamoDbReplicaUpdateDeleteReplicas(d.Get("replica").(*schema.Set).List()),
	}
	log.Printf("[DEBUG] Deleting DynamoDB Global Table: %#v", input)
	if _, err := dynamodbconn.UpdateGlobalTable(input); err != nil {
		return err
	}

	log.Println("[INFO] Waiting for DynamoDB Global Table to be destroyed")
	stateConf := &resource.StateChangeConf{
		Pending: []string{
			dynamodb.GlobalTableStatusActive,
			dynamodb.GlobalTableStatusCreating,
			dynamodb.GlobalTableStatusDeleting,
			dynamodb.GlobalTableStatusUpdating,
		},
		Target:     []string{},
		Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutDelete),
		MinTimeout: 10 * time.Second,
	}
	_, err := stateConf.WaitForState()
	return err
}

func resourceAwsDynamoDbGlobalTableRetrieve(d *schema.ResourceData, meta interface{}) (*dynamodb.GlobalTableDescription, error) {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	input := &dynamodb.DescribeGlobalTableInput{
		GlobalTableName: aws.String(d.Id()),
	}

	log.Printf("[DEBUG] Retrieving DynamoDB Global Table: %#v", input)

	output, err := dynamodbconn.DescribeGlobalTable(input)
	if err != nil {
		if isAWSErr(err, dynamodb.ErrCodeGlobalTableNotFoundException, "") {
			return nil, nil
		}
		return nil, fmt.Errorf("Error retrieving DynamoDB Global Table: %s", err)
	}

	return output.GlobalTableDescription, nil
}

func resourceAwsDynamoDbGlobalTableStateRefreshFunc(
	d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		gtd, err := resourceAwsDynamoDbGlobalTableRetrieve(d, meta)

		if err != nil {
			log.Printf("Error on retrieving DynamoDB Global Table when waiting: %s", err)
			return nil, "", err
		}

		if gtd == nil {
			return nil, "", nil
		}

		if gtd.GlobalTableStatus != nil {
			log.Printf("[DEBUG] Status for DynamoDB Global Table %s: %s", d.Id(), *gtd.GlobalTableStatus)
		}

		return gtd, *gtd.GlobalTableStatus, nil
	}
}

func flattenAwsDynamoDbGlobalTable(d *schema.ResourceData, globalTableDescription *dynamodb.GlobalTableDescription) error {
	var err error

	d.Set("arn", globalTableDescription.GlobalTableArn)
	d.Set("name", globalTableDescription.GlobalTableName)

	err = d.Set("replica", flattenAwsDynamoDbReplicas(globalTableDescription.ReplicationGroup))
	if err != nil {
		return err
	}

	return nil
}

func expandAwsDynamoDbReplicaUpdateCreateReplicas(configuredReplicas []interface{}) []*dynamodb.ReplicaUpdate {
	replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicaUpdates = append(replicaUpdates, expandAwsDynamoDbReplicaUpdateCreateReplica(replica))
	}
	return replicaUpdates
}

func expandAwsDynamoDbReplicaUpdateCreateReplica(configuredReplica map[string]interface{}) *dynamodb.ReplicaUpdate {
	replicaUpdate := &dynamodb.ReplicaUpdate{
		Create: &dynamodb.CreateReplicaAction{
			RegionName: aws.String(configuredReplica["region_name"].(string)),
		},
	}
	return replicaUpdate
}

func expandAwsDynamoDbReplicaUpdateDeleteReplicas(configuredReplicas []interface{}) []*dynamodb.ReplicaUpdate {
	replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicaUpdates = append(replicaUpdates, expandAwsDynamoDbReplicaUpdateDeleteReplica(replica))
	}
	return replicaUpdates
}

func expandAwsDynamoDbReplicaUpdateDeleteReplica(configuredReplica map[string]interface{}) *dynamodb.ReplicaUpdate {
	replicaUpdate := &dynamodb.ReplicaUpdate{
		Delete: &dynamodb.DeleteReplicaAction{
			RegionName: aws.String(configuredReplica["region_name"].(string)),
		},
	}
	return replicaUpdate
}

func expandAwsDynamoDbReplicas(configuredReplicas []interface{}) []*dynamodb.Replica {
	replicas := make([]*dynamodb.Replica, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicas = append(replicas, expandAwsDynamoDbReplica(replica))
	}
	return replicas
}

func expandAwsDynamoDbReplica(configuredReplica map[string]interface{}) *dynamodb.Replica {
	replica := &dynamodb.Replica{
		RegionName: aws.String(configuredReplica["region_name"].(string)),
	}
	return replica
}

func flattenAwsDynamoDbReplicas(replicaDescriptions []*dynamodb.ReplicaDescription) []interface{} {
	replicas := []interface{}{}
	for _, replicaDescription := range replicaDescriptions {
		replicas = append(replicas, flattenAwsDynamoDbReplica(replicaDescription))
	}
	return replicas
}

func flattenAwsDynamoDbReplica(replicaDescription *dynamodb.ReplicaDescription) map[string]interface{} {
	replica := make(map[string]interface{})
	replica["region_name"] = *replicaDescription.RegionName
	return replica
}
<commit_msg>Fix gosimple dynamodb issues<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

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

func resourceAwsDynamoDbGlobalTable() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsDynamoDbGlobalTableCreate,
		Read:   resourceAwsDynamoDbGlobalTableRead,
		Update: resourceAwsDynamoDbGlobalTableUpdate,
		Delete: resourceAwsDynamoDbGlobalTableDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(1 * time.Minute),
			Update: schema.DefaultTimeout(1 * time.Minute),
			Delete: schema.DefaultTimeout(1 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateAwsDynamoDbGlobalTableName,
			},

			"replica": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"region_name": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},

			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsDynamoDbGlobalTableCreate(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	globalTableName := d.Get("name").(string)

	input := &dynamodb.CreateGlobalTableInput{
		GlobalTableName:  aws.String(globalTableName),
		ReplicationGroup: expandAwsDynamoDbReplicas(d.Get("replica").(*schema.Set).List()),
	}

	log.Printf("[DEBUG] Creating DynamoDB Global Table: %#v", input)
	_, err := dynamodbconn.CreateGlobalTable(input)
	if err != nil {
		return err
	}

	d.SetId(globalTableName)

	log.Println("[INFO] Waiting for DynamoDB Global Table to be created")
	stateConf := &resource.StateChangeConf{
		Pending: []string{
			dynamodb.GlobalTableStatusCreating,
			dynamodb.GlobalTableStatusDeleting,
			dynamodb.GlobalTableStatusUpdating,
		},
		Target: []string{
			dynamodb.GlobalTableStatusActive,
		},
		Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		MinTimeout: 10 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	return resourceAwsDynamoDbGlobalTableRead(d, meta)
}

func resourceAwsDynamoDbGlobalTableRead(d *schema.ResourceData, meta interface{}) error {
	globalTableDescription, err := resourceAwsDynamoDbGlobalTableRetrieve(d, meta)

	if err != nil {
		return err
	}
	if globalTableDescription == nil {
		log.Printf("[WARN] DynamoDB Global Table %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	return flattenAwsDynamoDbGlobalTable(d, globalTableDescription)
}

func resourceAwsDynamoDbGlobalTableUpdate(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	if d.HasChange("replica") {
		o, n := d.GetChange("replica")
		if o == nil {
			o = new(schema.Set)
		}
		if n == nil {
			n = new(schema.Set)
		}

		os := o.(*schema.Set)
		ns := n.(*schema.Set)
		replicaUpdateCreateReplicas := expandAwsDynamoDbReplicaUpdateCreateReplicas(ns.Difference(os).List())
		replicaUpdateDeleteReplicas := expandAwsDynamoDbReplicaUpdateDeleteReplicas(os.Difference(ns).List())

		replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, (len(replicaUpdateCreateReplicas) + len(replicaUpdateDeleteReplicas)))
		replicaUpdates = append(replicaUpdates, replicaUpdateCreateReplicas...)
		replicaUpdates = append(replicaUpdates, replicaUpdateDeleteReplicas...)

		input := &dynamodb.UpdateGlobalTableInput{
			GlobalTableName: aws.String(d.Id()),
			ReplicaUpdates:  replicaUpdates,
		}
		log.Printf("[DEBUG] Updating DynamoDB Global Table: %#v", input)
		if _, err := dynamodbconn.UpdateGlobalTable(input); err != nil {
			return err
		}

		log.Println("[INFO] Waiting for DynamoDB Global Table to be updated")
		stateConf := &resource.StateChangeConf{
			Pending: []string{
				dynamodb.GlobalTableStatusCreating,
				dynamodb.GlobalTableStatusDeleting,
				dynamodb.GlobalTableStatusUpdating,
			},
			Target: []string{
				dynamodb.GlobalTableStatusActive,
			},
			Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
			Timeout:    d.Timeout(schema.TimeoutUpdate),
			MinTimeout: 10 * time.Second,
		}
		_, err := stateConf.WaitForState()
		if err != nil {
			return err
		}
	}

	return nil
}

// Deleting a DynamoDB Global Table is represented by removing all replicas.
func resourceAwsDynamoDbGlobalTableDelete(d *schema.ResourceData, meta interface{}) error {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	input := &dynamodb.UpdateGlobalTableInput{
		GlobalTableName: aws.String(d.Id()),
		ReplicaUpdates:  expandAwsDynamoDbReplicaUpdateDeleteReplicas(d.Get("replica").(*schema.Set).List()),
	}
	log.Printf("[DEBUG] Deleting DynamoDB Global Table: %#v", input)
	if _, err := dynamodbconn.UpdateGlobalTable(input); err != nil {
		return err
	}

	log.Println("[INFO] Waiting for DynamoDB Global Table to be destroyed")
	stateConf := &resource.StateChangeConf{
		Pending: []string{
			dynamodb.GlobalTableStatusActive,
			dynamodb.GlobalTableStatusCreating,
			dynamodb.GlobalTableStatusDeleting,
			dynamodb.GlobalTableStatusUpdating,
		},
		Target:     []string{},
		Refresh:    resourceAwsDynamoDbGlobalTableStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutDelete),
		MinTimeout: 10 * time.Second,
	}
	_, err := stateConf.WaitForState()
	return err
}

func resourceAwsDynamoDbGlobalTableRetrieve(d *schema.ResourceData, meta interface{}) (*dynamodb.GlobalTableDescription, error) {
	dynamodbconn := meta.(*AWSClient).dynamodbconn

	input := &dynamodb.DescribeGlobalTableInput{
		GlobalTableName: aws.String(d.Id()),
	}

	log.Printf("[DEBUG] Retrieving DynamoDB Global Table: %#v", input)

	output, err := dynamodbconn.DescribeGlobalTable(input)
	if err != nil {
		if isAWSErr(err, dynamodb.ErrCodeGlobalTableNotFoundException, "") {
			return nil, nil
		}
		return nil, fmt.Errorf("Error retrieving DynamoDB Global Table: %s", err)
	}

	return output.GlobalTableDescription, nil
}

func resourceAwsDynamoDbGlobalTableStateRefreshFunc(
	d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		gtd, err := resourceAwsDynamoDbGlobalTableRetrieve(d, meta)

		if err != nil {
			log.Printf("Error on retrieving DynamoDB Global Table when waiting: %s", err)
			return nil, "", err
		}

		if gtd == nil {
			return nil, "", nil
		}

		if gtd.GlobalTableStatus != nil {
			log.Printf("[DEBUG] Status for DynamoDB Global Table %s: %s", d.Id(), *gtd.GlobalTableStatus)
		}

		return gtd, *gtd.GlobalTableStatus, nil
	}
}

func flattenAwsDynamoDbGlobalTable(d *schema.ResourceData, globalTableDescription *dynamodb.GlobalTableDescription) error {
	var err error

	d.Set("arn", globalTableDescription.GlobalTableArn)
	d.Set("name", globalTableDescription.GlobalTableName)

	err = d.Set("replica", flattenAwsDynamoDbReplicas(globalTableDescription.ReplicationGroup))
	return err
}

func expandAwsDynamoDbReplicaUpdateCreateReplicas(configuredReplicas []interface{}) []*dynamodb.ReplicaUpdate {
	replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicaUpdates = append(replicaUpdates, expandAwsDynamoDbReplicaUpdateCreateReplica(replica))
	}
	return replicaUpdates
}

func expandAwsDynamoDbReplicaUpdateCreateReplica(configuredReplica map[string]interface{}) *dynamodb.ReplicaUpdate {
	replicaUpdate := &dynamodb.ReplicaUpdate{
		Create: &dynamodb.CreateReplicaAction{
			RegionName: aws.String(configuredReplica["region_name"].(string)),
		},
	}
	return replicaUpdate
}

func expandAwsDynamoDbReplicaUpdateDeleteReplicas(configuredReplicas []interface{}) []*dynamodb.ReplicaUpdate {
	replicaUpdates := make([]*dynamodb.ReplicaUpdate, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicaUpdates = append(replicaUpdates, expandAwsDynamoDbReplicaUpdateDeleteReplica(replica))
	}
	return replicaUpdates
}

func expandAwsDynamoDbReplicaUpdateDeleteReplica(configuredReplica map[string]interface{}) *dynamodb.ReplicaUpdate {
	replicaUpdate := &dynamodb.ReplicaUpdate{
		Delete: &dynamodb.DeleteReplicaAction{
			RegionName: aws.String(configuredReplica["region_name"].(string)),
		},
	}
	return replicaUpdate
}

func expandAwsDynamoDbReplicas(configuredReplicas []interface{}) []*dynamodb.Replica {
	replicas := make([]*dynamodb.Replica, 0, len(configuredReplicas))
	for _, replicaRaw := range configuredReplicas {
		replica := replicaRaw.(map[string]interface{})
		replicas = append(replicas, expandAwsDynamoDbReplica(replica))
	}
	return replicas
}

func expandAwsDynamoDbReplica(configuredReplica map[string]interface{}) *dynamodb.Replica {
	replica := &dynamodb.Replica{
		RegionName: aws.String(configuredReplica["region_name"].(string)),
	}
	return replica
}

func flattenAwsDynamoDbReplicas(replicaDescriptions []*dynamodb.ReplicaDescription) []interface{} {
	replicas := []interface{}{}
	for _, replicaDescription := range replicaDescriptions {
		replicas = append(replicas, flattenAwsDynamoDbReplica(replicaDescription))
	}
	return replicas
}

func flattenAwsDynamoDbReplica(replicaDescription *dynamodb.ReplicaDescription) map[string]interface{} {
	replica := make(map[string]interface{})
	replica["region_name"] = *replicaDescription.RegionName
	return replica
}
<|endoftext|>


<commit_before>package aws

import (
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ecr"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEcrRepositoryPolicy() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEcrRepositoryPolicyCreate,
		Read:   resourceAwsEcrRepositoryPolicyRead,
		Update: resourceAwsEcrRepositoryPolicyUpdate,
		Delete: resourceAwsEcrRepositoryPolicyDelete,

		Schema: map[string]*schema.Schema{
			"repository": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"policy": {
				Type:     schema.TypeString,
				Required: true,
			},
			"registry_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEcrRepositoryPolicyCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Creating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	log.Printf("[DEBUG] ECR repository policy created: %s", *repositoryPolicy.RepositoryName)

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return resourceAwsEcrRepositoryPolicyRead(d, meta)
}

func resourceAwsEcrRepositoryPolicyRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	log.Printf("[DEBUG] Reading repository policy %s", d.Id())
	out, err := conn.GetRepositoryPolicy(&ecr.GetRepositoryPolicyInput{
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				d.SetId("")
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] Received repository policy %s", out)

	repositoryPolicy := out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)
	d.Set("policy", repositoryPolicy.PolicyText)

	return nil
}

func resourceAwsEcrRepositoryPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	if !d.HasChange("policy") {
		return nil
	}

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Updating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return nil
}

func resourceAwsEcrRepositoryPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	_, err := conn.DeleteRepositoryPolicy(&ecr.DeleteRepositoryPolicyInput{
		RepositoryName: aws.String(d.Id()),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] repository policy %s deleted.", d.Id())

	return nil
}
<commit_msg>resource/aws_ecr_repository_policy: suppress diffs of equivalent policies via json suppressor<commit_after>package aws

import (
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ecr"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEcrRepositoryPolicy() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEcrRepositoryPolicyCreate,
		Read:   resourceAwsEcrRepositoryPolicyRead,
		Update: resourceAwsEcrRepositoryPolicyUpdate,
		Delete: resourceAwsEcrRepositoryPolicyDelete,

		Schema: map[string]*schema.Schema{
			"repository": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"policy": {
				Type:     schema.TypeString,
				Required: true,
				DiffSuppressFunc: suppressEquivalentJsonDiffs,
			},
			"registry_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEcrRepositoryPolicyCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Creating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	log.Printf("[DEBUG] ECR repository policy created: %s", *repositoryPolicy.RepositoryName)

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return resourceAwsEcrRepositoryPolicyRead(d, meta)
}

func resourceAwsEcrRepositoryPolicyRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	log.Printf("[DEBUG] Reading repository policy %s", d.Id())
	out, err := conn.GetRepositoryPolicy(&ecr.GetRepositoryPolicyInput{
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				d.SetId("")
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] Received repository policy %s", out)

	repositoryPolicy := out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)
	d.Set("policy", repositoryPolicy.PolicyText)

	return nil
}

func resourceAwsEcrRepositoryPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	if !d.HasChange("policy") {
		return nil
	}

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Updating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return nil
}

func resourceAwsEcrRepositoryPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	_, err := conn.DeleteRepositoryPolicy(&ecr.DeleteRepositoryPolicyInput{
		RepositoryName: aws.String(d.Id()),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] repository policy %s deleted.", d.Id())

	return nil
}
<|endoftext|>