<commit_before>// Copyright 2016 CoreOS, Inc.
//
// 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 ignition

import (
	"fmt"
	"strings"

	"github.com/coreos/go-semver/semver"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/kola/register"
)

func init() {
	// Reformat the root as btrfs
	btrfsConfig := `{
		               "ignition": {
		                   "version": "2.0.0"
		               },
		               "storage": {
		                   "filesystems": [
		                       {
		                           "mount": {
		                               "device": "/dev/disk/by-label/ROOT",
		                               "format": "btrfs",
		                               "create": {
		                                   "force": true,
		                                   "options": [
		                                       "--label=ROOT"
		                                   ]
		                               }
		                           }
		                       }
		                   ]
		               }
		           }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.btrfsroot.aws",
		Run:         btrfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    btrfsConfig,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.btrfsroot.gce",
		Run:         btrfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    btrfsConfig,
	})

	// Reformat the root as xfs
	xfsConfig := `{
		             "ignition": {
		                 "version": "2.0.0"
		             },
		             "storage": {
		                 "filesystems": [
		                     {
		                         "mount": {
		                             "device": "/dev/disk/by-partlabel/ROOT",
		                             "format": "xfs",
		                             "create": {
		                                 "force": true,
		                                 "options": [
		                                     "-L", "ROOT"
		                                 ]
		                             }
		                         }
		                     }
		                 ]
		             }
		         }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.xfsroot.aws",
		Run:         xfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    xfsConfig,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.xfsroot.gce",
		Run:         xfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    xfsConfig,
	})

	// Reformat the root as ext4
	ext4Config := `{
		             "ignition": {
		                 "version": "2.0.0"
		             },
		             "storage": {
		                 "filesystems": [
		                     {
		                         "mount": {
		                             "device": "/dev/disk/by-partlabel/ROOT",
		                             "format": "ext4",
		                             "create": {
		                                 "force": true,
		                                 "options": [
		                                     "-L", "ROOT"
		                                 ]
		                             }
		                         }
		                     }
		                 ]
		             }
		         }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4Root.aws",
		Run:         ext4Root,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4Root.gce",
		Run:         ext4Root,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4CheckExisting.aws",
		Run:         ext4CheckExisting,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4CheckExisting.gce",
		Run:         ext4CheckExisting,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    ext4Config,
	})
}

func btrfsRoot(c cluster.TestCluster) error {
	return testRoot(c, "btrfs")
}

func xfsRoot(c cluster.TestCluster) error {
	return testRoot(c, "xfs")
}

func ext4Root(c cluster.TestCluster) error {
	// Since the image's root partition is formatted to ext4 by default,
	// this test wont be able to differentiate between the original filesystem
	// and a newly created one. If mkfs.ext4 never ran, it would still pass.
	// It will ensure that if mkfs.ext4 ran, it ran successfully.
	return testRoot(c, "ext4")
}

func testRoot(c cluster.TestCluster, fs string) error {
	m := c.Machines()[0]

	out, err := m.SSH("findmnt --noheadings --output FSTYPE --target /")
	if err != nil {
		return fmt.Errorf("failed to run findmnt: %s: %v", out, err)
	}

	if string(out) != fs {
		return fmt.Errorf("root wasn't correctly reformatted:\n%s", out)
	}

	return nil
}

func ext4CheckExisting(c cluster.TestCluster) error {
	m := c.Machines()[0]

	// Redirect /dev/null to stdin so isatty(stdin) fails and the -p flag can be
	// checked
	out, err := m.SSH("sudo mkfs.ext4 -p /dev/disk/by-partlabel/ROOT < /dev/null")
	if err == nil {
		return fmt.Errorf("mkfs.ext4 returned sucessfully when it should have failed")
	}

	if !strings.HasPrefix(string(out), "/dev/disk/by-partlabel/ROOT contains a ext4 file system labelled 'ROOT'") {
		return fmt.Errorf("mkfs.ext4 did not check for existing filesystems.\nmkfs.ext4: %s", out)
	}

	return nil
}
<commit_msg>kola: fix min version for ext4 force tests<commit_after>// Copyright 2016 CoreOS, Inc.
//
// 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 ignition

import (
	"fmt"
	"strings"

	"github.com/coreos/go-semver/semver"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/kola/register"
)

func init() {
	// Reformat the root as btrfs
	btrfsConfig := `{
		               "ignition": {
		                   "version": "2.0.0"
		               },
		               "storage": {
		                   "filesystems": [
		                       {
		                           "mount": {
		                               "device": "/dev/disk/by-label/ROOT",
		                               "format": "btrfs",
		                               "create": {
		                                   "force": true,
		                                   "options": [
		                                       "--label=ROOT"
		                                   ]
		                               }
		                           }
		                       }
		                   ]
		               }
		           }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.btrfsroot.aws",
		Run:         btrfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    btrfsConfig,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.btrfsroot.gce",
		Run:         btrfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    btrfsConfig,
	})

	// Reformat the root as xfs
	xfsConfig := `{
		             "ignition": {
		                 "version": "2.0.0"
		             },
		             "storage": {
		                 "filesystems": [
		                     {
		                         "mount": {
		                             "device": "/dev/disk/by-partlabel/ROOT",
		                             "format": "xfs",
		                             "create": {
		                                 "force": true,
		                                 "options": [
		                                     "-L", "ROOT"
		                                 ]
		                             }
		                         }
		                     }
		                 ]
		             }
		         }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.xfsroot.aws",
		Run:         xfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    xfsConfig,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.xfsroot.gce",
		Run:         xfsRoot,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    xfsConfig,
	})

	// Reformat the root as ext4
	ext4Config := `{
		             "ignition": {
		                 "version": "2.0.0"
		             },
		             "storage": {
		                 "filesystems": [
		                     {
		                         "mount": {
		                             "device": "/dev/disk/by-partlabel/ROOT",
		                             "format": "ext4",
		                             "create": {
		                                 "force": true,
		                                 "options": [
		                                     "-L", "ROOT"
		                                 ]
		                             }
		                         }
		                     }
		                 ]
		             }
		         }`
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4Root.aws",
		Run:         ext4Root,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1010},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4Root.gce",
		Run:         ext4Root,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1045},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4CheckExisting.aws",
		Run:         ext4CheckExisting,
		ClusterSize: 1,
		Platforms:   []string{"aws"},
		MinVersion:  semver.Version{Major: 1081},
		UserData:    ext4Config,
	})
	register.Register(&register.Test{
		Name:        "coreos.ignition.v2.ext4CheckExisting.gce",
		Run:         ext4CheckExisting,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		MinVersion:  semver.Version{Major: 1081},
		UserData:    ext4Config,
	})
}

func btrfsRoot(c cluster.TestCluster) error {
	return testRoot(c, "btrfs")
}

func xfsRoot(c cluster.TestCluster) error {
	return testRoot(c, "xfs")
}

func ext4Root(c cluster.TestCluster) error {
	// Since the image's root partition is formatted to ext4 by default,
	// this test wont be able to differentiate between the original filesystem
	// and a newly created one. If mkfs.ext4 never ran, it would still pass.
	// It will ensure that if mkfs.ext4 ran, it ran successfully.
	return testRoot(c, "ext4")
}

func testRoot(c cluster.TestCluster, fs string) error {
	m := c.Machines()[0]

	out, err := m.SSH("findmnt --noheadings --output FSTYPE --target /")
	if err != nil {
		return fmt.Errorf("failed to run findmnt: %s: %v", out, err)
	}

	if string(out) != fs {
		return fmt.Errorf("root wasn't correctly reformatted:\n%s", out)
	}

	return nil
}

func ext4CheckExisting(c cluster.TestCluster) error {
	m := c.Machines()[0]

	// Redirect /dev/null to stdin so isatty(stdin) fails and the -p flag can be
	// checked
	out, err := m.SSH("sudo mkfs.ext4 -p /dev/disk/by-partlabel/ROOT < /dev/null")
	if err == nil {
		return fmt.Errorf("mkfs.ext4 returned sucessfully when it should have failed")
	}

	if !strings.HasPrefix(string(out), "/dev/disk/by-partlabel/ROOT contains a ext4 file system labelled 'ROOT'") {
		return fmt.Errorf("mkfs.ext4 did not check for existing filesystems.\nmkfs.ext4: %s", out)
	}

	return nil
}
<|endoftext|>


<commit_before>package provision

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/samalba/dockerclient"
)

func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth.Options) error {
	if !swarmOptions.IsSwarm {
		return nil
	}

	log.Info("Configuring swarm...")

	ip, err := p.GetDriver().GetIP()
	if err != nil {
		return err
	}

	u, err := url.Parse(swarmOptions.Host)
	if err != nil {
		return err
	}

	parts := strings.Split(u.Host, ":")
	port := parts[1]

	dockerPort := "2376"
	dockerDir := p.GetDockerOptionsDir()
	dockerHost := &mcndockerclient.RemoteDocker{
		HostURL:    fmt.Sprintf("tcp://%s:%s", ip, dockerPort),
		AuthOption: &authOptions,
	}
	advertiseInfo := fmt.Sprintf("%s:%s", ip, dockerPort)

	if swarmOptions.Master {
		cmd := fmt.Sprintf("manage --tlsverify --tlscacert=%s --tlscert=%s --tlskey=%s -H %s --strategy %s --advertise %s",
			authOptions.CaCertRemotePath,
			authOptions.ServerCertRemotePath,
			authOptions.ServerKeyRemotePath,
			swarmOptions.Host,
			swarmOptions.Strategy,
			advertiseInfo,
		)

		cmdMaster := strings.Fields(cmd)
		for _, option := range swarmOptions.ArbitraryFlags {
			cmdMaster = append(cmdMaster, "--"+option)
		}

		//Discovery must be at end of command
		cmdMaster = append(cmdMaster, swarmOptions.Discovery)

		hostBind := fmt.Sprintf("%s:%s", dockerDir, dockerDir)
		masterHostConfig := dockerclient.HostConfig{
			RestartPolicy: dockerclient.RestartPolicy{
				Name:              "always",
				MaximumRetryCount: 0,
			},
			Binds:        []string{hostBind},
			PortBindings: map[string][]dockerclient.PortBinding{"3376/tcp": {{"", port}}},
			NetworkMode:  "host",
		}

		swarmMasterConfig := &dockerclient.ContainerConfig{
			Image: swarmOptions.Image,
			Env:   swarmOptions.Env,
			ExposedPorts: map[string]struct{}{
				"2375/tcp": {},
				"3376/tcp": {},
			},
			Cmd:        cmdMaster,
			HostConfig: masterHostConfig,
		}

		err = mcndockerclient.CreateContainer(dockerHost, swarmMasterConfig, "swarm-agent-master")
		if err != nil {
			return err
		}
	}

	workerHostConfig := dockerclient.HostConfig{
		RestartPolicy: dockerclient.RestartPolicy{
			Name:              "always",
			MaximumRetryCount: 0,
		},
		NetworkMode: "host",
	}

	swarmWorkerConfig := &dockerclient.ContainerConfig{
		Image: swarmOptions.Image,
		Env:   swarmOptions.Env,
		Cmd: []string{
			"join",
			"--advertise",
			advertiseInfo,
			swarmOptions.Discovery,
		},
		HostConfig: workerHostConfig,
	}

	return mcndockerclient.CreateContainer(dockerHost, swarmWorkerConfig, "swarm-agent")
}
<commit_msg>set swarm manage to advertise on 3376<commit_after>package provision

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/samalba/dockerclient"
)

func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth.Options) error {
	if !swarmOptions.IsSwarm {
		return nil
	}

	log.Info("Configuring swarm...")

	ip, err := p.GetDriver().GetIP()
	if err != nil {
		return err
	}

	u, err := url.Parse(swarmOptions.Host)
	if err != nil {
		return err
	}

	parts := strings.Split(u.Host, ":")
	port := parts[1]

	dockerPort := "2376"
	dockerDir := p.GetDockerOptionsDir()
	dockerHost := &mcndockerclient.RemoteDocker{
		HostURL:    fmt.Sprintf("tcp://%s:%s", ip, dockerPort),
		AuthOption: &authOptions,
	}
	advertiseInfo := fmt.Sprintf("%s:%s", ip, dockerPort)

	if swarmOptions.Master {
		advertiseMasterInfo := fmt.Sprintf("%s:%s", ip, "3376")
		cmd := fmt.Sprintf("manage --tlsverify --tlscacert=%s --tlscert=%s --tlskey=%s -H %s --strategy %s --advertise %s",
			authOptions.CaCertRemotePath,
			authOptions.ServerCertRemotePath,
			authOptions.ServerKeyRemotePath,
			swarmOptions.Host,
			swarmOptions.Strategy,
			advertiseMasterInfo,
		)

		cmdMaster := strings.Fields(cmd)
		for _, option := range swarmOptions.ArbitraryFlags {
			cmdMaster = append(cmdMaster, "--"+option)
		}

		//Discovery must be at end of command
		cmdMaster = append(cmdMaster, swarmOptions.Discovery)

		hostBind := fmt.Sprintf("%s:%s", dockerDir, dockerDir)
		masterHostConfig := dockerclient.HostConfig{
			RestartPolicy: dockerclient.RestartPolicy{
				Name:              "always",
				MaximumRetryCount: 0,
			},
			Binds:        []string{hostBind},
			PortBindings: map[string][]dockerclient.PortBinding{"3376/tcp": {{"", port}}},
			NetworkMode:  "host",
		}

		swarmMasterConfig := &dockerclient.ContainerConfig{
			Image: swarmOptions.Image,
			Env:   swarmOptions.Env,
			ExposedPorts: map[string]struct{}{
				"2375/tcp": {},
				"3376/tcp": {},
			},
			Cmd:        cmdMaster,
			HostConfig: masterHostConfig,
		}

		err = mcndockerclient.CreateContainer(dockerHost, swarmMasterConfig, "swarm-agent-master")
		if err != nil {
			return err
		}
	}

	workerHostConfig := dockerclient.HostConfig{
		RestartPolicy: dockerclient.RestartPolicy{
			Name:              "always",
			MaximumRetryCount: 0,
		},
		NetworkMode: "host",
	}

	swarmWorkerConfig := &dockerclient.ContainerConfig{
		Image: swarmOptions.Image,
		Env:   swarmOptions.Env,
		Cmd: []string{
			"join",
			"--advertise",
			advertiseInfo,
			swarmOptions.Discovery,
		},
		HostConfig: workerHostConfig,
	}

	return mcndockerclient.CreateContainer(dockerHost, swarmWorkerConfig, "swarm-agent")
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"os"
	"regexp"
	"strings"
	"time"

	"errors"
	"github.com/bitly/go-simplejson"
	"github.com/hashicorp/go-version"
	"github.com/phase2/rig/util"
)

// Machine is the struct for encapsulating operations on a Docker Machine
type Machine struct {
	Name        string
	out         *util.RigLogger
	inspectData *simplejson.Json
}

// Create will generate a new Docker Machine configured according to user specification
func (m *Machine) Create(driver string, cpuCount string, memSize string, diskSize string) error {
	m.out.Info("Creating a %s machine named '%s' with CPU(%s) MEM(%s) DISK(%s)...", driver, m.Name, cpuCount, memSize, diskSize)

	boot2dockerURL := "https://github.com/boot2docker/boot2docker/releases/download/v" + util.GetRawCurrentDockerVersion() + "/boot2docker.iso"

	var create util.Executor

	switch driver {
	case util.VirtualBox:
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=virtualbox",
			"--virtualbox-boot2docker-url="+boot2dockerURL,
			"--virtualbox-memory="+memSize,
			"--virtualbox-cpu-count="+cpuCount,
			"--virtualbox-disk-size="+diskSize,
			"--virtualbox-host-dns-resolver=true",
			"--engine-opt", "dns=172.17.0.1",
		)
	case util.VMWare:
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=vmwarefusion",
			"--vmwarefusion-boot2docker-url="+boot2dockerURL,
			"--vmwarefusion-memory-size="+memSize,
			"--vmwarefusion-cpu-count="+cpuCount,
			"--vmwarefusion-disk-size="+diskSize,
			"--engine-opt", "dns=172.17.0.1",
		)
	case util.Xhyve:
		if err := m.CheckXhyveRequirements(); err != nil {
			return err
		}
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=xhyve",
			"--xhyve-boot2docker-url="+boot2dockerURL,
			"--xhyve-memory-size="+memSize,
			"--xhyve-cpu-count="+cpuCount,
			"--xhyve-disk-size="+diskSize,
			"--engine-opt", "dns=172.17.0.1",
		)
	}

	if err := create.Execute(false); err != nil {
		return fmt.Errorf("error creating machine '%s': %s", m.Name, err)
	}

	m.out.Info("Created docker-machine named '%s'...", m.Name)
	return nil
}

// CheckXhyveRequirements verifies that the correct xhyve environment exists
func (m Machine) CheckXhyveRequirements() error {
	// Is xhyve installed locally
	if err := util.Command("which", "xhyve").Run(); err != nil {
		return fmt.Errorf("xhyve is not installed. Install it with 'brew install xhyve'")
	}

	// Is docker-machine-driver-xhyve installed locally
	if err := util.Command("which", "docker-machine-driver-xhyve").Run(); err != nil {
		return fmt.Errorf("docker-machine-driver-xhyve is not installed. Install it with 'brew install docker-machine-driver-xhyve'")
	}

	return nil
}

// Start boots the Docker Machine
func (m Machine) Start() error {
	if !m.IsRunning() {
		m.out.Verbose("The machine '%s' is not running, starting...", m.Name)

		if err := util.StreamCommand("docker-machine", "start", m.Name); err != nil {
			return fmt.Errorf("error starting machine '%s': %s", m.Name, err)
		}

		return m.WaitForDev()
	}

	return nil
}

// Stop halts the Docker Machine
func (m Machine) Stop() error {
	if m.IsRunning() {
		return util.StreamCommand("docker-machine", "stop", m.Name)
	}
	return nil
}

// Remove deleted the Docker Machine
func (m Machine) Remove() error {
	return util.StreamCommand("docker-machine", "rm", "-y", m.Name)
}

// WaitForDev will wait a period of time for communication with the docker daemon to be established
func (m Machine) WaitForDev() error {
	maxTries := 10
	sleepSecs := 3

	for i := 1; i <= maxTries; i++ {
		m.SetEnv()
		if err := util.Command("docker", "ps").Run(); err == nil {
			m.out.Verbose("Machine '%s' has started", m.Name)
			return nil
		}
		m.out.Warning("Docker daemon not running! Trying again in %d seconds.  Try %d of %d. \n", sleepSecs, i, maxTries)
		time.Sleep(time.Duration(sleepSecs) * time.Second)
	}

	return fmt.Errorf("docker daemon failed to start")
}

// SetEnv will set the Docker proxy variables that determine which machine the docker command communicates
func (m Machine) SetEnv() {
	if js := m.GetData(); js != nil {
		tlsVerify := 0
		if js.Get("HostOptions").Get("EngineOptions").Get("TlsVerify").MustBool() {
			tlsVerify = 1
		}
		os.Setenv("DOCKER_TLS_VERIFY", fmt.Sprintf("%d", tlsVerify))
		os.Setenv("DOCKER_HOST", fmt.Sprintf("tcp://%s:2376", js.Get("Driver").Get("IPAddress").MustString()))
		os.Setenv("DOCKER_MACHINE_NAME", js.Get("Driver").Get("MachineName").MustString())
		os.Setenv("DOCKER_CERT_PATH", js.Get("HostOptions").Get("AuthOptions").Get("StorePath").MustString())
	}
}

// UnsetEnv will remove the Docker proxy variables
func (m Machine) UnsetEnv() {
	os.Unsetenv("DOCKER_TLS_VERIFY")
	os.Unsetenv("DOCKER_HOST")
	os.Unsetenv("DOCKER_CERT_PATH")
	os.Unsetenv("DOCKER_MACHINE_NAME")
}

// Exists determines if the Docker Machine exist
func (m Machine) Exists() bool {
	if err := util.Command("docker-machine", "status", m.Name).Run(); err != nil {
		return false
	}
	return true
}

// IsRunning returns the Docker Machine running status
func (m Machine) IsRunning() bool {
	if err := util.Command("docker-machine", "env", m.Name).Run(); err != nil {
		return false
	}
	return true
}

// GetData will inspect the Docker Machine and return the parsed JSON describing the machine
func (m *Machine) GetData() *simplejson.Json {
	if m.inspectData != nil {
		return m.inspectData
	}

	if inspect, inspectErr := util.Command("docker-machine", "inspect", m.Name).Output(); inspectErr == nil {
		if js, jsonErr := simplejson.NewJson(inspect); jsonErr != nil {
			m.out.Channel.Error.Fatalf("Failed to parse '%s' JSON: %s", m.Name, jsonErr)
		} else {
			m.inspectData = js
			return m.inspectData
		}
	}
	return nil
}

// GetIP returns the IP address for the Docker Machine
func (m Machine) GetIP() string {
	return m.GetData().Get("Driver").Get("IPAddress").MustString()
}

// GetHostDNSResolver checks if the VirtualBox host DNS resolver is working. This should work okay
// for VMware or other machines without the option, too.
func (m Machine) GetHostDNSResolver() bool {
	return m.GetData().Get("Driver").Get("HostDNSResolver").MustBool(false)
}

// GetBridgeIP returns the Bridge IP by looking for a bip= option
func (m Machine) GetBridgeIP() string {
	ip := "172.17.0.1"
	r := regexp.MustCompile("bip=([0-9.]+)/[0-9+]")
	var matches []string

	options := m.GetData().Get("HostOptions").Get("EngineOptions").Get("ArbitraryFlags").MustArray()

	for _, option := range options {
		matches = r.FindStringSubmatch(option.(string))
		if len(matches) > 1 {
			ip = matches[1]
		}
	}

	return ip
}

// GetDockerVersion returns the Version of Docker running within Docker Machine
func (m Machine) GetDockerVersion() (*version.Version, error) {
	b2dOutput, err := util.Command("docker-machine", "version", m.Name).CombinedOutput()
	if err != nil {
		return nil, errors.New(strings.TrimSpace(string(b2dOutput)))
	}
	b2dVersion := strings.TrimSpace(string(b2dOutput))
	return version.Must(version.NewVersion(b2dVersion)), nil
}

// GetDriver returns the virtualization driver name
func (m Machine) GetDriver() string {
	return m.GetData().Get("DriverName").MustString()
}

// IsXhyve returns if the virt driver is xhyve
func (m Machine) IsXhyve() bool {
	return m.GetDriver() == util.Xhyve
}

// GetCPU returns the number of configured CPU for this Docker Machine
func (m Machine) GetCPU() int {
	return m.GetData().Get("Driver").Get("CPU").MustInt()
}

// GetMemory returns the amount of configured memory for this Docker Machine
func (m Machine) GetMemory() int {
	return m.GetData().Get("Driver").Get("Memory").MustInt()
}

// GetDisk returns the disk size in MB
func (m Machine) GetDisk() int {
	return m.GetData().Get("Driver").Get("DiskSize").MustInt()
}

// GetDiskInGB returns the disk size in GB
func (m Machine) GetDiskInGB() int {
	return m.GetDisk() / 1000
}

// GetSysctl returns the configured value for the provided sysctl setting on the Docker Machine
func (m Machine) GetSysctl(setting string) (string, error) {
	output, err := util.Command("docker-machine", "ssh", m.Name, "sudo", "sysctl", "-n", setting).CombinedOutput()
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(output)), nil
}

// SetSysctl sets the sysctl setting on the Docker Machine
func (m Machine) SetSysctl(key string, val string) error {
	cmd := fmt.Sprintf("sudo sysctl -w %s=%s", key, val)
	m.out.Verbose("Modifying Docker Machine kernel settings: %s", cmd)
	_, err := util.Command("docker-machine", "ssh", m.Name, cmd).CombinedOutput()
	return err
}
<commit_msg>Machine data caching (#125)<commit_after>package commands

import (
	"fmt"
	"os"
	"regexp"
	"strings"
	"time"

	"errors"
	"github.com/bitly/go-simplejson"
	"github.com/hashicorp/go-version"
	"github.com/phase2/rig/util"
)

// Machine is the struct for encapsulating operations on a Docker Machine
type Machine struct {
	Name        string
	out         *util.RigLogger
	inspectData *simplejson.Json
}

// Create will generate a new Docker Machine configured according to user specification
func (m *Machine) Create(driver string, cpuCount string, memSize string, diskSize string) error {
	m.out.Info("Creating a %s machine named '%s' with CPU(%s) MEM(%s) DISK(%s)...", driver, m.Name, cpuCount, memSize, diskSize)

	boot2dockerURL := "https://github.com/boot2docker/boot2docker/releases/download/v" + util.GetRawCurrentDockerVersion() + "/boot2docker.iso"

	var create util.Executor

	switch driver {
	case util.VirtualBox:
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=virtualbox",
			"--virtualbox-boot2docker-url="+boot2dockerURL,
			"--virtualbox-memory="+memSize,
			"--virtualbox-cpu-count="+cpuCount,
			"--virtualbox-disk-size="+diskSize,
			"--virtualbox-host-dns-resolver=true",
			"--engine-opt", "dns=172.17.0.1",
		)
	case util.VMWare:
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=vmwarefusion",
			"--vmwarefusion-boot2docker-url="+boot2dockerURL,
			"--vmwarefusion-memory-size="+memSize,
			"--vmwarefusion-cpu-count="+cpuCount,
			"--vmwarefusion-disk-size="+diskSize,
			"--engine-opt", "dns=172.17.0.1",
		)
	case util.Xhyve:
		if err := m.CheckXhyveRequirements(); err != nil {
			return err
		}
		create = util.Command(
			"docker-machine",
			"create", m.Name,
			"--driver=xhyve",
			"--xhyve-boot2docker-url="+boot2dockerURL,
			"--xhyve-memory-size="+memSize,
			"--xhyve-cpu-count="+cpuCount,
			"--xhyve-disk-size="+diskSize,
			"--engine-opt", "dns=172.17.0.1",
		)
	}

	if err := create.Execute(false); err != nil {
		return fmt.Errorf("error creating machine '%s': %s", m.Name, err)
	}

	m.out.Info("Created docker-machine named '%s'...", m.Name)
	return nil
}

// CheckXhyveRequirements verifies that the correct xhyve environment exists
func (m *Machine) CheckXhyveRequirements() error {
	// Is xhyve installed locally
	if err := util.Command("which", "xhyve").Run(); err != nil {
		return fmt.Errorf("xhyve is not installed. Install it with 'brew install xhyve'")
	}

	// Is docker-machine-driver-xhyve installed locally
	if err := util.Command("which", "docker-machine-driver-xhyve").Run(); err != nil {
		return fmt.Errorf("docker-machine-driver-xhyve is not installed. Install it with 'brew install docker-machine-driver-xhyve'")
	}

	return nil
}

// Start boots the Docker Machine
func (m *Machine) Start() error {
	if !m.IsRunning() {
		m.out.Verbose("The machine '%s' is not running, starting...", m.Name)

		if err := util.StreamCommand("docker-machine", "start", m.Name); err != nil {
			return fmt.Errorf("error starting machine '%s': %s", m.Name, err)
		}

		return m.WaitForDev()
	}

	return nil
}

// Stop halts the Docker Machine
func (m *Machine) Stop() error {
	if m.IsRunning() {
		return util.StreamCommand("docker-machine", "stop", m.Name)
	}
	return nil
}

// Remove deleted the Docker Machine
func (m *Machine) Remove() error {
	return util.StreamCommand("docker-machine", "rm", "-y", m.Name)
}

// WaitForDev will wait a period of time for communication with the docker daemon to be established
func (m *Machine) WaitForDev() error {
	maxTries := 10
	sleepSecs := 3

	for i := 1; i <= maxTries; i++ {
		m.SetEnv()
		if err := util.Command("docker", "ps").Run(); err == nil {
			m.out.Verbose("Machine '%s' has started", m.Name)
			return nil
		}
		m.out.Warning("Docker daemon not running! Trying again in %d seconds.  Try %d of %d. \n", sleepSecs, i, maxTries)
		time.Sleep(time.Duration(sleepSecs) * time.Second)
	}

	return fmt.Errorf("docker daemon failed to start")
}

// SetEnv will set the Docker proxy variables that determine which machine the docker command communicates
func (m *Machine) SetEnv() {
	if js := m.GetData(); js != nil {
		tlsVerify := 0
		if js.Get("HostOptions").Get("EngineOptions").Get("TlsVerify").MustBool() {
			tlsVerify = 1
		}
		os.Setenv("DOCKER_TLS_VERIFY", fmt.Sprintf("%d", tlsVerify))
		os.Setenv("DOCKER_HOST", fmt.Sprintf("tcp://%s:2376", js.Get("Driver").Get("IPAddress").MustString()))
		os.Setenv("DOCKER_MACHINE_NAME", js.Get("Driver").Get("MachineName").MustString())
		os.Setenv("DOCKER_CERT_PATH", js.Get("HostOptions").Get("AuthOptions").Get("StorePath").MustString())
	}
}

// UnsetEnv will remove the Docker proxy variables
func (m *Machine) UnsetEnv() {
	os.Unsetenv("DOCKER_TLS_VERIFY")
	os.Unsetenv("DOCKER_HOST")
	os.Unsetenv("DOCKER_CERT_PATH")
	os.Unsetenv("DOCKER_MACHINE_NAME")
}

// Exists determines if the Docker Machine exist
func (m *Machine) Exists() bool {
	if err := util.Command("docker-machine", "status", m.Name).Run(); err != nil {
		return false
	}
	return true
}

// IsRunning returns the Docker Machine running status
func (m *Machine) IsRunning() bool {
	if err := util.Command("docker-machine", "env", m.Name).Run(); err != nil {
		return false
	}
	return true
}

// GetData will inspect the Docker Machine and return the parsed JSON describing the machine
func (m *Machine) GetData() *simplejson.Json {
	if m.inspectData != nil {
		return m.inspectData
	}

	if inspect, inspectErr := util.Command("docker-machine", "inspect", m.Name).Output(); inspectErr == nil {
		if js, jsonErr := simplejson.NewJson(inspect); jsonErr != nil {
			m.out.Channel.Error.Fatalf("Failed to parse '%s' JSON: %s", m.Name, jsonErr)
		} else {
			m.inspectData = js
			return m.inspectData
		}
	}
	return nil
}

// GetIP returns the IP address for the Docker Machine
func (m *Machine) GetIP() string {
	return m.GetData().Get("Driver").Get("IPAddress").MustString()
}

// GetHostDNSResolver checks if the VirtualBox host DNS resolver is working. This should work okay
// for VMware or other machines without the option, too.
func (m *Machine) GetHostDNSResolver() bool {
	return m.GetData().Get("Driver").Get("HostDNSResolver").MustBool(false)
}

// GetBridgeIP returns the Bridge IP by looking for a bip= option
func (m *Machine) GetBridgeIP() string {
	ip := "172.17.0.1"
	r := regexp.MustCompile("bip=([0-9.]+)/[0-9+]")
	var matches []string

	options := m.GetData().Get("HostOptions").Get("EngineOptions").Get("ArbitraryFlags").MustArray()

	for _, option := range options {
		matches = r.FindStringSubmatch(option.(string))
		if len(matches) > 1 {
			ip = matches[1]
		}
	}

	return ip
}

// GetDockerVersion returns the Version of Docker running within Docker Machine
func (m *Machine) GetDockerVersion() (*version.Version, error) {
	b2dOutput, err := util.Command("docker-machine", "version", m.Name).CombinedOutput()
	if err != nil {
		return nil, errors.New(strings.TrimSpace(string(b2dOutput)))
	}
	b2dVersion := strings.TrimSpace(string(b2dOutput))
	return version.Must(version.NewVersion(b2dVersion)), nil
}

// GetDriver returns the virtualization driver name
func (m *Machine) GetDriver() string {
	return m.GetData().Get("DriverName").MustString()
}

// IsXhyve returns if the virt driver is xhyve
func (m *Machine) IsXhyve() bool {
	return m.GetDriver() == util.Xhyve
}

// GetCPU returns the number of configured CPU for this Docker Machine
func (m *Machine) GetCPU() int {
	return m.GetData().Get("Driver").Get("CPU").MustInt()
}

// GetMemory returns the amount of configured memory for this Docker Machine
func (m *Machine) GetMemory() int {
	return m.GetData().Get("Driver").Get("Memory").MustInt()
}

// GetDisk returns the disk size in MB
func (m *Machine) GetDisk() int {
	return m.GetData().Get("Driver").Get("DiskSize").MustInt()
}

// GetDiskInGB returns the disk size in GB
func (m *Machine) GetDiskInGB() int {
	return m.GetDisk() / 1000
}

// GetSysctl returns the configured value for the provided sysctl setting on the Docker Machine
func (m *Machine) GetSysctl(setting string) (string, error) {
	output, err := util.Command("docker-machine", "ssh", m.Name, "sudo", "sysctl", "-n", setting).CombinedOutput()
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(output)), nil
}

// SetSysctl sets the sysctl setting on the Docker Machine
func (m *Machine) SetSysctl(key string, val string) error {
	cmd := fmt.Sprintf("sudo sysctl -w %s=%s", key, val)
	m.out.Verbose("Modifying Docker Machine kernel settings: %s", cmd)
	_, err := util.Command("docker-machine", "ssh", m.Name, cmd).CombinedOutput()
	return err
}
<|endoftext|>


<commit_before>package scroll

import (
	"fmt"
	"strings"

	"github.com/coreos/go-etcd/etcd"
)

const (
	endpointKey = "vulcand/upstreams/%v/endpoints/%v"
	locationKey = "vulcand/hosts/%v/locations/%v"

	// If vulcand registration is enabled, the app will be re-registering itself every
	// this amount of seconds.
	endpointTTL = 60 // seconds
)

type registry struct {
	etcdClient *etcd.Client
}

type endpoint struct {
	upstream string
	host     string
	port     int
}

type location struct {
	apiHost  string
	methods  []string
	path     string
	upstream string
}

func newRegistry() *registry {
	return &registry{
		etcdClient: etcd.NewClient([]string{"http://127.0.0.1:4001"}),
	}
}

func (r *registry) RegisterEndpoint(e *endpoint) error {
	key := fmt.Sprintf(endpointKey, e.GetUpstream(), e.GetID())

	if _, err := r.etcdClient.Set(key, e.GetEndpoint(), endpointTTL); err != nil {
		return err
	}

	return nil
}

func (r *registry) RegisterLocation(l *location) error {
	key := fmt.Sprintf(locationKey, l.GetAPIHost(), l.GetID())

	pathKey := fmt.Sprintf("%v/path", key)
	if _, err := r.etcdClient.Set(pathKey, l.GetPath(), 0); err != nil {
		return err
	}

	upstreamKey := fmt.Sprintf("%v/upstream", key)
	if _, err := r.etcdClient.Set(upstreamKey, l.GetUpstream(), 0); err != nil {
		return err
	}

	return nil
}

func newEndpoint(upstream, host string, port int) *endpoint {
	return &endpoint{
		upstream: upstream,
		host:     host,
		port:     port,
	}
}

func (e *endpoint) GetID() string {
	return fmt.Sprintf("%v_%v", e.host, e.port)
}

func (e *endpoint) GetUpstream() string {
	return e.upstream
}

func (e *endpoint) GetEndpoint() string {
	return fmt.Sprintf("http://%v:%v", e.host, e.port)
}

func (e *endpoint) String() string {
	return fmt.Sprintf("id [%v], upstream [%v], endpoint [%v]",
		e.GetID(), e.GetUpstream(), e.GetEndpoint())
}

func newLocation(apiHost string, methods []string, path, upstream string) *location {
	return &location{
		apiHost:  apiHost,
		methods:  methods,
		path:     convertPath(path),
		upstream: upstream,
	}
}

func (l *location) GetID() string {
	return strings.Replace(fmt.Sprintf("%v%v", strings.Join(l.methods, "."), l.path), "/", ".", -1)
}

func (l *location) GetAPIHost() string {
	return l.apiHost
}

func (l *location) GetPath() string {
	methods := strings.Join(l.methods, `", "`)
	return fmt.Sprintf(`TrieRoute("%v", "%v")`, methods, l.path)
}

func (l *location) GetUpstream() string {
	return l.upstream
}

func (l *location) String() string {
	return fmt.Sprintf("id [%v], API host [%v], path [%v], upstream [%v]",
		l.GetID(), l.GetAPIHost(), l.GetPath(), l.GetUpstream())
}

// Convert router path to the format understood by vulcand.
//
// Effectively, just replaces curly brackets with angle brackets.
func convertPath(path string) string {
	return strings.Replace(strings.Replace(path, "{", "<", -1), "}", ">", -1)
}
<commit_msg>Use mailgun version of etcd client<commit_after>package scroll

import (
	"fmt"
	"strings"

	"github.com/mailgun/go-etcd/etcd"
)

const (
	endpointKey = "vulcand/upstreams/%v/endpoints/%v"
	locationKey = "vulcand/hosts/%v/locations/%v"

	// If vulcand registration is enabled, the app will be re-registering itself every
	// this amount of seconds.
	endpointTTL = 60 // seconds
)

type registry struct {
	etcdClient *etcd.Client
}

type endpoint struct {
	upstream string
	host     string
	port     int
}

type location struct {
	apiHost  string
	methods  []string
	path     string
	upstream string
}

func newRegistry() *registry {
	return &registry{
		etcdClient: etcd.NewClient([]string{"http://127.0.0.1:4001"}),
	}
}

func (r *registry) RegisterEndpoint(e *endpoint) error {
	key := fmt.Sprintf(endpointKey, e.GetUpstream(), e.GetID())

	if _, err := r.etcdClient.Set(key, e.GetEndpoint(), endpointTTL); err != nil {
		return err
	}

	return nil
}

func (r *registry) RegisterLocation(l *location) error {
	key := fmt.Sprintf(locationKey, l.GetAPIHost(), l.GetID())

	pathKey := fmt.Sprintf("%v/path", key)
	if _, err := r.etcdClient.Set(pathKey, l.GetPath(), 0); err != nil {
		return err
	}

	upstreamKey := fmt.Sprintf("%v/upstream", key)
	if _, err := r.etcdClient.Set(upstreamKey, l.GetUpstream(), 0); err != nil {
		return err
	}

	return nil
}

func newEndpoint(upstream, host string, port int) *endpoint {
	return &endpoint{
		upstream: upstream,
		host:     host,
		port:     port,
	}
}

func (e *endpoint) GetID() string {
	return fmt.Sprintf("%v_%v", e.host, e.port)
}

func (e *endpoint) GetUpstream() string {
	return e.upstream
}

func (e *endpoint) GetEndpoint() string {
	return fmt.Sprintf("http://%v:%v", e.host, e.port)
}

func (e *endpoint) String() string {
	return fmt.Sprintf("id [%v], upstream [%v], endpoint [%v]",
		e.GetID(), e.GetUpstream(), e.GetEndpoint())
}

func newLocation(apiHost string, methods []string, path, upstream string) *location {
	return &location{
		apiHost:  apiHost,
		methods:  methods,
		path:     convertPath(path),
		upstream: upstream,
	}
}

func (l *location) GetID() string {
	return strings.Replace(fmt.Sprintf("%v%v", strings.Join(l.methods, "."), l.path), "/", ".", -1)
}

func (l *location) GetAPIHost() string {
	return l.apiHost
}

func (l *location) GetPath() string {
	methods := strings.Join(l.methods, `", "`)
	return fmt.Sprintf(`TrieRoute("%v", "%v")`, methods, l.path)
}

func (l *location) GetUpstream() string {
	return l.upstream
}

func (l *location) String() string {
	return fmt.Sprintf("id [%v], API host [%v], path [%v], upstream [%v]",
		l.GetID(), l.GetAPIHost(), l.GetPath(), l.GetUpstream())
}

// Convert router path to the format understood by vulcand.
//
// Effectively, just replaces curly brackets with angle brackets.
func convertPath(path string) string {
	return strings.Replace(strings.Replace(path, "{", "<", -1), "}", ">", -1)
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdClean = &Command{
	UsageLine: "clean [-i] [-r] [-n] [-x] [importpath...]",
	Short:     "remove object files",
	Long: `
Clean removes object files from package source directories.
The go command builds most objects in a temporary directory,
so go clean is mainly concerned with object files left by other
tools or by manual invocations of go build.

Specifically, clean removes the following files from each of the
source directories corresponding to the import paths:

	_obj/            old object directory, left from Makefiles
	_test/           old test directory, left from Makefiles
	_testmain.go     old gotest file, left from Makefiles
	test.out         old test log, left from Makefiles
	build.out        old test log, left from Makefiles
	*.[568ao]        object files, left from Makefiles

	DIR(.exe)        from go build
	DIR.test(.exe)   from go test -c
	MAINFILE(.exe)   from go build MAINFILE.go

In the list, DIR represents the final path element of the
directory, and MAINFILE is the base name of any Go source
file in the directory that is not included when building
the package.

The -i flag causes clean to remove the corresponding installed
archive or binary (what 'go install' would create).

The -n flag causes clean to print the remove commands it would execute,
but not run them.

The -r flag causes clean to be applied recursively to all the
dependencies of the packages named by the import paths.

The -x flag causes clean to print remove commands as it executes them.
	`,
}

var cleanI bool // clean -i flag
var cleanN bool // clean -n flag
var cleanR bool // clean -r flag
var cleanX bool // clean -x flag

func init() {
	// break init cycle
	cmdClean.Run = runClean

	cmdClean.Flag.BoolVar(&cleanI, "i", false, "")
	cmdClean.Flag.BoolVar(&cleanN, "n", false, "")
	cmdClean.Flag.BoolVar(&cleanR, "r", false, "")
	cmdClean.Flag.BoolVar(&cleanX, "x", false, "")
}

func runClean(cmd *Command, args []string) {
	for _, pkg := range packagesAndErrors(args) {
		clean(pkg)
	}
}

var cleaned = map[*Package]bool{}

// TODO: These are dregs left by Makefile-based builds.
// Eventually, can stop deleting these.
var cleanDir = map[string]bool{
	"_test": true,
	"_obj":  true,
}

var cleanFile = map[string]bool{
	"_testmain.go": true,
	"test.out":     true,
	"build.out":    true,
	"a.out":        true,
}

var cleanExt = map[string]bool{
	".5": true,
	".6": true,
	".8": true,
	".a": true,
	".o": true,
}

func clean(p *Package) {
	if cleaned[p] {
		return
	}
	if p.Dir == "" {
		errorf("can't load package: %v", p.Error)
		return
	}
	dirs, err := ioutil.ReadDir(p.Dir)
	if err != nil {
		errorf("%v", err)
		return
	}

	var b builder

	packageFile := map[string]bool{}
	if p.Name != "main" {
		// Record which files are not in package main.
		// The others are.
		keep := func(list []string) {
			for _, f := range list {
				packageFile[f] = true
			}
		}
		keep(p.GoFiles)
		keep(p.CgoFiles)
		keep(p.TestGoFiles)
		keep(p.XTestGoFiles)
	}

	_, elem := filepath.Split(p.Dir)
	allRemove := []string{
		elem,
		elem + ".exe",
		elem + ".test",
		elem + ".test.exe",
	}
	for _, dir := range dirs {
		name := dir.Name()
		if packageFile[name] {
			continue
		}
		if !dir.IsDir() && strings.HasSuffix(name, ".go") {
			base := name[:len(name)-len(".go")]
			allRemove = append(allRemove, base, base+".exe")
		}
	}
	if cleanN || cleanX {
		b.showcmd(p.Dir, "rm %s", strings.Join(allRemove, " "))
	}

	toRemove := map[string]bool{}
	for _, name := range allRemove {
		toRemove[name] = true
	}
	for _, dir := range dirs {
		name := dir.Name()
		if dir.IsDir() {
			// TODO: Remove once Makefiles are forgotten.
			if cleanDir[name] {
				if cleanN || cleanX {
					b.showcmd(p.Dir, "rm -r %s", name)
					if cleanN {
						continue
					}
				}
				os.RemoveAll(filepath.Join(p.Dir, name))
			}
			continue
		}

		if cleanN {
			continue
		}

		if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] {
			os.Remove(filepath.Join(p.Dir, name))
		}
	}

	if cleanI && p.target != "" {
		if cleanN || cleanX {
			b.showcmd("", "rm %s", p.target)
		}
		if !cleanN {
			os.Remove(p.target)
		}
	}

	if cleanR {
		for _, p1 := range p.imports {
			clean(p1)
		}
	}
}
<commit_msg>cmd/go: fixed panic on `go clean -n` and `go clean -x`.         also made generated scripts act more like running go clean itself<commit_after>// Copyright 2012 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.

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdClean = &Command{
	UsageLine: "clean [-i] [-r] [-n] [-x] [importpath...]",
	Short:     "remove object files",
	Long: `
Clean removes object files from package source directories.
The go command builds most objects in a temporary directory,
so go clean is mainly concerned with object files left by other
tools or by manual invocations of go build.

Specifically, clean removes the following files from each of the
source directories corresponding to the import paths:

	_obj/            old object directory, left from Makefiles
	_test/           old test directory, left from Makefiles
	_testmain.go     old gotest file, left from Makefiles
	test.out         old test log, left from Makefiles
	build.out        old test log, left from Makefiles
	*.[568ao]        object files, left from Makefiles

	DIR(.exe)        from go build
	DIR.test(.exe)   from go test -c
	MAINFILE(.exe)   from go build MAINFILE.go

In the list, DIR represents the final path element of the
directory, and MAINFILE is the base name of any Go source
file in the directory that is not included when building
the package.

The -i flag causes clean to remove the corresponding installed
archive or binary (what 'go install' would create).

The -n flag causes clean to print the remove commands it would execute,
but not run them.

The -r flag causes clean to be applied recursively to all the
dependencies of the packages named by the import paths.

The -x flag causes clean to print remove commands as it executes them.
	`,
}

var cleanI bool // clean -i flag
var cleanN bool // clean -n flag
var cleanR bool // clean -r flag
var cleanX bool // clean -x flag

func init() {
	// break init cycle
	cmdClean.Run = runClean

	cmdClean.Flag.BoolVar(&cleanI, "i", false, "")
	cmdClean.Flag.BoolVar(&cleanN, "n", false, "")
	cmdClean.Flag.BoolVar(&cleanR, "r", false, "")
	cmdClean.Flag.BoolVar(&cleanX, "x", false, "")
}

func runClean(cmd *Command, args []string) {
	for _, pkg := range packagesAndErrors(args) {
		clean(pkg)
	}
}

var cleaned = map[*Package]bool{}

// TODO: These are dregs left by Makefile-based builds.
// Eventually, can stop deleting these.
var cleanDir = map[string]bool{
	"_test": true,
	"_obj":  true,
}

var cleanFile = map[string]bool{
	"_testmain.go": true,
	"test.out":     true,
	"build.out":    true,
	"a.out":        true,
}

var cleanExt = map[string]bool{
	".5": true,
	".6": true,
	".8": true,
	".a": true,
	".o": true,
}

func clean(p *Package) {
	if cleaned[p] {
		return
	}
	if p.Dir == "" {
		errorf("can't load package: %v", p.Error)
		return
	}
	dirs, err := ioutil.ReadDir(p.Dir)
	if err != nil {
		errorf("%v", err)
		return
	}

	var b builder
	b.print = fmt.Print

	packageFile := map[string]bool{}
	if p.Name != "main" {
		// Record which files are not in package main.
		// The others are.
		keep := func(list []string) {
			for _, f := range list {
				packageFile[f] = true
			}
		}
		keep(p.GoFiles)
		keep(p.CgoFiles)
		keep(p.TestGoFiles)
		keep(p.XTestGoFiles)
	}

	_, elem := filepath.Split(p.Dir)
	allRemove := []string{
		elem,
		elem + ".exe",
		elem + ".test",
		elem + ".test.exe",
	}
	for _, dir := range dirs {
		name := dir.Name()
		if packageFile[name] {
			continue
		}
		if !dir.IsDir() && strings.HasSuffix(name, ".go") {
			base := name[:len(name)-len(".go")]
			allRemove = append(allRemove, base, base+".exe")
		}
	}
	if cleanN || cleanX {
		b.showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " "))
	}

	toRemove := map[string]bool{}
	for _, name := range allRemove {
		toRemove[name] = true
	}
	for _, dir := range dirs {
		name := dir.Name()
		if dir.IsDir() {
			// TODO: Remove once Makefiles are forgotten.
			if cleanDir[name] {
				if cleanN || cleanX {
					b.showcmd(p.Dir, "rm -r %s", name)
					if cleanN {
						continue
					}
				}
				os.RemoveAll(filepath.Join(p.Dir, name))
			}
			continue
		}

		if cleanN {
			continue
		}

		if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] {
			os.Remove(filepath.Join(p.Dir, name))
		}
	}

	if cleanI && p.target != "" {
		if cleanN || cleanX {
			b.showcmd("", "rm -f %s", p.target)
		}
		if !cleanN {
			os.Remove(p.target)
		}
	}

	if cleanR {
		for _, p1 := range p.imports {
			clean(p1)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 The Cockroach 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.
//
// Author: Vivek Menezes (vivek.menezes@gmail.com)

package sql

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/cockroachdb/cockroach/sql/parser"
	"github.com/cockroachdb/cockroach/sql/sqlbase"
)

// distinct constructs a distinctNode.
func (*planner) distinct(n *parser.SelectClause, p planNode) planNode {
	if !n.Distinct {
		return p
	}
	d := &distinctNode{
		planNode:   p,
		suffixSeen: make(map[string]struct{}),
	}
	ordering := p.Ordering()
	if !ordering.isEmpty() {
		d.columnsInOrder = make([]bool, len(p.Columns()))
		for colIdx := range ordering.exactMatchCols {
			if colIdx >= len(d.columnsInOrder) {
				// If the exact-match column is not part of the output, we can safely ignore it.
				continue
			}
			d.columnsInOrder[colIdx] = true
		}
		for _, c := range ordering.ordering {
			if c.colIdx >= len(d.columnsInOrder) {
				// Cannot use sort order. This happens when the
				// columns used for sorting are not part of the output.
				// e.g. SELECT a FROM t ORDER BY c.
				d.columnsInOrder = nil
				break
			}
			d.columnsInOrder[c.colIdx] = true
		}
	}
	return d
}

type distinctNode struct {
	planNode
	// All the columns that are part of the Sort. Set to nil if no-sort, or
	// sort used an expression that was not part of the requested column set.
	columnsInOrder []bool
	// encoding of the columnsInOrder columns for the previous row.
	prefixSeen []byte
	// encoding of the non-columnInOrder columns for rows sharing the same
	// prefixSeen value.
	suffixSeen map[string]struct{}
	err        error
	explain    explainMode
	debugVals  debugValues
}

func (n *distinctNode) MarkDebug(mode explainMode) {
	if mode != explainDebug {
		panic(fmt.Sprintf("unknown debug mode %d", mode))
	}
	n.explain = mode
	n.planNode.MarkDebug(mode)
}

func (n *distinctNode) DebugValues() debugValues {
	if n.explain != explainDebug {
		panic(fmt.Sprintf("node not in debug mode (mode %d)", n.explain))
	}
	return n.debugVals
}

func (n *distinctNode) Next() bool {
	if n.err != nil {
		return false
	}
	for n.planNode.Next() {
		if n.explain == explainDebug {
			n.debugVals = n.planNode.DebugValues()
			if n.debugVals.output != debugValueRow {
				// Let the non-row debug values pass through.
				return true
			}
		}
		// Detect duplicates
		prefix, suffix := n.encodeValues(n.Values())
		if n.err != nil {
			return false
		}

		if !bytes.Equal(prefix, n.prefixSeen) {
			// The prefix of the row which is ordered differs from the last row;
			// reset our seen set.
			if len(n.suffixSeen) > 0 {
				n.suffixSeen = make(map[string]struct{})
			}
			n.prefixSeen = prefix
			if suffix != nil {
				n.suffixSeen[string(suffix)] = struct{}{}
			}
			return true
		}

		// The prefix of the row is the same as the last row; check
		// to see if the suffix which is not ordered has been seen.
		if suffix != nil {
			sKey := string(suffix)
			if _, ok := n.suffixSeen[sKey]; !ok {
				n.suffixSeen[sKey] = struct{}{}
				return true
			}
		}

		// The row is a duplicate
		if n.explain == explainDebug {
			// Return as a filtered row.
			n.debugVals.output = debugValueFiltered
			return true
		}
	}
	n.err = n.planNode.Err()
	return false
}

func (n *distinctNode) Err() error {
	return n.err
}

func (n *distinctNode) encodeValues(values parser.DTuple) ([]byte, []byte) {
	var prefix, suffix []byte
	for i, val := range values {
		if n.columnsInOrder != nil && n.columnsInOrder[i] {
			if prefix == nil {
				prefix = make([]byte, 0, 100)
			}
			prefix, n.err = sqlbase.EncodeDatum(prefix, val)
		} else {
			if suffix == nil {
				suffix = make([]byte, 0, 100)
			}
			suffix, n.err = sqlbase.EncodeDatum(suffix, val)
		}
		if n.err != nil {
			break
		}
	}
	return prefix, suffix
}

func (n *distinctNode) ExplainPlan(_ bool) (string, string, []planNode) {
	var description string
	if n.columnsInOrder != nil {
		columns := n.Columns()
		strs := make([]string, 0, len(columns))
		for i, column := range columns {
			if n.columnsInOrder[i] {
				strs = append(strs, column.Name)
			}
		}
		description = strings.Join(strs, ",")
	}
	return "distinct", description, []planNode{n.planNode}
}

func (n *distinctNode) ExplainTypes(_ func(string, string)) {}

func (n *distinctNode) SetLimitHint(numRows int64, soft bool) {
	// Any limit becomes a "soft" limit underneath.
	n.planNode.SetLimitHint(numRows, true)
}
<commit_msg>Make distinctNode a fully-fledged planNode.<commit_after>// Copyright 2015 The Cockroach 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.
//
// Author: Vivek Menezes (vivek.menezes@gmail.com)

package sql

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/cockroachdb/cockroach/sql/parser"
	"github.com/cockroachdb/cockroach/sql/sqlbase"
)

// distinct constructs a distinctNode.
func (*planner) distinct(n *parser.SelectClause, p planNode) planNode {
	if !n.Distinct {
		return p
	}
	d := &distinctNode{
		plan:       p,
		suffixSeen: make(map[string]struct{}),
	}
	ordering := p.Ordering()
	if !ordering.isEmpty() {
		d.columnsInOrder = make([]bool, len(p.Columns()))
		for colIdx := range ordering.exactMatchCols {
			if colIdx >= len(d.columnsInOrder) {
				// If the exact-match column is not part of the output, we can safely ignore it.
				continue
			}
			d.columnsInOrder[colIdx] = true
		}
		for _, c := range ordering.ordering {
			if c.colIdx >= len(d.columnsInOrder) {
				// Cannot use sort order. This happens when the
				// columns used for sorting are not part of the output.
				// e.g. SELECT a FROM t ORDER BY c.
				d.columnsInOrder = nil
				break
			}
			d.columnsInOrder[c.colIdx] = true
		}
	}
	return d
}

type distinctNode struct {
	plan planNode
	// All the columns that are part of the Sort. Set to nil if no-sort, or
	// sort used an expression that was not part of the requested column set.
	columnsInOrder []bool
	// encoding of the columnsInOrder columns for the previous row.
	prefixSeen []byte
	// encoding of the non-columnInOrder columns for rows sharing the same
	// prefixSeen value.
	suffixSeen map[string]struct{}
	err        error
	explain    explainMode
	debugVals  debugValues
}

func (n *distinctNode) Start() error            { return n.plan.Start() }
func (n *distinctNode) Columns() []ResultColumn { return n.plan.Columns() }
func (n *distinctNode) Values() parser.DTuple   { return n.plan.Values() }
func (n *distinctNode) Ordering() orderingInfo  { return n.plan.Ordering() }

func (n *distinctNode) MarkDebug(mode explainMode) {
	if mode != explainDebug {
		panic(fmt.Sprintf("unknown debug mode %d", mode))
	}
	n.explain = mode
	n.plan.MarkDebug(mode)
}

func (n *distinctNode) DebugValues() debugValues {
	if n.explain != explainDebug {
		panic(fmt.Sprintf("node not in debug mode (mode %d)", n.explain))
	}
	return n.debugVals
}

func (n *distinctNode) Next() bool {
	if n.err != nil {
		return false
	}
	for n.plan.Next() {
		if n.explain == explainDebug {
			n.debugVals = n.plan.DebugValues()
			if n.debugVals.output != debugValueRow {
				// Let the non-row debug values pass through.
				return true
			}
		}
		// Detect duplicates
		prefix, suffix := n.encodeValues(n.Values())
		if n.err != nil {
			return false
		}

		if !bytes.Equal(prefix, n.prefixSeen) {
			// The prefix of the row which is ordered differs from the last row;
			// reset our seen set.
			if len(n.suffixSeen) > 0 {
				n.suffixSeen = make(map[string]struct{})
			}
			n.prefixSeen = prefix
			if suffix != nil {
				n.suffixSeen[string(suffix)] = struct{}{}
			}
			return true
		}

		// The prefix of the row is the same as the last row; check
		// to see if the suffix which is not ordered has been seen.
		if suffix != nil {
			sKey := string(suffix)
			if _, ok := n.suffixSeen[sKey]; !ok {
				n.suffixSeen[sKey] = struct{}{}
				return true
			}
		}

		// The row is a duplicate
		if n.explain == explainDebug {
			// Return as a filtered row.
			n.debugVals.output = debugValueFiltered
			return true
		}
	}
	n.err = n.plan.Err()
	return false
}

func (n *distinctNode) Err() error {
	return n.err
}

func (n *distinctNode) encodeValues(values parser.DTuple) ([]byte, []byte) {
	var prefix, suffix []byte
	for i, val := range values {
		if n.columnsInOrder != nil && n.columnsInOrder[i] {
			if prefix == nil {
				prefix = make([]byte, 0, 100)
			}
			prefix, n.err = sqlbase.EncodeDatum(prefix, val)
		} else {
			if suffix == nil {
				suffix = make([]byte, 0, 100)
			}
			suffix, n.err = sqlbase.EncodeDatum(suffix, val)
		}
		if n.err != nil {
			break
		}
	}
	return prefix, suffix
}

func (n *distinctNode) ExplainPlan(_ bool) (string, string, []planNode) {
	var description string
	if n.columnsInOrder != nil {
		columns := n.Columns()
		strs := make([]string, 0, len(columns))
		for i, column := range columns {
			if n.columnsInOrder[i] {
				strs = append(strs, column.Name)
			}
		}
		description = strings.Join(strs, ",")
	}
	return "distinct", description, []planNode{n.plan}
}

func (n *distinctNode) ExplainTypes(_ func(string, string)) {}

func (n *distinctNode) SetLimitHint(numRows int64, soft bool) {
	// Any limit becomes a "soft" limit underneath.
	n.plan.SetLimitHint(numRows, true)
}
<|endoftext|>


<commit_before>package nginxconf

// Comment represents a nginx config file comment.
// This should not include a `#` prefix because it
// will be added when accessed via the String() method.
type Comment string

// String returns comment with a hash `#` prefix.
func (c *Comment) String() string {
	return "#" + string(*c)
}
<commit_msg>fix comment String method<commit_after>package nginxconf

// Comment represents a nginx config file comment.
// This should not include a `#` prefix because it
// will be added when accessed via the String() method.
type Comment string

// String returns comment with a hash `#` prefix.
func (c Comment) String() string {
	return "#" + string(c)
}
<|endoftext|>


<commit_before>
package golog

import (
    "io"
    "io/ioutil"
    "log"
    "os"
    "fmt"
    "strings"
    "time"
    "sync/atomic"
)
const (
	// everything
	LevelTrace int32 = 1

	// Info, Warnings and Errors
	LevelInfo int32 = 2

	// Warning and Errors
	LevelWarn int32 = 4

	// Errors
	LevelError int32 = 8
)

// goLogStruct provides support to write to log files.
type goLogStruct struct {
	LogLevel           int32
	Trace              *log.Logger
	Info               *log.Logger
	Warning            *log.Logger
	Error              *log.Logger
	File               *log.Logger
	LogFile            *os.File
}

// log maintains a pointer to a singleton for the logging system.
var logger goLogStruct

// Called to init the logging system.
func (lS goLogStruct) Init(logLevel int32, baseFilePath string) error {
	log.SetPrefix("TRACE: ")
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	err := startFile(logLevel, baseFilePath)
	if err != nil {
		return err;
	}
	lS = logger
	return err
}

// StartFile initializes goLogStruct and only displays the specified logging level
// and creates a file to capture writes.
func startFile(logLevel int32, baseFilePath string) error {
	baseFilePath = strings.TrimRight(baseFilePath, "/")
	currentDate := time.Now().UTC()
	dateDirectory := time.Now().UTC().Format("2006-01-02")
	dateFile := currentDate.Format("2006-01-02T15-04-05")

	filePath := fmt.Sprintf("%s/%s/", baseFilePath, dateDirectory)
	fileName := strings.Replace(fmt.Sprintf("%s.txt", dateFile), " ", "-", -1)

	err := os.MkdirAll(filePath, os.ModePerm)
	if err != nil {
		log.Fatalf("main : Start : Failed to Create log directory : %s : %s\n", filePath, err)
		return err
	}

	logf, err := os.Create(fmt.Sprintf("%s%s", filePath, fileName))
	if err != nil {
		log.Fatalf("main : Start : Failed to Create log file : %s : %s\n", fileName, err)
		return err
	}

	turnOnLogging(logLevel, logf)
	return err

}

// Stop will release resources and shutdown all processing.
func Stop() error {
	var err error
	if logger.LogFile != nil {
		Trace("main", "Stop", "Closing File")
		err = logger.LogFile.Close()
	}
	return err
}

// LogLevel returns the configured logging level.
func GetLogLevel() int32 {
	return atomic.LoadInt32(&logger.LogLevel)
}

// turnOnLogging configures the logging writers.
func turnOnLogging(logLevel int32, fileHandle io.Writer) {
	traceHandle := ioutil.Discard
	infoHandle := ioutil.Discard
	warnHandle := ioutil.Discard
	errorHandle := ioutil.Discard

	if logLevel&LevelTrace != 0 {
		traceHandle = os.Stdout
		infoHandle = os.Stdout
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelInfo != 0 {
		infoHandle = os.Stdout
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelWarn != 0 {
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelError != 0 {
		errorHandle = os.Stderr
	}

	if fileHandle != nil {
		if traceHandle == os.Stdout {
			traceHandle = io.MultiWriter(fileHandle, traceHandle)
		}

		if infoHandle == os.Stdout {
			infoHandle = io.MultiWriter(fileHandle, infoHandle)
		}

		if warnHandle == os.Stdout {
			warnHandle = io.MultiWriter(fileHandle, warnHandle)
		}

		if errorHandle == os.Stderr {
			errorHandle = io.MultiWriter(fileHandle, errorHandle)
		}
	}

	logger.Trace = log.New(traceHandle, "TRACE: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Info = log.New(infoHandle, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Warning = log.New(warnHandle, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Error = log.New(errorHandle, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)

	atomic.StoreInt32(&logger.LogLevel, logLevel)
}

//** TRACE

// Trace writes to the Trace destination
func Trace(format string, a ...interface{}) {
	logger.Trace.Output(2, fmt.Sprintf("%s\n", fmt.Sprintf(format, a...)))
}

//** INFO

// Info writes to the Info destination
func Info(format string, a ...interface{}) {
	logger.Info.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//** WARNING

// Warning writes to the Warning destination
func Warning(format string, a ...interface{}) {
	logger.Warning.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//** ERROR

// Error writes to the Error destination and accepts an err
func Error(format string, a ...interface{}) {
	logger.Error.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//writes to the Error and exit(1)
func Fatal(format string, a ...interface{}) {
	logger.Error.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
	os.Exit(1)
}

<commit_msg>GetLoggerInstance added<commit_after>
package golog

import (
    "io"
    "io/ioutil"
    "log"
    "os"
    "fmt"
    "strings"
    "time"
    "sync/atomic"
    "errors"
)
const (
	// everything
	LevelTrace int32 = 1

	// Info, Warnings and Errors
	LevelInfo int32 = 2

	// Warning and Errors
	LevelWarn int32 = 4

	// Errors
	LevelError int32 = 8
)

// goLogStruct provides support to write to log files.
type goLogStruct struct {
	LogLevel           int32
	Trace              *log.Logger
	Info               *log.Logger
	Warning            *log.Logger
	Error              *log.Logger
	File               *log.Logger
	LogFile            *os.File
}

// log maintains a pointer to a singleton for the logging system.
var logger goLogStruct

// Called to init the logging system.
func (lS goLogStruct) Init(logLevel int32, baseFilePath string) error {
	log.SetPrefix("TRACE: ")
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	err := startFile(logLevel, baseFilePath)
	if err != nil {
		return err;
	}
	lS = logger
	return err
}

func GetLoggerInstance() (goLogStruct, error) {
	if &logger == nil {
		return logger, errors.New("Logger not initialized")
	}
	return logger, nil
}

// StartFile initializes goLogStruct and only displays the specified logging level
// and creates a file to capture writes.
func startFile(logLevel int32, baseFilePath string) error {
	baseFilePath = strings.TrimRight(baseFilePath, "/")
	currentDate := time.Now().UTC()
	dateDirectory := time.Now().UTC().Format("2006-01-02")
	dateFile := currentDate.Format("2006-01-02T15-04-05")

	filePath := fmt.Sprintf("%s/%s/", baseFilePath, dateDirectory)
	fileName := strings.Replace(fmt.Sprintf("%s.txt", dateFile), " ", "-", -1)

	err := os.MkdirAll(filePath, os.ModePerm)
	if err != nil {
		log.Fatalf("main : Start : Failed to Create log directory : %s : %s\n", filePath, err)
		return err
	}

	logf, err := os.Create(fmt.Sprintf("%s%s", filePath, fileName))
	if err != nil {
		log.Fatalf("main : Start : Failed to Create log file : %s : %s\n", fileName, err)
		return err
	}

	turnOnLogging(logLevel, logf)
	return err

}

// Stop will release resources and shutdown all processing.
func Stop() error {
	var err error
	if logger.LogFile != nil {
		Trace("main", "Stop", "Closing File")
		err = logger.LogFile.Close()
	}
	return err
}

// LogLevel returns the configured logging level.
func GetLogLevel() int32 {
	return atomic.LoadInt32(&logger.LogLevel)
}

// turnOnLogging configures the logging writers.
func turnOnLogging(logLevel int32, fileHandle io.Writer) {
	traceHandle := ioutil.Discard
	infoHandle := ioutil.Discard
	warnHandle := ioutil.Discard
	errorHandle := ioutil.Discard

	if logLevel&LevelTrace != 0 {
		traceHandle = os.Stdout
		infoHandle = os.Stdout
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelInfo != 0 {
		infoHandle = os.Stdout
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelWarn != 0 {
		warnHandle = os.Stdout
		errorHandle = os.Stderr
	}

	if logLevel&LevelError != 0 {
		errorHandle = os.Stderr
	}

	if fileHandle != nil {
		if traceHandle == os.Stdout {
			traceHandle = io.MultiWriter(fileHandle, traceHandle)
		}

		if infoHandle == os.Stdout {
			infoHandle = io.MultiWriter(fileHandle, infoHandle)
		}

		if warnHandle == os.Stdout {
			warnHandle = io.MultiWriter(fileHandle, warnHandle)
		}

		if errorHandle == os.Stderr {
			errorHandle = io.MultiWriter(fileHandle, errorHandle)
		}
	}

	logger.Trace = log.New(traceHandle, "TRACE: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Info = log.New(infoHandle, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Warning = log.New(warnHandle, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Error = log.New(errorHandle, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)

	atomic.StoreInt32(&logger.LogLevel, logLevel)
}

//** TRACE

// Trace writes to the Trace destination
func Trace(format string, a ...interface{}) {
	logger.Trace.Output(2, fmt.Sprintf("%s\n", fmt.Sprintf(format, a...)))
}

//** INFO

// Info writes to the Info destination
func Info(format string, a ...interface{}) {
	logger.Info.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//** WARNING

// Warning writes to the Warning destination
func Warning(format string, a ...interface{}) {
	logger.Warning.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//** ERROR

// Error writes to the Error destination and accepts an err
func Error(format string, a ...interface{}) {
	logger.Error.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
}

//writes to the Error and exit(1)
func Fatal(format string, a ...interface{}) {
	logger.Error.Output(2, fmt.Sprintf(fmt.Sprintf(format, a...)))
	os.Exit(1)
}

<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"go/token"

	"github.com/davyxu/gosproto/meta"
)

const goCodeTemplate = `// Generated by github.com/davyxu/gosproto/sprotogen
// DO NOT EDIT!

package {{.PackageName}}

import (
	"reflect"
	"github.com/davyxu/gosproto"
	"github.com/davyxu/goobjfmt"
	{{if .CellnetReg}}"github.com/davyxu/cellnet/codec/sproto"{{end}}
	{{if .EnumValueGroup}}"fmt"{{end}}
)

{{range $a, $enumobj := .Enums}}
type {{.Name}} int32
const (	{{range .StFields}}
	{{$enumobj.Name}}_{{.Name}} {{.GoEnumTypeName}} = {{.TagNumber}} {{end}}
)

var (
{{$enumobj.Name}}MapperValueByName = map[string]int32{ {{range .StFields}}
	"{{.Name}}": {{.TagNumber}}, {{end}}
}

{{$enumobj.Name}}MapperNameByValue = map[int32]string{ {{range .StFields}}
	{{.TagNumber}}: "{{.Name}}" , {{end}}
}
)

func (self {{$enumobj.Name}}) String() string {
	return sproto.EnumName({{$enumobj.Name}}MapperNameByValue, int32(self))
}
{{end}}

{{range $a, $stobj := .Structs}}
type {{.Name}} struct{
	{{range .StFields}}
		{{.GoFieldName}} {{.GoTypeName}} {{.GoTags}}
	{{end}}
}

func (self *{{.Name}}) String() string { return goobjfmt.CompactTextString(self) }

{{range .StFields}}{{if .IsExtendType}}
func (self *{{$stobj.Name}}) {{.GoExtendFieldGetterName}}() {{.GoExtendFieldGetterType}} {
	{{.GoExtendFieldGetter}}
}
func (self *{{$stobj.Name}}) Set{{.GoExtendFieldGetterName}}(v {{.GoExtendFieldGetterType}})  {
	{{.GoExtendFieldSetter}}
}
{{end}} {{end}}
{{end}}

var SProtoStructs = []reflect.Type{
{{range .Structs}}
	reflect.TypeOf((*{{.Name}})(nil)).Elem(), // {{.MsgID}} {{end}}
}

var SProtoEnumValue = map[string]map[int32]string{ {{range .Enums}}
	"{{.Name}}": {{.Name}}MapperNameByValue,{{end}}
}

{{if .EnumValueGroup}}
func ResultToString(result int32) string {
	switch( result ) {
		case 0: return "OK";
	{{range $a, $enumObj := .Enums}} {{if .IsResultEnum}} {{range .Fields}} {{if ne .TagNumber 0}}
		case {{.TagNumber}}: return "{{$enumObj.Name}}.{{.Name}}"; {{end}} {{end}} {{end}} {{end}}
	}

	return fmt.Sprintf("result: %d", result)
}
{{end}}
{{if .CellnetReg}}
func init() {
	sprotocodec.AutoRegisterMessageMeta(SProtoStructs)
}
{{end}}

`

func (self *fieldModel) GoEnumTypeName() string {

	if self.st.EnumValueIgnoreType {
		return ""
	}

	return self.st.Name
}

func (self *fieldModel) GoExtendFieldGetterName() string {
	pname := publicFieldName(self.Name)

	if token.Lookup(pname).IsKeyword() {
		return pname + "_"
	}

	return pname
}

func (self *fieldModel) GoExtendFieldGetter() string {

	switch self.Type {
	case meta.FieldType_Float32,
		meta.FieldType_Float64:
		return fmt.Sprintf("return %s(self.%s) * %f", self.GoExtendFieldGetterType(), self.GoFieldName(), 1.0/float32(self.ExtendTypePrecision()))
	}

	return "unknown extend type:" + self.Type.String()
}

func (self *fieldModel) GoExtendFieldSetter() string {

	switch self.Type {
	case meta.FieldType_Float32:
		return fmt.Sprintf("self.%s = int32(v* %d)", self.GoFieldName(), self.ExtendTypePrecision())
	case meta.FieldType_Float64:
		return fmt.Sprintf("self.%s = int64(v* %d)", self.GoFieldName(), self.ExtendTypePrecision())
	}

	return "unknown extend type:" + self.Type.String()
}

func (self *fieldModel) GoExtendFieldGetterType() string {
	var b bytes.Buffer
	if self.Repeatd {
		b.WriteString("[]")
	}

	// 字段类型映射go的类型
	switch self.Type {
	case meta.FieldType_Float32:
		b.WriteString("float32")
	case meta.FieldType_Float64:
		b.WriteString("float64")
	default:
		b.WriteString("unknown extend type:" + self.Type.String())
	}

	return b.String()
}

func (self *fieldModel) GoFieldName() string {

	var pname string

	// 扩展类型不能直接访问
	if self.IsExtendType() {
		pname = "Extend_" + self.Name
	} else {
		pname = publicFieldName(self.Name)
	}

	// 碰到关键字在尾部加_
	if token.Lookup(pname).IsKeyword() {
		return pname + "_"
	}

	return pname
}

func (self *fieldModel) GoTypeName() string {

	var b bytes.Buffer
	if self.Repeatd {
		b.WriteString("[]")
	}

	if self.Type == meta.FieldType_Struct {
		b.WriteString("*")
	}

	// 字段类型映射go的类型
	switch self.Type {
	case meta.FieldType_Integer:
		b.WriteString("int")
	case meta.FieldType_Bool:
		b.WriteString("bool")
	case meta.FieldType_Struct,
		meta.FieldType_Enum:
		b.WriteString(self.Complex.Name)
	case meta.FieldType_Float32:
		b.WriteString("int32")
	case meta.FieldType_Float64:
		b.WriteString("int64")
	case meta.FieldType_Bytes:
		b.WriteString("[]byte")
	default:
		b.WriteString(self.Type.String())
	}

	return b.String()
}

func (self *fieldModel) GoTags() string {

	var b bytes.Buffer

	b.WriteString("`sproto:\"")

	// 整形类型对解码层都视为整形
	switch self.Type {
	case meta.FieldType_Int32,
		meta.FieldType_Int64,
		meta.FieldType_UInt32,
		meta.FieldType_UInt64,
		meta.FieldType_Float32,
		meta.FieldType_Float64,
		meta.FieldType_Enum:
		b.WriteString("integer")
	case meta.FieldType_Bytes:
		b.WriteString("string")
	default:
		b.WriteString(self.Kind())
	}

	b.WriteString(",")

	b.WriteString(fmt.Sprintf("%d", self.TagNumber()))
	b.WriteString(",")

	if self.Repeatd {
		b.WriteString("array,")
	}

	b.WriteString(fmt.Sprintf("name=%s", self.GoFieldName()))

	b.WriteString("\"`")

	return b.String()
}

func gen_go(fm *fileModel, filename string) {

	addData(fm, "go")

	generateCode("sp->go", goCodeTemplate, filename, fm, &generateOption{
		formatGoCode: true,
	})

}
<commit_msg>修复: 在枚举为0时,多余的import<commit_after>package main

import (
	"bytes"
	"fmt"
	"go/token"

	"github.com/davyxu/gosproto/meta"
)

const goCodeTemplate = `// Generated by github.com/davyxu/gosproto/sprotogen
// DO NOT EDIT!

package {{.PackageName}}

import (
	"reflect"
	{{if gt (.Enums|len) 0}}"github.com/davyxu/gosproto"{{end}}
	"github.com/davyxu/goobjfmt"
	{{if .CellnetReg}}"github.com/davyxu/cellnet/codec/sproto"{{end}}
	{{if .EnumValueGroup}}"fmt"{{end}}
)

{{range $a, $enumobj := .Enums}}
type {{.Name}} int32
const (	{{range .StFields}}
	{{$enumobj.Name}}_{{.Name}} {{.GoEnumTypeName}} = {{.TagNumber}} {{end}}
)

var (
{{$enumobj.Name}}MapperValueByName = map[string]int32{ {{range .StFields}}
	"{{.Name}}": {{.TagNumber}}, {{end}}
}

{{$enumobj.Name}}MapperNameByValue = map[int32]string{ {{range .StFields}}
	{{.TagNumber}}: "{{.Name}}" , {{end}}
}
)

func (self {{$enumobj.Name}}) String() string {
	return sproto.EnumName({{$enumobj.Name}}MapperNameByValue, int32(self))
}
{{end}}

{{range $a, $stobj := .Structs}}
type {{.Name}} struct{
	{{range .StFields}}
		{{.GoFieldName}} {{.GoTypeName}} {{.GoTags}}
	{{end}}
}

func (self *{{.Name}}) String() string { return goobjfmt.CompactTextString(self) }

{{range .StFields}}{{if .IsExtendType}}
func (self *{{$stobj.Name}}) {{.GoExtendFieldGetterName}}() {{.GoExtendFieldGetterType}} {
	{{.GoExtendFieldGetter}}
}
func (self *{{$stobj.Name}}) Set{{.GoExtendFieldGetterName}}(v {{.GoExtendFieldGetterType}})  {
	{{.GoExtendFieldSetter}}
}
{{end}} {{end}}
{{end}}

var SProtoStructs = []reflect.Type{
{{range .Structs}}
	reflect.TypeOf((*{{.Name}})(nil)).Elem(), // {{.MsgID}} {{end}}
}

var SProtoEnumValue = map[string]map[int32]string{ {{range .Enums}}
	"{{.Name}}": {{.Name}}MapperNameByValue,{{end}}
}

{{if .EnumValueGroup}}
func ResultToString(result int32) string {
	switch( result ) {
		case 0: return "OK";
	{{range $a, $enumObj := .Enums}} {{if .IsResultEnum}} {{range .Fields}} {{if ne .TagNumber 0}}
		case {{.TagNumber}}: return "{{$enumObj.Name}}.{{.Name}}"; {{end}} {{end}} {{end}} {{end}}
	}

	return fmt.Sprintf("result: %d", result)
}
{{end}}
{{if .CellnetReg}}
func init() {
	sprotocodec.AutoRegisterMessageMeta(SProtoStructs)
}
{{end}}

`

func (self *fieldModel) GoEnumTypeName() string {

	if self.st.EnumValueIgnoreType {
		return ""
	}

	return self.st.Name
}

func (self *fieldModel) GoExtendFieldGetterName() string {
	pname := publicFieldName(self.Name)

	if token.Lookup(pname).IsKeyword() {
		return pname + "_"
	}

	return pname
}

func (self *fieldModel) GoExtendFieldGetter() string {

	switch self.Type {
	case meta.FieldType_Float32,
		meta.FieldType_Float64:
		return fmt.Sprintf("return %s(self.%s) * %f", self.GoExtendFieldGetterType(), self.GoFieldName(), 1.0/float32(self.ExtendTypePrecision()))
	}

	return "unknown extend type:" + self.Type.String()
}

func (self *fieldModel) GoExtendFieldSetter() string {

	switch self.Type {
	case meta.FieldType_Float32:
		return fmt.Sprintf("self.%s = int32(v* %d)", self.GoFieldName(), self.ExtendTypePrecision())
	case meta.FieldType_Float64:
		return fmt.Sprintf("self.%s = int64(v* %d)", self.GoFieldName(), self.ExtendTypePrecision())
	}

	return "unknown extend type:" + self.Type.String()
}

func (self *fieldModel) GoExtendFieldGetterType() string {
	var b bytes.Buffer
	if self.Repeatd {
		b.WriteString("[]")
	}

	// 字段类型映射go的类型
	switch self.Type {
	case meta.FieldType_Float32:
		b.WriteString("float32")
	case meta.FieldType_Float64:
		b.WriteString("float64")
	default:
		b.WriteString("unknown extend type:" + self.Type.String())
	}

	return b.String()
}

func (self *fieldModel) GoFieldName() string {

	var pname string

	// 扩展类型不能直接访问
	if self.IsExtendType() {
		pname = "Extend_" + self.Name
	} else {
		pname = publicFieldName(self.Name)
	}

	// 碰到关键字在尾部加_
	if token.Lookup(pname).IsKeyword() {
		return pname + "_"
	}

	return pname
}

func (self *fieldModel) GoTypeName() string {

	var b bytes.Buffer
	if self.Repeatd {
		b.WriteString("[]")
	}

	if self.Type == meta.FieldType_Struct {
		b.WriteString("*")
	}

	// 字段类型映射go的类型
	switch self.Type {
	case meta.FieldType_Integer:
		b.WriteString("int")
	case meta.FieldType_Bool:
		b.WriteString("bool")
	case meta.FieldType_Struct,
		meta.FieldType_Enum:
		b.WriteString(self.Complex.Name)
	case meta.FieldType_Float32:
		b.WriteString("int32")
	case meta.FieldType_Float64:
		b.WriteString("int64")
	case meta.FieldType_Bytes:
		b.WriteString("[]byte")
	default:
		b.WriteString(self.Type.String())
	}

	return b.String()
}

func (self *fieldModel) GoTags() string {

	var b bytes.Buffer

	b.WriteString("`sproto:\"")

	// 整形类型对解码层都视为整形
	switch self.Type {
	case meta.FieldType_Int32,
		meta.FieldType_Int64,
		meta.FieldType_UInt32,
		meta.FieldType_UInt64,
		meta.FieldType_Float32,
		meta.FieldType_Float64,
		meta.FieldType_Enum:
		b.WriteString("integer")
	case meta.FieldType_Bytes:
		b.WriteString("string")
	default:
		b.WriteString(self.Kind())
	}

	b.WriteString(",")

	b.WriteString(fmt.Sprintf("%d", self.TagNumber()))
	b.WriteString(",")

	if self.Repeatd {
		b.WriteString("array,")
	}

	b.WriteString(fmt.Sprintf("name=%s", self.GoFieldName()))

	b.WriteString("\"`")

	return b.String()
}

func gen_go(fm *fileModel, filename string) {

	addData(fm, "go")

	generateCode("sp->go", goCodeTemplate, filename, fm, &generateOption{
		formatGoCode: true,
	})

}
<|endoftext|>


<commit_before>package main

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

func getHttpResource(url string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	ok := false
	retriesAllowed := 3
	resp := &http.Response{}
	var err error = nil

	for i := 0; i < retriesAllowed; i++ {
		if i > 0 {
			fmt.Println("Attempt", i+1, "of", retriesAllowed)
		}

		resp, err = client.Get(url)
		if err != nil {
			fmt.Println("err, getHttpResource, get: ", err)
			continue
		}
		defer resp.Body.Close()

		if resp.StatusCode == 200 {
			ok = true
			break
		} else {
			errmsg := fmt.Sprintf("Http server returned status code:", resp.StatusCode)
			err = errors.New(errmsg)
		}
	}

	body := []byte{}
	if ok {
		body, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("err, getHttpResource, readall: ", err)
		}
	}

	return string(body), err
}

func putHttpResource(url string, body string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	reader := strings.NewReader(body)
	req, err := http.NewRequest("PUT", url, reader)

	resp, err := client.Do(req)

	out, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	return string(out), err
}

//func deleteHttpResource(url string, body string) (string, error) {
func deleteHttpResource(url string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	//reader := strings.NewReader(body)
	//req, err := http.NewRequest("DELETE", url, reader)
	req, err := http.NewRequest("DELETE", url, nil)

	resp, err := client.Do(req)

	out, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	return string(out), err
}

func postHttpResource(url string, body string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	ok := false
	retriesAllowed := 3
	resp := &http.Response{}
	var err error = nil
	bodyType := "application/json"

	reader := strings.NewReader(body)

	for i := 0; i < retriesAllowed; i++ {
		if i > 0 {
			fmt.Println("Attempt", i+1, "of", retriesAllowed)
		}

		resp, err = client.Post(url, bodyType, reader)
		if err != nil {
			fmt.Println("err, postHttpResource, post: ", err)
			continue
		}
		defer resp.Body.Close()

		if resp.StatusCode == 200 {
			ok = true
			break
		} else {
			errmsg := fmt.Sprintf("Http server returned status code:", resp.StatusCode)
			err = errors.New(errmsg)
		}
	}

	out := []byte{}
	if ok {
		out, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("err, getHttpResource, readall: ", err)
		}
	}

	return string(out), err
}

func TimeoutDialer(connectTimeout time.Duration, readWriteTimeout time.Duration) func(network, address string) (conn net.Conn, err error) {
	return func(network, address string) (net.Conn, error) {
		conn, err := net.DialTimeout(network, address, connectTimeout)
		if err != nil {
			return nil, err
		}
		err = conn.SetDeadline(time.Now().Add(readWriteTimeout))
		if err != nil {
			fmt.Println("Unable to set deadline of http connection:", err)
			return nil, err
		}
		return conn, nil
	}
}

func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {
	return &http.Client{
		Transport: &http.Transport{
			Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
		},
	}
}
<commit_msg>Fixed string formatting.<commit_after>package main

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

func getHttpResource(url string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	ok := false
	retriesAllowed := 3
	resp := &http.Response{}
	var err error = nil

	for i := 0; i < retriesAllowed; i++ {
		if i > 0 {
			fmt.Println("Attempt", i+1, "of", retriesAllowed)
		}

		resp, err = client.Get(url)
		if err != nil {
			fmt.Println("err, getHttpResource, get: ", err)
			continue
		}
		defer resp.Body.Close()

		if resp.StatusCode == 200 {
			ok = true
			break
		} else {
			errmsg := fmt.Sprintf("Http server returned status code:", resp.StatusCode)
			err = errors.New(errmsg)
		}
	}

	body := []byte{}
	if ok {
		body, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("err, getHttpResource, readall: ", err)
		}
	}

	return string(body), err
}

func putHttpResource(url string, body string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	reader := strings.NewReader(body)
	req, err := http.NewRequest("PUT", url, reader)

	resp, err := client.Do(req)

	out, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	return string(out), err
}

//func deleteHttpResource(url string, body string) (string, error) {
func deleteHttpResource(url string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	//reader := strings.NewReader(body)
	//req, err := http.NewRequest("DELETE", url, reader)
	req, err := http.NewRequest("DELETE", url, nil)

	resp, err := client.Do(req)

	out, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	return string(out), err
}

func postHttpResource(url string, body string) (string, error) {
	client := NewTimeoutClient(10*time.Second, 15*time.Second)

	ok := false
	retriesAllowed := 3
	resp := &http.Response{}
	var err error = nil
	bodyType := "application/json"

	reader := strings.NewReader(body)

	for i := 0; i < retriesAllowed; i++ {
		if i > 0 {
			fmt.Println("Attempt", i+1, "of", retriesAllowed)
		}

		resp, err = client.Post(url, bodyType, reader)
		if err != nil {
			fmt.Println("err, postHttpResource, post: ", err)
			continue
		}
		defer resp.Body.Close()

		if resp.StatusCode == 200 {
			ok = true
			break
		} else {
			errmsg := fmt.Sprintf("Http server returned status code: %s", resp.StatusCode)
			err = errors.New(errmsg)
		}
	}

	out := []byte{}
	if ok {
		out, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("err, getHttpResource, readall: ", err)
		}
	}

	return string(out), err
}

func TimeoutDialer(connectTimeout time.Duration, readWriteTimeout time.Duration) func(network, address string) (conn net.Conn, err error) {
	return func(network, address string) (net.Conn, error) {
		conn, err := net.DialTimeout(network, address, connectTimeout)
		if err != nil {
			return nil, err
		}
		err = conn.SetDeadline(time.Now().Add(readWriteTimeout))
		if err != nil {
			fmt.Println("Unable to set deadline of http connection:", err)
			return nil, err
		}
		return conn, nil
	}
}

func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {
	return &http.Client{
		Transport: &http.Transport{
			Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
		},
	}
}
<|endoftext|>