<commit_before>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"

	"vitess.io/vitess/go/vt/log"
)

// TopoProcess is a generic handle for a running Topo service .
// It can be spawned manually
type TopoProcess struct {
	Name               string
	Binary             string
	DataDirectory      string
	LogDirectory       string
	ListenClientURL    string
	AdvertiseClientURL string
	Port               int
	Host               string
	VerifyURL          string
	PeerURL            string
	ZKPorts            string

	proc *exec.Cmd
	exit chan error
}

// Setup starts a new topo service
func (topo *TopoProcess) Setup(topoFlavor string, cluster *LocalProcessCluster) (err error) {
	switch topoFlavor {
	case "zk2":
		return topo.SetupZookeeper(cluster)
	case "consul":
		return topo.SetupConsul(cluster)
	default:
		return topo.SetupEtcd()
	}
}

// SetupEtcd spawns a new etcd service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupEtcd() (err error) {
	topo.proc = exec.Command(
		topo.Binary,
		"--name", topo.Name,
		"--data-dir", topo.DataDirectory,
		"--listen-client-urls", topo.ListenClientURL,
		"--advertise-client-urls", topo.AdvertiseClientURL,
		"--initial-advertise-peer-urls", topo.PeerURL,
		"--listen-peer-urls", topo.PeerURL,
		"--initial-cluster", fmt.Sprintf("%s=%s", topo.Name, topo.PeerURL),
		"--enable-v2=true",
	)

	err = createDirectory(topo.DataDirectory, 0700)
	if err != nil && !os.IsExist(err) {
		return err
	}
	errFile, err := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	if err != nil {
		return err
	}

	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Errorf("Starting etcd with command: %v", strings.Join(topo.proc.Args, " "))

	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// SetupZookeeper spawns a new zookeeper topo service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupZookeeper(cluster *LocalProcessCluster) (err error) {

	host, err := os.Hostname()
	if err != nil {
		return
	}

	topo.ZKPorts = fmt.Sprintf("%d:%d:%d", cluster.GetAndReservePort(), cluster.GetAndReservePort(), topo.Port)

	topo.proc = exec.Command(
		topo.Binary,
		"-log_dir", topo.LogDirectory,
		"-zk.cfg", fmt.Sprintf("1@%v:%s", host, topo.ZKPorts),
		"init",
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile
	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting zookeeper with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Run()
	if err != nil {
		return
	}
	return
}

// SetupConsul spawns a new consul service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupConsul(cluster *LocalProcessCluster) (err error) {

	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v1/kv/?keys", topo.Host, topo.Port)

	configFile := path.Join(os.Getenv("VTDATAROOT"), "consul.json")

	config := fmt.Sprintf(`{"ports":{"dns":%d,"http":%d,"serf_lan":%d,"serf_wan":%d}}`,
		cluster.GetAndReservePort(), topo.Port, cluster.GetAndReservePort(), cluster.GetAndReservePort())

	err = ioutil.WriteFile(configFile, []byte(config), 0666)
	if err != nil {
		return
	}

	topo.proc = exec.Command(
		topo.Binary, "agent",
		"-dev",
		"-config-file", configFile,
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting consul with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// TearDown shutdowns the running topo service
func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool, topoFlavor string) error {

	if topoFlavor == "zk2" {
		cmd := "shutdown"
		if keepdata {
			cmd = "teardown"
		}
		topo.proc = exec.Command(
			topo.Binary,
			"-log_dir", topo.LogDirectory,
			"-zk.cfg", fmt.Sprintf("1@%v:%s", topo.Host, topo.ZKPorts),
			cmd,
		)

		err := topo.proc.Run()
		if err != nil {
			return err
		}
	} else {
		if topo.proc == nil || topo.exit == nil {
			return nil
		}

		topo.removeTopoDirectories(Cell)

		// Attempt graceful shutdown with SIGTERM first
		_ = topo.proc.Process.Signal(syscall.SIGTERM)

		if !(*keepData || keepdata) {
			_ = os.RemoveAll(topo.DataDirectory)
			_ = os.RemoveAll(currentRoot)
		}
		_ = os.Setenv("VTDATAROOT", originalVtRoot)

		select {
		case <-topo.exit:
			topo.proc = nil
			return nil

		case <-time.After(10 * time.Second):
			topo.proc.Process.Kill()
			topo.proc = nil
			return <-topo.exit
		}
	}

	return nil
}

// IsHealthy function checks if topo server is up and running
func (topo *TopoProcess) IsHealthy() bool {
	resp, err := http.Get(topo.VerifyURL)
	if err != nil {
		return false
	}
	if resp.StatusCode == 200 {
		return true
	}
	return false
}

func (topo *TopoProcess) removeTopoDirectories(Cell string) {
	_ = topo.ManageTopoDir("rmdir", "/vitess/global")
	_ = topo.ManageTopoDir("rmdir", "/vitess/"+Cell)
}

// ManageTopoDir creates global and zone in etcd2
func (topo *TopoProcess) ManageTopoDir(command string, directory string) (err error) {
	url := topo.VerifyURL + directory
	payload := strings.NewReader(`{"dir":"true"}`)
	if command == "mkdir" {
		req, _ := http.NewRequest("PUT", url, payload)
		req.Header.Add("content-type", "application/json")
		_, err = http.DefaultClient.Do(req)
		return err
	} else if command == "rmdir" {
		req, _ := http.NewRequest("DELETE", url+"?dir=true", payload)
		_, err = http.DefaultClient.Do(req)
		return err
	} else {
		return nil
	}
}

// TopoProcessInstance returns a TopoProcess handle for a etcd sevice,
// configured with the given Config.
// The process must be manually started by calling setup()
func TopoProcessInstance(port int, peerPort int, hostname string, flavor string, name string) *TopoProcess {
	binary := "etcd"
	if flavor == "zk2" {
		binary = "zkctl"
	}
	if flavor == "consul" {
		binary = "consul"
	}

	topo := &TopoProcess{
		Name:   name,
		Binary: binary,
		Port:   port,
		Host:   hostname,
	}

	topo.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.ListenClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port))
	topo.LogDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port), "logs")
	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", topo.Host, topo.Port)
	topo.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort)
	return topo
}
<commit_msg>endtoend: change log level of etcd start from error to info<commit_after>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"

	"vitess.io/vitess/go/vt/log"
)

// TopoProcess is a generic handle for a running Topo service .
// It can be spawned manually
type TopoProcess struct {
	Name               string
	Binary             string
	DataDirectory      string
	LogDirectory       string
	ListenClientURL    string
	AdvertiseClientURL string
	Port               int
	Host               string
	VerifyURL          string
	PeerURL            string
	ZKPorts            string

	proc *exec.Cmd
	exit chan error
}

// Setup starts a new topo service
func (topo *TopoProcess) Setup(topoFlavor string, cluster *LocalProcessCluster) (err error) {
	switch topoFlavor {
	case "zk2":
		return topo.SetupZookeeper(cluster)
	case "consul":
		return topo.SetupConsul(cluster)
	default:
		return topo.SetupEtcd()
	}
}

// SetupEtcd spawns a new etcd service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupEtcd() (err error) {
	topo.proc = exec.Command(
		topo.Binary,
		"--name", topo.Name,
		"--data-dir", topo.DataDirectory,
		"--listen-client-urls", topo.ListenClientURL,
		"--advertise-client-urls", topo.AdvertiseClientURL,
		"--initial-advertise-peer-urls", topo.PeerURL,
		"--listen-peer-urls", topo.PeerURL,
		"--initial-cluster", fmt.Sprintf("%s=%s", topo.Name, topo.PeerURL),
		"--enable-v2=true",
	)

	err = createDirectory(topo.DataDirectory, 0700)
	if err != nil && !os.IsExist(err) {
		return err
	}
	errFile, err := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	if err != nil {
		return err
	}

	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting etcd with command: %v", strings.Join(topo.proc.Args, " "))

	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// SetupZookeeper spawns a new zookeeper topo service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupZookeeper(cluster *LocalProcessCluster) (err error) {

	host, err := os.Hostname()
	if err != nil {
		return
	}

	topo.ZKPorts = fmt.Sprintf("%d:%d:%d", cluster.GetAndReservePort(), cluster.GetAndReservePort(), topo.Port)

	topo.proc = exec.Command(
		topo.Binary,
		"-log_dir", topo.LogDirectory,
		"-zk.cfg", fmt.Sprintf("1@%v:%s", host, topo.ZKPorts),
		"init",
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile
	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting zookeeper with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Run()
	if err != nil {
		return
	}
	return
}

// SetupConsul spawns a new consul service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupConsul(cluster *LocalProcessCluster) (err error) {

	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v1/kv/?keys", topo.Host, topo.Port)

	configFile := path.Join(os.Getenv("VTDATAROOT"), "consul.json")

	config := fmt.Sprintf(`{"ports":{"dns":%d,"http":%d,"serf_lan":%d,"serf_wan":%d}}`,
		cluster.GetAndReservePort(), topo.Port, cluster.GetAndReservePort(), cluster.GetAndReservePort())

	err = ioutil.WriteFile(configFile, []byte(config), 0666)
	if err != nil {
		return
	}

	topo.proc = exec.Command(
		topo.Binary, "agent",
		"-dev",
		"-config-file", configFile,
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting consul with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// TearDown shutdowns the running topo service
func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool, topoFlavor string) error {

	if topoFlavor == "zk2" {
		cmd := "shutdown"
		if keepdata {
			cmd = "teardown"
		}
		topo.proc = exec.Command(
			topo.Binary,
			"-log_dir", topo.LogDirectory,
			"-zk.cfg", fmt.Sprintf("1@%v:%s", topo.Host, topo.ZKPorts),
			cmd,
		)

		err := topo.proc.Run()
		if err != nil {
			return err
		}
	} else {
		if topo.proc == nil || topo.exit == nil {
			return nil
		}

		topo.removeTopoDirectories(Cell)

		// Attempt graceful shutdown with SIGTERM first
		_ = topo.proc.Process.Signal(syscall.SIGTERM)

		if !(*keepData || keepdata) {
			_ = os.RemoveAll(topo.DataDirectory)
			_ = os.RemoveAll(currentRoot)
		}
		_ = os.Setenv("VTDATAROOT", originalVtRoot)

		select {
		case <-topo.exit:
			topo.proc = nil
			return nil

		case <-time.After(10 * time.Second):
			topo.proc.Process.Kill()
			topo.proc = nil
			return <-topo.exit
		}
	}

	return nil
}

// IsHealthy function checks if topo server is up and running
func (topo *TopoProcess) IsHealthy() bool {
	resp, err := http.Get(topo.VerifyURL)
	if err != nil {
		return false
	}
	if resp.StatusCode == 200 {
		return true
	}
	return false
}

func (topo *TopoProcess) removeTopoDirectories(Cell string) {
	_ = topo.ManageTopoDir("rmdir", "/vitess/global")
	_ = topo.ManageTopoDir("rmdir", "/vitess/"+Cell)
}

// ManageTopoDir creates global and zone in etcd2
func (topo *TopoProcess) ManageTopoDir(command string, directory string) (err error) {
	url := topo.VerifyURL + directory
	payload := strings.NewReader(`{"dir":"true"}`)
	if command == "mkdir" {
		req, _ := http.NewRequest("PUT", url, payload)
		req.Header.Add("content-type", "application/json")
		_, err = http.DefaultClient.Do(req)
		return err
	} else if command == "rmdir" {
		req, _ := http.NewRequest("DELETE", url+"?dir=true", payload)
		_, err = http.DefaultClient.Do(req)
		return err
	} else {
		return nil
	}
}

// TopoProcessInstance returns a TopoProcess handle for a etcd sevice,
// configured with the given Config.
// The process must be manually started by calling setup()
func TopoProcessInstance(port int, peerPort int, hostname string, flavor string, name string) *TopoProcess {
	binary := "etcd"
	if flavor == "zk2" {
		binary = "zkctl"
	}
	if flavor == "consul" {
		binary = "consul"
	}

	topo := &TopoProcess{
		Name:   name,
		Binary: binary,
		Port:   port,
		Host:   hostname,
	}

	topo.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.ListenClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port))
	topo.LogDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port), "logs")
	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", topo.Host, topo.Port)
	topo.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort)
	return topo
}
<|endoftext|>


<commit_before>package output

import "github.com/codegangsta/cli"

// Print prints the results of the CLI command.
func Print(c *cli.Context, f *func() interface{}, keys []string) {
	i := (*f)()
	if c.IsSet("json") {
		jsonOut(i)
		return
	}
	if c.IsSet("csv") {
		switch i.(type) {
		case map[string]interface{}:
			m := i.(map[string]interface{})
			metadataCSV(c, m, keys)
		case []map[string]interface{}:
			m := i.([]map[string]interface{})
			listCSV(c, m, keys)
		}
		default:
			fmt.Fprintf(c.App.Writer, "%v", i)
		return
	}
	switch i.(type) {
	case map[string]interface{}:
		m := i.(map[string]interface{})
		metadataTable(c, m, keys)
	case []map[string]interface{}:
		m := i.([]map[string]interface{})
		listTable(c, m, keys)
	}
	default:
		fmt.Fprintf(c.App.Writer, "%v", i)
}
<commit_msg>put default in switch block<commit_after>package output

import (
	"fmt"

	"github.com/codegangsta/cli"
)

// Print prints the results of the CLI command.
func Print(c *cli.Context, f *func() interface{}, keys []string) {
	i := (*f)()
	if c.IsSet("json") {
		jsonOut(i)
		return
	}
	if c.IsSet("csv") {
		switch i.(type) {
		case map[string]interface{}:
			m := i.(map[string]interface{})
			metadataCSV(c, m, keys)
		case []map[string]interface{}:
			m := i.([]map[string]interface{})
			listCSV(c, m, keys)
		default:
			fmt.Fprintf(c.App.Writer, "%v", i)
		}
		return
	}
	switch i.(type) {
	case map[string]interface{}:
		m := i.(map[string]interface{})
		metadataTable(c, m, keys)
	case []map[string]interface{}:
		m := i.([]map[string]interface{})
		listTable(c, m, keys)
	default:
		fmt.Fprintf(c.App.Writer, "%v", i)
	}
}
<|endoftext|>


<commit_before>package getaredis

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"golang.org/x/oauth2"

	"github.com/digitalocean/godo"
	"github.com/garyburd/redigo/redis"
)

type TokenSource struct {
	AccessToken string
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}

type Host struct {
	PublicIP           string
	PrivateIP          string
	Name               string
	NumberOfContainers int
	MemoryFree         float32
}

func (ctx *context) ListHosts() []Host {
	redisServerKeys, _ := redis.Strings(ctx.redis.Do("KEYS", "server:*"))
	servers := make([]interface{}, len(redisServerKeys))
	for i, t := range redisServerKeys {
		servers[i] = t
	}
	serverConfigs, _ := redis.Strings(ctx.redis.Do("MGET", servers...))

	hosts := make([]Host, len(serverConfigs))
	for i, val := range serverConfigs {
		newHost := new(Host)
		err := json.Unmarshal([]byte(val), newHost)
		if err != nil {
			continue
		}
		hosts[i] = *newHost
	}
	return hosts
}

func (ctx *context) NewHost() error {
	redisIP := strings.Split(ctx.config.RedisAddress, ":")[0]
	redisPort := strings.Split(ctx.config.RedisAddress, ":")[1]
	dropletName := "getaredis-server-" + generateRandomString(10)
	userData := `#cloud-config
runcmd:
  - docker pull redis
  - apt-get install -y supervisor nginx apache2-utils
  - echo 'DOCKER_OPTS=$DOCKER_OPTS" -H unix:///var/run/docker.sock -H tcp://127.0.0.1:2375"' >> /etc/default/docker
  - service docker restart
  - mkdir -p /etc/nginx/docker_auth
  - htpasswd -b -c /etc/nginx/docker_auth/.htpasswd %v %v
  - service nginx reload
write_files:
  - path: /etc/supervisor/conf.d/go_jobs.conf
    content: |
        [program:service_discovery]
        command=/usr/local/bin/service_discovery
        autostart=true
        autorestart=true
        stderr_logfile=/var/log/service_discovery.err.log
        stdout_logfile=/var/log/service_discovery.out.log
  - path: /usr/local/bin/service_discovery
    permissions: '0755'
    content: |
        #!/bin/bash
        (
          PUBLIC_IP=$(curl http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
          PRIVATE_IP=$(curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address)
          NODE_NAME=%v
          echo "AUTH %v";
          while true; do
            NUMBER_OF_CONTAINERS=$(($(docker ps | wc -l) - 1))
            echo "SET server:$NODE_NAME '{\"PublicIP\":\"$PUBLIC_IP\",\"PrivateIP\":\"$PRIVATE_IP\",\"Name\":\"$NODE_NAME\",\"NumberOfContainers\":$NUMBER_OF_CONTAINERS}'";
            echo "EXPIRE server:$NODE_NAME 10";
            sleep 4;
          done
        ) | telnet %v %v
  - path : /etc/nginx/conf.d/docker.conf
    content: |
        server {
          listen 2377;
          location / {
            auth_basic "Restricted";
            auth_basic_user_file /etc/nginx/docker_auth/.htpasswd;
            proxy_buffering off;
            proxy_pass http://localhost:2375;
          }
        }
`

	userData = fmt.Sprintf(userData, ctx.config.Docker["user"], ctx.config.Docker["password"], dropletName, ctx.config.RedisPassword, redisIP, redisPort)

	var sshKey *godo.DropletCreateSSHKey
	if ctx.config.DropletSSHKeyID != -1 {
		sshKey = &godo.DropletCreateSSHKey{ID: ctx.config.DropletSSHKeyID}
	}

	createRequest := &godo.DropletCreateRequest{
		Name:   dropletName,
		Region: "nyc3",
		Size:   "512mb",
		Image: godo.DropletCreateImage{
			Slug: "docker",
		},
		UserData:          userData,
		PrivateNetworking: true,
		SSHKeys:           []godo.DropletCreateSSHKey{*sshKey},
	}

	_, _, err := ctx.digitalocean.Droplets.Create(createRequest)
	return err
}

func (ctx *context) DeleteHost(ip string) error {
	droplets, _, err := ctx.digitalocean.Droplets.List(nil)
	if err != nil {
		return err
	}
	deleted := false
	for _, d := range droplets {
		for _, intr := range d.Networks.V4 {
			if intr.IPAddress == ip {
				_, err := ctx.digitalocean.Droplets.Delete(d.ID)
				if err != nil {
					return err
				}
				deleted = true
				break
			}
		}
	}
	if !deleted {
		return errors.New("Couldn't find droplet with this IP")
	}
	return nil
}
<commit_msg>Fixing missing update<commit_after>package getaredis

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"golang.org/x/oauth2"

	"github.com/digitalocean/godo"
	"github.com/garyburd/redigo/redis"
)

type TokenSource struct {
	AccessToken string
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}

type Host struct {
	PublicIP           string
	PrivateIP          string
	Name               string
	NumberOfContainers int
	MemoryFree         float32
}

func (ctx *context) ListHosts() []Host {
	redisServerKeys, _ := redis.Strings(ctx.redis.Do("KEYS", "server:*"))
	servers := make([]interface{}, len(redisServerKeys))
	for i, t := range redisServerKeys {
		servers[i] = t
	}
	serverConfigs, _ := redis.Strings(ctx.redis.Do("MGET", servers...))

	hosts := make([]Host, len(serverConfigs))
	for i, val := range serverConfigs {
		newHost := new(Host)
		err := json.Unmarshal([]byte(val), newHost)
		if err != nil {
			continue
		}
		hosts[i] = *newHost
	}
	return hosts
}

func (ctx *context) NewHost() error {
	redisIP := strings.Split(ctx.config.RedisAddress, ":")[0]
	redisPort := strings.Split(ctx.config.RedisAddress, ":")[1]
	dropletName := "getaredis-server-" + generateRandomString(10)
	userData := `#cloud-config
runcmd:
  - docker pull redis
  - apt-get update
  - apt-get install -y supervisor nginx apache2-utils
  - echo 'DOCKER_OPTS=$DOCKER_OPTS" -H unix:///var/run/docker.sock -H tcp://127.0.0.1:2375"' >> /etc/default/docker
  - service docker restart
  - mkdir -p /etc/nginx/docker_auth
  - htpasswd -b -c /etc/nginx/docker_auth/.htpasswd %v %v
  - service nginx reload
write_files:
  - path: /etc/supervisor/conf.d/go_jobs.conf
    content: |
        [program:service_discovery]
        command=/usr/local/bin/service_discovery
        autostart=true
        autorestart=true
        stderr_logfile=/var/log/service_discovery.err.log
        stdout_logfile=/var/log/service_discovery.out.log
  - path: /usr/local/bin/service_discovery
    permissions: '0755'
    content: |
        #!/bin/bash
        (
          PUBLIC_IP=$(curl http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
          PRIVATE_IP=$(curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address)
          NODE_NAME=%v
          echo "AUTH %v";
          while true; do
            NUMBER_OF_CONTAINERS=$(($(docker ps | wc -l) - 1))
            echo "SET server:$NODE_NAME '{\"PublicIP\":\"$PUBLIC_IP\",\"PrivateIP\":\"$PRIVATE_IP\",\"Name\":\"$NODE_NAME\",\"NumberOfContainers\":$NUMBER_OF_CONTAINERS}'";
            echo "EXPIRE server:$NODE_NAME 10";
            sleep 4;
          done
        ) | telnet %v %v
  - path : /etc/nginx/conf.d/docker.conf
    content: |
        server {
          listen 2377;
          location / {
            auth_basic "Restricted";
            auth_basic_user_file /etc/nginx/docker_auth/.htpasswd;
            proxy_buffering off;
            proxy_pass http://localhost:2375;
          }
        }
`

	userData = fmt.Sprintf(userData, ctx.config.Docker["user"], ctx.config.Docker["password"], dropletName, ctx.config.RedisPassword, redisIP, redisPort)

	var sshKey *godo.DropletCreateSSHKey
	if ctx.config.DropletSSHKeyID != -1 {
		sshKey = &godo.DropletCreateSSHKey{ID: ctx.config.DropletSSHKeyID}
	}

	createRequest := &godo.DropletCreateRequest{
		Name:   dropletName,
		Region: "nyc3",
		Size:   "512mb",
		Image: godo.DropletCreateImage{
			Slug: "docker",
		},
		UserData:          userData,
		PrivateNetworking: true,
		SSHKeys:           []godo.DropletCreateSSHKey{*sshKey},
	}

	_, _, err := ctx.digitalocean.Droplets.Create(createRequest)
	return err
}

func (ctx *context) DeleteHost(ip string) error {
	droplets, _, err := ctx.digitalocean.Droplets.List(nil)
	if err != nil {
		return err
	}
	deleted := false
	for _, d := range droplets {
		for _, intr := range d.Networks.V4 {
			if intr.IPAddress == ip {
				_, err := ctx.digitalocean.Droplets.Delete(d.ID)
				if err != nil {
					return err
				}
				deleted = true
				break
			}
		}
	}
	if !deleted {
		return errors.New("Couldn't find droplet with this IP")
	}
	return nil
}
<|endoftext|>


<commit_before>package p2p

import (
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"
)

var ipCheckServices = []string{
	"http://members.3322.org/dyndns/getip",
	"http://ifconfig.me/",
	"http://icanhazip.com/",
	"http://ifconfig.io/ip",
	"http://ident.me/",
	"http://whatismyip.akamai.com/",
	"http://myip.dnsomatic.com/",
	"http://diagnostic.opendns.com/myip",
	"http://myexternalip.com/raw",
}

type IpResult struct {
	Success bool
	Ip      string
}

var timeout = time.Duration(10)

func GetIP() *IpResult {
	resultCh := make(chan *IpResult, 1)
	for _, s := range ipCheckServices {
		go ipAddress(s, resultCh)
	}

	for {
		select {
		case result := <-resultCh:
			return result
		case <-time.After(time.Second * timeout):
			return &IpResult{false, ""}
		}
	}
}

func ipAddress(service string, done chan<- *IpResult) {
	client := http.Client{Timeout: time.Duration(timeout * time.Second)}
	resp, err := client.Get(service)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	address := strings.TrimSpace(string(data))
	if net.ParseIP(address) != nil {
		select {
		case done <- &IpResult{true, address}:
			return
		default:
			return
		}
	}
}
<commit_msg>Reduce get external IP waiting time<commit_after>package p2p

import (
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"
)

var ipCheckServices = []string{
	"http://members.3322.org/dyndns/getip",
	"http://ifconfig.me/",
	"http://icanhazip.com/",
	"http://ifconfig.io/ip",
	"http://ident.me/",
	"http://whatismyip.akamai.com/",
	"http://myip.dnsomatic.com/",
	"http://diagnostic.opendns.com/myip",
	"http://myexternalip.com/raw",
}

type IpResult struct {
	Success bool
	Ip      string
}

var timeout = time.Duration(5)

func GetIP() *IpResult {
	resultCh := make(chan *IpResult, 1)
	for _, s := range ipCheckServices {
		go ipAddress(s, resultCh)
	}

	for {
		select {
		case result := <-resultCh:
			return result
		case <-time.After(time.Second * timeout):
			return &IpResult{false, ""}
		}
	}
}

func ipAddress(service string, done chan<- *IpResult) {
	client := http.Client{Timeout: time.Duration(timeout * time.Second)}
	resp, err := client.Get(service)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	address := strings.TrimSpace(string(data))
	if net.ParseIP(address) != nil {
		select {
		case done <- &IpResult{true, address}:
			return
		default:
			return
		}
	}
}
<|endoftext|>


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

package docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id"`
	RepoTags    []string `json:",omitempty"`
	Created     int64
	Size        int64
	VirtualSize int64
	ParentId    string `json:",omitempty"`
	Repository  string `json:",omitempty"`
	Tag         string `json:",omitempty"`
}

type Image struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"containerconfig,omitempty"`
	DockerVersion   string    `json:"dockerversion,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/dkMrwP for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/7hjHHy for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/pHEbma for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/GBmyhc for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Tag of the image
	Tag string

	// Registry server to push the image
	Registry string

	OutputStream io.Writer `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authencation in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/GBmyhc for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)

	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.stream("POST", path, true, false, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/PhBKnS for more details.
type PullImageOptions struct {
	Repository    string `qs:"fromImage"`
	Registry      string
	Tag           string
	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)
	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
}

func (c *Client) LoadImage(in io.Reader) error {
	return c.stream("POST", "/images/load", true, false, nil, in, nil, nil)
}

func (c *Client) ExportImage(imageName string, out io.Writer) error {
	return c.stream("GET", fmt.Sprintf("/images/%s/get", imageName), true, false, nil, nil, out, nil)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, rawJSONStream, headers, in, w, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, false)
}

// BuildImageOptions present the set of informations available for building
// an image from a tarfile with a Dockerfile in it,the details about Dockerfile
// see http://docs.docker.io/en/latest/reference/builder/
type BuildImageOptions struct {
	Name                string    `qs:"t"`
	NoCache             bool      `qs:"nocache"`
	SuppressOutput      bool      `qs:"q"`
	RmTmpContainer      bool      `qs:"rm"`
	ForceRmTmpContainer bool      `qs:"forcerm"`
	InputStream         io.Reader `qs:"-"`
	OutputStream        io.Writer `qs:"-"`
	Remote              string    `qs:"remote"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers map[string]string
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil {
		headers = map[string]string{"Content-Type": "application/tar"}
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, false, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image
type TagImageOptions struct {
	Repo  string
	Tag   string
	Force bool
}

// TagImage adds a tag to the image 'name'
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}
<commit_msg>Improving via Structs + godocs<commit_after>// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id"`
	RepoTags    []string `json:",omitempty"`
	Created     int64
	Size        int64
	VirtualSize int64
	ParentId    string `json:",omitempty"`
	Repository  string `json:",omitempty"`
	Tag         string `json:",omitempty"`
}

type Image struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"containerconfig,omitempty"`
	DockerVersion   string    `json:"dockerversion,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/dkMrwP for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/7hjHHy for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/pHEbma for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/GBmyhc for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Tag of the image
	Tag string

	// Registry server to push the image
	Registry string

	OutputStream io.Writer `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authencation in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/GBmyhc for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)

	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.stream("POST", path, true, false, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/PhBKnS for more details.
type PullImageOptions struct {
	Repository    string `qs:"fromImage"`
	Registry      string
	Tag           string
	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	var headers = make(map[string]string)
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(auth)
	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
}

// LoadImageOptions represents the options for LoadImage Docker API Call
type LoadImageOptions struct {
	In io.Reader
}

// LoadImage imports a tarball docker image
//
// See http://docs.docker.com/reference/api/docker_remote_api_v1.14/#load-a-tarball-with-a-set-of-images-and-tags-into-docker for more details
func (c *Client) LoadImage(opts LoadImageOptions) error {
	return c.stream("POST", "/images/load", true, false, nil, opts.In, nil, nil)
}

// ExportImageOptions represent the options for ExportImage Docker API call
type ExportImageOptions struct {
	ImageName string
	Out       io.Writer
}

// ExportImage exports an image (as a tar file) into the stream
//
// See http://docs.docker.com/reference/api/docker_remote_api_v1.14/#get-a-tarball-containing-all-images-and-tags-in-a-repository for more details
func (c *Client) ExportImage(opts ExportImageOptions) error {
	return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.ImageName), true, false, nil, nil, opts.Out, nil)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, rawJSONStream, headers, in, w, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, false)
}

// BuildImageOptions present the set of informations available for building
// an image from a tarfile with a Dockerfile in it,the details about Dockerfile
// see http://docs.docker.io/en/latest/reference/builder/
type BuildImageOptions struct {
	Name                string    `qs:"t"`
	NoCache             bool      `qs:"nocache"`
	SuppressOutput      bool      `qs:"q"`
	RmTmpContainer      bool      `qs:"rm"`
	ForceRmTmpContainer bool      `qs:"forcerm"`
	InputStream         io.Reader `qs:"-"`
	OutputStream        io.Writer `qs:"-"`
	Remote              string    `qs:"remote"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers map[string]string
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil {
		headers = map[string]string{"Content-Type": "application/tar"}
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, false, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image
type TagImageOptions struct {
	Repo  string
	Tag   string
	Force bool
}

// TagImage adds a tag to the image 'name'
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}
<|endoftext|>


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

package ebiten

import (
	"fmt"
	"image"
	"image/color"
	"runtime"

	"github.com/hajimehoshi/ebiten/internal/math"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"github.com/hajimehoshi/ebiten/internal/restorable"
)

// Image represents a rectangle set of pixels.
// The pixel format is alpha-premultiplied RGBA.
// Image implements image.Image.
//
// Functions of Image never returns error as of 1.5.0-alpha, and error values are always nil.
type Image struct {
	restorable *restorable.Image
}

// Size returns the size of the image.
func (i *Image) Size() (width, height int) {
	return i.restorable.Size()
}

// Clear resets the pixels of the image into 0.
//
// When the image is disposed, Clear does nothing.
//
// Clear always returns nil as of 1.5.0-alpha.
func (i *Image) Clear() error {
	i.restorable.Fill(0, 0, 0, 0)
	return nil
}

// Fill fills the image with a solid color.
//
// When the image is disposed, Fill does nothing.
//
// Fill always returns nil as of 1.5.0-alpha.
func (i *Image) Fill(clr color.Color) error {
	r, g, b, a := clr.RGBA()
	i.restorable.Fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
	return nil
}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     SourceRect:    nil. When SourceRect is nil, the whole source image is used.
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// For drawing, the pixels of the argument image at the time of this call is adopted.
// Even if the argument image is mutated after this call,
// the drawing result is never affected.
//
// When the image is disposed, DrawImage does nothing.
//
// When the given image is as same as i, DrawImage panics.
//
// DrawImage always returns nil as of 1.5.0-alpha.
func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
	if i == img {
		panic("ebiten: Image.DrawImage: img must be different from the receiver")
	}
	if i.restorable == nil {
		return nil
	}
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	// Parts is deprecated. This implementations is for backward compatibility.
	if parts == nil && options.Parts != nil {
		parts = imageParts(options.Parts)
	}
	// ImageParts is deprecated. This implementations is for backward compatibility.
	if parts != nil {
		l := parts.Len()
		for idx := 0; idx < l; idx++ {
			sx0, sy0, sx1, sy1 := parts.Src(idx)
			dx0, dy0, dx1, dy1 := parts.Dst(idx)
			op := &DrawImageOptions{
				ColorM:        options.ColorM,
				CompositeMode: options.CompositeMode,
			}
			r := image.Rect(sx0, sy0, sx1, sy1)
			op.SourceRect = &r
			op.GeoM.Scale(
				float64(dx1-dx0)/float64(sx1-sx0),
				float64(dy1-dy0)/float64(sy1-sy0))
			op.GeoM.Translate(float64(dx0), float64(dy0))
			op.GeoM.Concat(options.GeoM)
			i.DrawImage(img, op)
		}
		return nil
	}
	w, h := img.restorable.Size()
	sx0, sy0, sx1, sy1 := 0, 0, w, h
	if r := options.SourceRect; r != nil {
		sx0 = r.Min.X
		sy0 = r.Min.Y
		sx1 = r.Max.X
		sy1 = r.Max.Y
	}
	vs := vertices(sx0, sy0, sx1, sy1, w, h, &options.GeoM.impl)
	mode := opengl.CompositeMode(options.CompositeMode)
	i.restorable.DrawImage(img.restorable, vs, &options.ColorM.impl, mode)
	return nil
}

// Bounds returns the bounds of the image.
func (i *Image) Bounds() image.Rectangle {
	w, h := i.restorable.Size()
	return image.Rect(0, 0, w, h)
}

// ColorModel returns the color model of the image.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from GPU to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
func (i *Image) At(x, y int) color.Color {
	if i.restorable == nil {
		return color.Transparent
	}
	// TODO: Error should be delayed until flushing. Do not panic here.
	clr, err := i.restorable.At(x, y)
	if err != nil {
		panic(err)
	}
	return clr
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// When the image is disposed, Dipose does nothing.
//
// Dipose always return nil as of 1.5.0-alpha.
func (i *Image) Dispose() error {
	if i.restorable == nil {
		return nil
	}
	i.restorable.Dispose()
	i.restorable = nil
	runtime.SetFinalizer(i, nil)
	return nil
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// ReplacePixels may be slow (as for implementation, this calls glTexSubImage2D).
//
// When len(p) is not 4 * (width) * (height), ReplacePixels panics.
//
// When the image is disposed, ReplacePixels does nothing.
//
// ReplacePixels always returns nil as of 1.5.0-alpha.
func (i *Image) ReplacePixels(p []uint8) error {
	if i.restorable == nil {
		return nil
	}
	w, h := i.restorable.Size()
	if l := 4 * w * h; len(p) != l {
		panic(fmt.Sprintf("ebiten: len(p) was %d but must be %d", len(p), l))
	}
	w2, h2 := math.NextPowerOf2Int(w), math.NextPowerOf2Int(h)
	pix := make([]uint8, 4*w2*h2)
	for j := 0; j < h; j++ {
		copy(pix[j*w2*4:], p[j*w*4:(j+1)*w*4])
	}
	i.restorable.ReplacePixels(pix)
	return nil
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	SourceRect    *image.Rectangle
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.5.0-alpha): Use Part instead.
	ImageParts ImageParts

	// Deprecated (as of 1.1.0-alpha): Use Part instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// If width or height is less than 1 or more than MaxImageSize, NewImage panics.
//
// Error returned by NewImage is always nil as of 1.5.0-alpha.
func NewImage(width, height int, filter Filter) (*Image, error) {
	checkSize(width, height)
	r := restorable.NewImage(width, height, glFilter(filter), false)
	r.Fill(0, 0, 0, 0)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i, nil
}

// newVolatileImage returns an empty 'volatile' image.
// A volatile image is always cleared at the start of a frame.
//
// This is suitable for offscreen images that pixels are changed often.
//
// Pixels in regular non-volatile images are saved at each end of a frame if the image
// is changed, and restored automatically from the saved pixels on GL context lost.
// On the other hand, pixels in volatile images are not saved.
// Saving pixels is an expensive operation, and it is desirable to avoid it if possible.
//
// Note that volatile images are internal only and will never be source of drawing.
//
// If width or height is less than 1 or more than MaxImageSize, newVolatileImage panics.
//
// Error returned by newVolatileImage is always nil as of 1.5.0-alpha.
func newVolatileImage(width, height int, filter Filter) *Image {
	checkSize(width, height)
	r := restorable.NewImage(width, height, glFilter(filter), true)
	r.Fill(0, 0, 0, 0)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i
}

// NewImageFromImage creates a new image with the given image (source).
//
// If source's width or height is less than 1 or more than MaxImageSize, NewImageFromImage panics.
//
// Error returned by NewImageFromImage is always nil as of 1.5.0-alpha.
func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
	size := source.Bounds().Size()
	checkSize(size.X, size.Y)
	r := restorable.NewImageFromImage(source, glFilter(filter))
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i, nil
}

func newImageWithScreenFramebuffer(width, height int, offsetX, offsetY float64) *Image {
	checkSize(width, height)
	r := restorable.NewScreenFramebufferImage(width, height, offsetX, offsetY)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i
}

// MaxImageSize represents the maximum width/height of an image.
const MaxImageSize = restorable.MaxImageSize

func checkSize(width, height int) {
	if width <= 0 {
		panic("ebiten: width must be more than 0")
	}
	if height <= 0 {
		panic("ebiten: height must be more than 0")
	}
	if width > MaxImageSize {
		panic(fmt.Sprintf("ebiten: width (%d) must be less than or equal to %d", width, MaxImageSize))
	}
	if height > MaxImageSize {
		panic(fmt.Sprintf("ebiten: height (%d) must be less than or equal to %d", height, MaxImageSize))
	}
}
<commit_msg>graphics: Fix document<commit_after>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ebiten

import (
	"fmt"
	"image"
	"image/color"
	"runtime"

	"github.com/hajimehoshi/ebiten/internal/math"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"github.com/hajimehoshi/ebiten/internal/restorable"
)

// Image represents a rectangle set of pixels.
// The pixel format is alpha-premultiplied RGBA.
// Image implements image.Image.
//
// Functions of Image never returns error as of 1.5.0-alpha, and error values are always nil.
type Image struct {
	restorable *restorable.Image
}

// Size returns the size of the image.
func (i *Image) Size() (width, height int) {
	return i.restorable.Size()
}

// Clear resets the pixels of the image into 0.
//
// When the image is disposed, Clear does nothing.
//
// Clear always returns nil as of 1.5.0-alpha.
func (i *Image) Clear() error {
	i.restorable.Fill(0, 0, 0, 0)
	return nil
}

// Fill fills the image with a solid color.
//
// When the image is disposed, Fill does nothing.
//
// Fill always returns nil as of 1.5.0-alpha.
func (i *Image) Fill(clr color.Color) error {
	r, g, b, a := clr.RGBA()
	i.restorable.Fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
	return nil
}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     SourceRect:    nil. When SourceRect is nil, the whole source image is used.
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// For drawing, the pixels of the argument image at the time of this call is adopted.
// Even if the argument image is mutated after this call,
// the drawing result is never affected.
//
// When the image is disposed, DrawImage does nothing.
//
// When the given image is as same as i, DrawImage panics.
//
// DrawImage always returns nil as of 1.5.0-alpha.
func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
	if i == img {
		panic("ebiten: Image.DrawImage: img must be different from the receiver")
	}
	if i.restorable == nil {
		return nil
	}
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	// Parts is deprecated. This implementations is for backward compatibility.
	if parts == nil && options.Parts != nil {
		parts = imageParts(options.Parts)
	}
	// ImageParts is deprecated. This implementations is for backward compatibility.
	if parts != nil {
		l := parts.Len()
		for idx := 0; idx < l; idx++ {
			sx0, sy0, sx1, sy1 := parts.Src(idx)
			dx0, dy0, dx1, dy1 := parts.Dst(idx)
			op := &DrawImageOptions{
				ColorM:        options.ColorM,
				CompositeMode: options.CompositeMode,
			}
			r := image.Rect(sx0, sy0, sx1, sy1)
			op.SourceRect = &r
			op.GeoM.Scale(
				float64(dx1-dx0)/float64(sx1-sx0),
				float64(dy1-dy0)/float64(sy1-sy0))
			op.GeoM.Translate(float64(dx0), float64(dy0))
			op.GeoM.Concat(options.GeoM)
			i.DrawImage(img, op)
		}
		return nil
	}
	w, h := img.restorable.Size()
	sx0, sy0, sx1, sy1 := 0, 0, w, h
	if r := options.SourceRect; r != nil {
		sx0 = r.Min.X
		sy0 = r.Min.Y
		sx1 = r.Max.X
		sy1 = r.Max.Y
	}
	vs := vertices(sx0, sy0, sx1, sy1, w, h, &options.GeoM.impl)
	mode := opengl.CompositeMode(options.CompositeMode)
	i.restorable.DrawImage(img.restorable, vs, &options.ColorM.impl, mode)
	return nil
}

// Bounds returns the bounds of the image.
func (i *Image) Bounds() image.Rectangle {
	w, h := i.restorable.Size()
	return image.Rect(0, 0, w, h)
}

// ColorModel returns the color model of the image.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from GPU to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
func (i *Image) At(x, y int) color.Color {
	if i.restorable == nil {
		return color.Transparent
	}
	// TODO: Error should be delayed until flushing. Do not panic here.
	clr, err := i.restorable.At(x, y)
	if err != nil {
		panic(err)
	}
	return clr
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// When the image is disposed, Dipose does nothing.
//
// Dipose always return nil as of 1.5.0-alpha.
func (i *Image) Dispose() error {
	if i.restorable == nil {
		return nil
	}
	i.restorable.Dispose()
	i.restorable = nil
	runtime.SetFinalizer(i, nil)
	return nil
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// ReplacePixels may be slow (as for implementation, this calls glTexSubImage2D).
//
// When len(p) is not 4 * (width) * (height), ReplacePixels panics.
//
// When the image is disposed, ReplacePixels does nothing.
//
// ReplacePixels always returns nil as of 1.5.0-alpha.
func (i *Image) ReplacePixels(p []uint8) error {
	if i.restorable == nil {
		return nil
	}
	w, h := i.restorable.Size()
	if l := 4 * w * h; len(p) != l {
		panic(fmt.Sprintf("ebiten: len(p) was %d but must be %d", len(p), l))
	}
	w2, h2 := math.NextPowerOf2Int(w), math.NextPowerOf2Int(h)
	pix := make([]uint8, 4*w2*h2)
	for j := 0; j < h; j++ {
		copy(pix[j*w2*4:], p[j*w*4:(j+1)*w*4])
	}
	i.restorable.ReplacePixels(pix)
	return nil
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	SourceRect    *image.Rectangle
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.5.0-alpha): Use SourceRect instead.
	ImageParts ImageParts

	// Deprecated (as of 1.1.0-alpha): Use SourceRect instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// If width or height is less than 1 or more than MaxImageSize, NewImage panics.
//
// Error returned by NewImage is always nil as of 1.5.0-alpha.
func NewImage(width, height int, filter Filter) (*Image, error) {
	checkSize(width, height)
	r := restorable.NewImage(width, height, glFilter(filter), false)
	r.Fill(0, 0, 0, 0)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i, nil
}

// newVolatileImage returns an empty 'volatile' image.
// A volatile image is always cleared at the start of a frame.
//
// This is suitable for offscreen images that pixels are changed often.
//
// Pixels in regular non-volatile images are saved at each end of a frame if the image
// is changed, and restored automatically from the saved pixels on GL context lost.
// On the other hand, pixels in volatile images are not saved.
// Saving pixels is an expensive operation, and it is desirable to avoid it if possible.
//
// Note that volatile images are internal only and will never be source of drawing.
//
// If width or height is less than 1 or more than MaxImageSize, newVolatileImage panics.
//
// Error returned by newVolatileImage is always nil as of 1.5.0-alpha.
func newVolatileImage(width, height int, filter Filter) *Image {
	checkSize(width, height)
	r := restorable.NewImage(width, height, glFilter(filter), true)
	r.Fill(0, 0, 0, 0)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i
}

// NewImageFromImage creates a new image with the given image (source).
//
// If source's width or height is less than 1 or more than MaxImageSize, NewImageFromImage panics.
//
// Error returned by NewImageFromImage is always nil as of 1.5.0-alpha.
func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
	size := source.Bounds().Size()
	checkSize(size.X, size.Y)
	r := restorable.NewImageFromImage(source, glFilter(filter))
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i, nil
}

func newImageWithScreenFramebuffer(width, height int, offsetX, offsetY float64) *Image {
	checkSize(width, height)
	r := restorable.NewScreenFramebufferImage(width, height, offsetX, offsetY)
	i := &Image{r}
	runtime.SetFinalizer(i, (*Image).Dispose)
	return i
}

// MaxImageSize represents the maximum width/height of an image.
const MaxImageSize = restorable.MaxImageSize

func checkSize(width, height int) {
	if width <= 0 {
		panic("ebiten: width must be more than 0")
	}
	if height <= 0 {
		panic("ebiten: height must be more than 0")
	}
	if width > MaxImageSize {
		panic(fmt.Sprintf("ebiten: width (%d) must be less than or equal to %d", width, MaxImageSize))
	}
	if height > MaxImageSize {
		panic(fmt.Sprintf("ebiten: height (%d) must be less than or equal to %d", height, MaxImageSize))
	}
}
<|endoftext|>


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

package path

import (
	"fmt"
	"github.com/andreaskoch/allmark/util"
	"os"
	"path/filepath"
	"strings"
)

const (
	// Filesystem directory seperator
	FilesystemDirectorySeperator = string(os.PathSeparator)

	// Url directory seperator
	UrlDirectorySeperator = "/"

	// Web server default file
	WebServerDefaultFilename = "index.html"
)

func NewProvider(basePath string, useTempDir bool) *Provider {

	// create a unique temp directory
	baseDirHash := util.GetHash(basePath)
	tempDir := filepath.Join(os.TempDir(), baseDirHash)
	if useTempDir {
		util.CreateDirectory(tempDir)
	}

	return &Provider{
		basePath:   basePath,
		tempDir:    tempDir,
		useTempDir: useTempDir,
	}
}

type Provider struct {
	basePath   string
	tempDir    string
	useTempDir bool
}

func (provider *Provider) New(basePath string) *Provider {
	return NewProvider(basePath, provider.UseTempDir())
}

func (provider *Provider) BasePath() string {
	return provider.basePath
}

func (provider *Provider) UseTempDir() bool {
	return provider.useTempDir
}

func (provider *Provider) TempDir() string {
	return provider.tempDir
}

func (provider *Provider) GetWebRoute(pather Pather) string {

	switch pathType := pather.PathType(); pathType {
	case PatherTypeItem:
		return provider.getItemRoute(pather)
	case PatherTypeFile, PatherTypeIndex:
		return provider.getFileRoute(pather)
	default:
		panic(fmt.Sprintf("Unknown pather type %q", pathType))
	}

	panic("Unreachable. Unknown pather type")
}

func (provider *Provider) GetFilepath(pather Pather) string {

	switch pathType := pather.PathType(); pathType {
	case PatherTypeItem:
		return provider.GetRenderTargetPath(pather)
	case PatherTypeFile:
		return pather.Path()
	default:
		panic(fmt.Sprintf("Unknown pather type %q", pathType))
	}

	panic("Unreachable. Unknown pather type")
}

func (provider *Provider) GetRenderTargetPath(pather Pather) string {

	itemDirectoryRelative := provider.getRelativePath(pather.Directory())
	relativeRenderTargetPath := filepath.Join(itemDirectoryRelative, WebServerDefaultFilename)

	var renderTargetPath string
	if provider.UseTempDir() {

		renderTargetPath = filepath.Join(provider.TempDir(), relativeRenderTargetPath)

		// make sure the directory exists
		util.CreateDirectory(filepath.Dir(renderTargetPath))

	} else {

		renderTargetPath = filepath.Join(provider.basePath, relativeRenderTargetPath)

	}

	return renderTargetPath
}

func (provider *Provider) getItemRoute(pather Pather) string {
	absoluteTargetFilesystemPath := provider.GetRenderTargetPath(pather)
	itemRoute := provider.getRouteFromFilepath(absoluteTargetFilesystemPath)

	return itemRoute
}

func (provider *Provider) getFileRoute(pather Pather) string {
	absoluteFilepath := provider.getRouteFromFilepath(pather.Path())
	return provider.getRouteFromFilepath(absoluteFilepath)
}

func (provider *Provider) getRouteFromFilepath(path string) string {
	relativeFilepath := provider.getRelativePath(path)

	// remove temp dir
	if provider.UseTempDir() {
		relativeFilepath = strings.TrimPrefix(relativeFilepath, provider.TempDir())
	}

	// filepath to route
	route := filepath.ToSlash(relativeFilepath)

	// Trim leading slash
	route = StripLeadingUrlDirectorySeperator(route)

	return route
}

func (provider *Provider) getRelativePath(filepath string) string {
	return strings.Replace(filepath, provider.basePath, "", 1)
}
<commit_msg>Escape special characters in the web routes<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package path

import (
	"fmt"
	"github.com/andreaskoch/allmark/util"
	"os"
	"path/filepath"
	"strings"
)

const (
	// Filesystem directory seperator
	FilesystemDirectorySeperator = string(os.PathSeparator)

	// Url directory seperator
	UrlDirectorySeperator = "/"

	// Web server default file
	WebServerDefaultFilename = "index.html"
)

func NewProvider(basePath string, useTempDir bool) *Provider {

	// create a unique temp directory
	baseDirHash := util.GetHash(basePath)
	tempDir := filepath.Join(os.TempDir(), baseDirHash)
	if useTempDir {
		util.CreateDirectory(tempDir)
	}

	return &Provider{
		basePath:   basePath,
		tempDir:    tempDir,
		useTempDir: useTempDir,
	}
}

type Provider struct {
	basePath   string
	tempDir    string
	useTempDir bool
}

func (provider *Provider) New(basePath string) *Provider {
	return NewProvider(basePath, provider.UseTempDir())
}

func (provider *Provider) BasePath() string {
	return provider.basePath
}

func (provider *Provider) UseTempDir() bool {
	return provider.useTempDir
}

func (provider *Provider) TempDir() string {
	return provider.tempDir
}

func (provider *Provider) GetWebRoute(pather Pather) string {

	switch pathType := pather.PathType(); pathType {
	case PatherTypeItem:
		return replaceSpecialUrlCharacters(provider.getItemRoute(pather))
	case PatherTypeFile, PatherTypeIndex:
		return replaceSpecialUrlCharacters(provider.getFileRoute(pather))
	default:
		panic(fmt.Sprintf("Unknown pather type %q", pathType))
	}

	panic("Unreachable. Unknown pather type")
}

func (provider *Provider) GetFilepath(pather Pather) string {

	switch pathType := pather.PathType(); pathType {
	case PatherTypeItem:
		return provider.GetRenderTargetPath(pather)
	case PatherTypeFile:
		return pather.Path()
	default:
		panic(fmt.Sprintf("Unknown pather type %q", pathType))
	}

	panic("Unreachable. Unknown pather type")
}

func (provider *Provider) GetRenderTargetPath(pather Pather) string {

	itemDirectoryRelative := provider.getRelativePath(pather.Directory())
	relativeRenderTargetPath := filepath.Join(itemDirectoryRelative, WebServerDefaultFilename)

	var renderTargetPath string
	if provider.UseTempDir() {

		renderTargetPath = filepath.Join(provider.TempDir(), relativeRenderTargetPath)

		// make sure the directory exists
		util.CreateDirectory(filepath.Dir(renderTargetPath))

	} else {

		renderTargetPath = filepath.Join(provider.basePath, relativeRenderTargetPath)

	}

	return renderTargetPath
}

func (provider *Provider) getItemRoute(pather Pather) string {
	absoluteTargetFilesystemPath := provider.GetRenderTargetPath(pather)
	itemRoute := provider.getRouteFromFilepath(absoluteTargetFilesystemPath)

	return itemRoute
}

func (provider *Provider) getFileRoute(pather Pather) string {
	absoluteFilepath := provider.getRouteFromFilepath(pather.Path())
	return provider.getRouteFromFilepath(absoluteFilepath)
}

func (provider *Provider) getRouteFromFilepath(path string) string {
	relativeFilepath := provider.getRelativePath(path)

	// remove temp dir
	if provider.UseTempDir() {
		relativeFilepath = strings.TrimPrefix(relativeFilepath, provider.TempDir())
	}

	// filepath to route
	route := filepath.ToSlash(relativeFilepath)

	// Trim leading slash
	route = StripLeadingUrlDirectorySeperator(route)

	return route
}

func (provider *Provider) getRelativePath(filepath string) string {
	return strings.Replace(filepath, provider.basePath, "", 1)
}

func replaceSpecialUrlCharacters(url string) string {
	url = strings.Replace(url, "&", "&", -1)
	return url
}
<|endoftext|>


<commit_before>package api

import (
	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/middleware"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/setting"
)

func GetOrgQuotas(c *middleware.Context) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	query := m.GetOrgQuotasQuery{OrgId: c.ParamsInt64(":orgId")}

	if err := bus.Dispatch(&query); err != nil {
		return ApiError(500, "Failed to get org quotas", err)
	}

	return Json(200, query.Result)
}

func UpdateOrgQuota(c *middleware.Context, cmd m.UpdateOrgQuotaCmd) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	cmd.OrgId = c.ParamsInt64(":orgId")
	cmd.Target = c.Params(":target")

	if _, ok := m.QuotaToMap(setting.Quota.Org)[cmd.Target]; !ok {
		return ApiError(404, "Invalid quota target", nil)
	}

	if err := bus.Dispatch(&cmd); err != nil {
		return ApiError(500, "Failed to update org quotas", err)
	}
	return ApiSuccess("Organization quota updated")
}

func GetUserQuotas(c *middleware.Context) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	query := m.GetUserQuotasQuery{UserId: c.ParamsInt64(":id")}

	if err := bus.Dispatch(&query); err != nil {
		return ApiError(500, "Failed to get org quotas", err)
	}

	return Json(200, query.Result)
}

func UpdateUserQuota(c *middleware.Context, cmd m.UpdateUserQuotaCmd) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	cmd.UserId = c.ParamsInt64(":id")
	cmd.Target = c.Params(":target")

	if _, ok := m.QuotaToMap(setting.Quota.User)[cmd.Target]; !ok {
		return ApiError(404, "Invalid quota target", nil)
	}

	if err := bus.Dispatch(&cmd); err != nil {
		return ApiError(500, "Failed to update org quotas", err)
	}
	return ApiSuccess("Organization quota updated")
}
<commit_msg>fix getting default quota as map[string]int64<commit_after>package api

import (
	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/middleware"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/setting"
)

func GetOrgQuotas(c *middleware.Context) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	query := m.GetOrgQuotasQuery{OrgId: c.ParamsInt64(":orgId")}

	if err := bus.Dispatch(&query); err != nil {
		return ApiError(500, "Failed to get org quotas", err)
	}

	return Json(200, query.Result)
}

func UpdateOrgQuota(c *middleware.Context, cmd m.UpdateOrgQuotaCmd) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	cmd.OrgId = c.ParamsInt64(":orgId")
	cmd.Target = c.Params(":target")

	if _, ok := setting.Quota.Org.ToMap()[cmd.Target]; !ok {
		return ApiError(404, "Invalid quota target", nil)
	}

	if err := bus.Dispatch(&cmd); err != nil {
		return ApiError(500, "Failed to update org quotas", err)
	}
	return ApiSuccess("Organization quota updated")
}

func GetUserQuotas(c *middleware.Context) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	query := m.GetUserQuotasQuery{UserId: c.ParamsInt64(":id")}

	if err := bus.Dispatch(&query); err != nil {
		return ApiError(500, "Failed to get org quotas", err)
	}

	return Json(200, query.Result)
}

func UpdateUserQuota(c *middleware.Context, cmd m.UpdateUserQuotaCmd) Response {
	if !setting.Quota.Enabled {
		return ApiError(404, "Quotas not enabled", nil)
	}
	cmd.UserId = c.ParamsInt64(":id")
	cmd.Target = c.Params(":target")

	if _, ok := setting.Quota.User.ToMap()[cmd.Target]; !ok {
		return ApiError(404, "Invalid quota target", nil)
	}

	if err := bus.Dispatch(&cmd); err != nil {
		return ApiError(500, "Failed to update org quotas", err)
	}
	return ApiSuccess("Organization quota updated")
}
<|endoftext|>


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

// Adapted from encoding/xml/read_test.go.

// Package atom defines XML data structures for an Atom feed.
package atom

import (
	"encoding/xml"
	"time"
)

type Feed struct {
	XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
	Title   string   `xml:"title"`
	ID      string   `xml:"id"`
	Link    []Link   `xml:"link"`
	Updated TimeStr  `xml:"updated"`
	Author  *Person  `xml:"author"`
	Entry   []*Entry `xml:"entry"`
}

type Entry struct {
	Title     string  `xml:"title"`
	ID        string  `xml:"id"`
	Link      []Link  `xml:"link"`
	Published TimeStr `xml:"published"`
	Updated   TimeStr `xml:"updated"`
	Author    *Person `xml:"author"`
	Summary   *Text   `xml:"summary"`
	Content   *Text   `xml:"content"`
}

type Link struct {
	Rel  string `xml:"rel,attr"`
	Href string `xml:"href,attr"`
}

type Person struct {
	Name     string `xml:"name"`
	URI      string `xml:"uri,omitempty"`
	Email    string `xml:"email,omitempty"`
	InnerXML string `xml:",innerxml"`
}

type Text struct {
	Type string `xml:"type,attr"`
	Body string `xml:",chardata"`
}

type TimeStr string

func Time(t time.Time) TimeStr {
	return TimeStr(t.Format("2006-01-02T15:04:05-07:00"))
}
<commit_msg>go.blog/pkg/atom: remove package<commit_after><|endoftext|>


<commit_before>/*
 * Copyright © 2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 *
 * 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.
 *
 * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @license 	Apache-2.0
 */

package pkg

import (
	"net/http"
	"strconv"
)

func ParsePagination(r *http.Request, defaultLimit, defaultOffset, maxLimit int64) (int64, int64) {
	var offset, limit int64
	var err error

	if offsetParam := r.URL.Query().Get("offset"); offsetParam == "" {
		offset = defaultOffset
	} else {
		offset, err = strconv.ParseInt(offsetParam, 10, 64)
		if err != nil {
			offset = defaultOffset
		}
	}

	if limitParam := r.URL.Query().Get("limit"); limitParam == "" {
		limit = defaultLimit
	} else {
		limit, err = strconv.ParseInt(limitParam, 10, 64)
		if err != nil {
			limit = defaultLimit
		}
	}

	if limit > maxLimit {
		limit = maxLimit
	}

	if limit < 0 {
		limit = 0
	}

	if offset < 0 {
		offset = 0
	}

	return limit, offset
}
<commit_msg>pkg: remove unused code<commit_after><|endoftext|>


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

package pool

import (
	"fmt"
	"reflect"
	"sync"
)

// Pool is a bucketed pool for variably sized byte slices.
type Pool struct {
	buckets []sync.Pool
	sizes   []int
	// initialize is the function used to create an empty slice when none exist yet.
	initialize func(int) interface{}
}

// New returns a new Pool with size buckets for minSize to maxSize
// increasing by the given factor.
func New(minSize, maxSize int, factor float64, newFunc func(int) interface{}) *Pool {
	if minSize < 1 {
		panic("invalid minimum pool size")
	}
	if maxSize < 1 {
		panic("invalid maximum pool size")
	}
	if factor < 1 {
		panic("invalid factor")
	}

	var sizes []int

	for s := minSize; s <= maxSize; s = int(float64(s) * factor) {
		sizes = append(sizes, s)
	}

	p := &Pool{
		buckets:    make([]sync.Pool, len(sizes)),
		sizes:      sizes,
		initialize: newFunc,
	}

	return p
}

// Get returns a new byte slices that fits the given size.
func (p *Pool) Get(sz int) interface{} {
	for i, bktSize := range p.sizes {
		if sz > bktSize {
			continue
		}
		b := p.buckets[i].Get()
		if b == nil {
			b = p.initialize(bktSize)
		}
		return b
	}
	return p.initialize(sz)
}

// Put adds a slice to the right bucket in the pool.
func (p *Pool) Put(s interface{}) {
	slice := reflect.ValueOf(s)

	if slice.Kind() != reflect.Slice {
		panic(fmt.Sprintf("%+v is not a slice", slice))
	}
	for i, size := range p.sizes {
		if slice.Cap() > size {
			continue
		}
		p.buckets[i].Put(slice.Slice(0, 0).Interface())
	}
}
<commit_msg>rename initialize to make<commit_after>// Copyright 2017 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pool

import (
	"fmt"
	"reflect"
	"sync"
)

// Pool is a bucketed pool for variably sized byte slices.
type Pool struct {
	buckets []sync.Pool
	sizes   []int
	// make is the function used to create an empty slice when none exist yet.
	make func(int) interface{}
}

// New returns a new Pool with size buckets for minSize to maxSize
// increasing by the given factor.
func New(minSize, maxSize int, factor float64, makeFunc func(int) interface{}) *Pool {
	if minSize < 1 {
		panic("invalid minimum pool size")
	}
	if maxSize < 1 {
		panic("invalid maximum pool size")
	}
	if factor < 1 {
		panic("invalid factor")
	}

	var sizes []int

	for s := minSize; s <= maxSize; s = int(float64(s) * factor) {
		sizes = append(sizes, s)
	}

	p := &Pool{
		buckets: make([]sync.Pool, len(sizes)),
		sizes:   sizes,
		make:    makeFunc,
	}

	return p
}

// Get returns a new byte slices that fits the given size.
func (p *Pool) Get(sz int) interface{} {
	for i, bktSize := range p.sizes {
		if sz > bktSize {
			continue
		}
		b := p.buckets[i].Get()
		if b == nil {
			b = p.make(bktSize)
		}
		return b
	}
	return p.make(sz)
}

// Put adds a slice to the right bucket in the pool.
func (p *Pool) Put(s interface{}) {
	slice := reflect.ValueOf(s)

	if slice.Kind() != reflect.Slice {
		panic(fmt.Sprintf("%+v is not a slice", slice))
	}
	for i, size := range p.sizes {
		if slice.Cap() > size {
			continue
		}
		p.buckets[i].Put(slice.Slice(0, 0).Interface())
	}
}
<|endoftext|>


<commit_before>package player

import "github.com/lean-poker/poker-player-go/leanpoker"
import s "github.com/lean-poker/poker-player-go/strategies"

const VERSION = "Pasha Team Player 0.0.3"

func BetRequest(state *leanpoker.Game) int {
	return s.Default(state)
}

func Showdown(state *leanpoker.Game) {

}

func Version() string {
	return VERSION
}
<commit_msg>state replaced to game.<commit_after>package player

import "github.com/lean-poker/poker-player-go/leanpoker"
import s "github.com/lean-poker/poker-player-go/strategies"

const VERSION = "Pasha Team Player 0.0.3"

func BetRequest(game *leanpoker.Game) int {
	return s.Default(game)
}

func Showdown(game *leanpoker.Game) {

}

func Version() string {
	return VERSION
}
<|endoftext|>