func (d *Driver) Create() error {
	// NOTE(ahmetalpbalkan): We can probably parallelize the sh*t out of this.
	// However that would lead to a concurrency logic and while creation of a
	// resource fails, other ones would be kicked off, which could lead to a
	// resource leak. This is slower but safer.
	c, err := d.newAzureClient()
	if err != nil {
		return err
	}

	var customData string
	if d.CustomDataFile != "" {
		buf, err := ioutil.ReadFile(d.CustomDataFile)
		if err != nil {
			return err
		}
		customData = base64.StdEncoding.EncodeToString(buf)
	}

	if err := c.CreateResourceGroup(d.ResourceGroup, d.Location); err != nil {
		return err
	}
	if err := c.CreateAvailabilitySetIfNotExists(d.ctx, d.ResourceGroup, d.AvailabilitySet, d.Location); err != nil {
		return err
	}
	if err := c.CreateNetworkSecurityGroup(d.ctx, d.ResourceGroup, d.naming().NSG(), d.Location, d.ctx.FirewallRules); err != nil {
		return err
	}
	vnetResourceGroup, vNetName := parseVirtualNetwork(d.VirtualNetwork, d.ResourceGroup)
	if err := c.CreateVirtualNetworkIfNotExists(vnetResourceGroup, vNetName, d.Location); err != nil {
		return err
	}
	if err := c.CreateSubnet(d.ctx, vnetResourceGroup, vNetName, d.SubnetName, d.SubnetPrefix); err != nil {
		return err
	}
	if d.NoPublicIP {
		log.Info("Not creating a public IP address.")
	} else {
		if err := c.CreatePublicIPAddress(d.ctx, d.ResourceGroup, d.naming().IP(), d.Location, d.StaticPublicIP, d.DNSLabel); err != nil {
			return err
		}
	}
	if err := c.CreateNetworkInterface(d.ctx, d.ResourceGroup, d.naming().NIC(), d.Location,
		d.ctx.PublicIPAddressID, d.ctx.SubnetID, d.ctx.NetworkSecurityGroupID, d.PrivateIPAddr); err != nil {
		return err
	}
	if err := c.CreateStorageAccount(d.ctx, d.ResourceGroup, d.Location, storage.SkuName(d.StorageType)); err != nil {
		return err
	}
	if err := d.generateSSHKey(d.ctx); err != nil {
		return err
	}
	err = c.CreateVirtualMachine(d.ResourceGroup, d.naming().VM(), d.Location, d.Size, d.ctx.AvailabilitySetID,
		d.ctx.NetworkInterfaceID, d.BaseDriver.SSHUser, d.ctx.SSHPublicKey, d.Image, customData, d.ctx.StorageAccount)
	return err
}


func (d *Driver) Remove() error {
	if err := d.checkLegacyDriver(false); err != nil {
		return err
	}

	// NOTE(ahmetalpbalkan):
	//   - remove attempts are best effort and if a resource is already gone, we
	//     continue removing other resources instead of failing.
	//   - we can probably do a lot of parallelization here but a sequential
	//     logic works fine too. If we were to detach the NIC from the VM and
	//     then delete the VM, this could enable some parallelization.

	log.Info("NOTICE: Please check Azure portal/CLI to make sure you have no leftover resources to avoid unexpected charges.")
	c, err := d.newAzureClient()
	if err != nil {
		return err
	}
	if err := c.DeleteVirtualMachineIfExists(d.ResourceGroup, d.naming().VM()); err != nil {
		return err
	}
	if err := c.DeleteNetworkInterfaceIfExists(d.ResourceGroup, d.naming().NIC()); err != nil {
		return err
	}
	if err := c.DeletePublicIPAddressIfExists(d.ResourceGroup, d.naming().IP()); err != nil {
		return err
	}
	if err := c.DeleteNetworkSecurityGroupIfExists(d.ResourceGroup, d.naming().NSG()); err != nil {
		return err
	}
	if err := c.CleanupAvailabilitySetIfExists(d.ResourceGroup, d.AvailabilitySet); err != nil {
		return err
	}
	if err := c.CleanupSubnetIfExists(d.ResourceGroup, d.VirtualNetwork, d.SubnetName); err != nil {
		return err
	}
	err = c.CleanupVirtualNetworkIfExists(d.ResourceGroup, d.VirtualNetwork)
	return err
}

// Remove deletes the virtual machine and resources associated to it.

Remove deletes the virtual machine and resources associated to it .


func (d *Driver) GetIP() (string, error) {
	if err := d.checkLegacyDriver(true); err != nil {
		return "", err
	}

	if d.resolvedIP == "" {
		ip, err := d.ipAddress()
		if err != nil {
			return "", err
		}
		d.resolvedIP = ip
	}
	log.Debugf("Machine IP address resolved to: %s", d.resolvedIP)
	return d.resolvedIP, nil
}

func ( d * Driver ) GetIP ( ) ( string , error ) { if err := d . checkLegacyDriver ( true ) ; err != nil { return " " , err } if d . resolvedIP == " " { ip , err := d . ipAddress ( ) if err != nil { return " " , err } d . resolvedIP = ip } log . Debugf ( " " , d . resolvedIP ) return d . resolvedIP , nil }

// GetIP returns public IP address or hostname of the machine instance.

GetIP returns public IP address or hostname of the machine instance .


func (d *Driver) GetURL() (string, error) {
	if err := drivers.MustBeRunning(d); err != nil {
		return "", err
	}

	// NOTE (ahmetalpbalkan) I noticed that this is not used until machine is
	// actually created and provisioned. By then GetIP() should be returning
	// a non-empty IP address as the VM is already allocated and connected to.
	ip, err := d.GetIP()
	if err != nil {
		return "", err
	}
	u := (&url.URL{
		Scheme: "tcp",
		Host:   net.JoinHostPort(ip, fmt.Sprintf("%d", d.DockerPort)),
	}).String()
	log.Debugf("Machine URL is resolved to: %s", u)
	return u, nil
}

// GetURL returns a socket address to connect to Docker engine of the machine
// instance.

GetURL returns a socket address to connect to Docker engine of the machine instance .


func (d *Driver) GetState() (state.State, error) {
	if err := d.checkLegacyDriver(true); err != nil {
		return state.None, err
	}

	c, err := d.newAzureClient()
	if err != nil {
		return state.None, err
	}
	powerState, err := c.GetVirtualMachinePowerState(
		d.ResourceGroup, d.naming().VM())
	if err != nil {
		return state.None, err
	}

	machineState := machineStateForVMPowerState(powerState)
	log.Debugf("Determined Azure PowerState=%q, docker-machine state=%q",
		powerState, machineState)
	return machineState, nil
}

func ( d * Driver ) GetState ( ) ( state . State , error ) { if err := d . checkLegacyDriver ( true ) ; err != nil { return state . None , err } c , err := d . newAzureClient ( ) if err != nil { return state . None , err } powerState , err := c . GetVirtualMachinePowerState ( d . ResourceGroup , d . naming ( ) . VM ( ) ) if err != nil { return state . None , err } machineState := machineStateForVMPowerState ( powerState ) log . Debugf ( " " , powerState , machineState ) return machineState , nil }

// GetState returns the state of the virtual machine role instance.

GetState returns the state of the virtual machine role instance .


func (d *Driver) Start() error {
	if err := d.checkLegacyDriver(true); err != nil {
		return err
	}

	c, err := d.newAzureClient()
	if err != nil {
		return err
	}
	return c.StartVirtualMachine(d.ResourceGroup, d.naming().VM())
}

func ( d * Driver ) Start ( ) error { if err := d . checkLegacyDriver ( true ) ; err != nil { return err } c , err := d . newAzureClient ( ) if err != nil { return err } return c . StartVirtualMachine ( d . ResourceGroup , d . naming ( ) . VM ( ) ) }

// Start issues a power on for the virtual machine instance.

Start issues a power on for the virtual machine instance .


func (d *Driver) Stop() error {
	if err := d.checkLegacyDriver(true); err != nil {
		return err
	}

	c, err := d.newAzureClient()
	if err != nil {
		return err
	}
	log.Info("NOTICE: Stopping an Azure Virtual Machine is just going to power it off, not deallocate.")
	log.Info("NOTICE: You should remove the machine if you would like to avoid unexpected costs.")
	return c.StopVirtualMachine(d.ResourceGroup, d.naming().VM())
}

func ( d * Driver ) Stop ( ) error { if err := d . checkLegacyDriver ( true ) ; err != nil { return err } c , err := d . newAzureClient ( ) if err != nil { return err } log . Info ( " " ) log . Info ( " " ) return c . StopVirtualMachine ( d . ResourceGroup , d . naming ( ) . VM ( ) ) }

// Stop issues a power off for the virtual machine instance.

Stop issues a power off for the virtual machine instance .


func (d *Driver) Restart() error {
	if err := d.checkLegacyDriver(true); err != nil {
		return err
	}

	// NOTE(ahmetalpbalkan) Azure will always keep the VM in Running state
	// during the restart operation. Hence we rely on returned async operation
	// polling to make sure the reboot is waited upon.
	c, err := d.newAzureClient()
	if err != nil {
		return err
	}
	return c.RestartVirtualMachine(d.ResourceGroup, d.naming().VM())
}

// Restart reboots the virtual machine instance.

Restart reboots the virtual machine instance .


func create() {
	log.SetDebug(true)

	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	defer client.Close()

	hostName := "myfunhost"

	// Set some options on the provider...
	driver := virtualbox.NewDriver(hostName, "/tmp/automatic")
	driver.CPU = 2
	driver.Memory = 2048

	data, err := json.Marshal(driver)
	if err != nil {
		log.Error(err)
		return
	}

	h, err := client.NewHost("virtualbox", data)
	if err != nil {
		log.Error(err)
		return
	}

	h.HostOptions.EngineOptions.StorageDriver = "overlay"

	if err := client.Create(h); err != nil {
		log.Error(err)
		return
	}

	out, err := h.RunSSHCommand("df -h")
	if err != nil {
		log.Error(err)
		return
	}

	fmt.Printf("Results of your disk space query:\n%s\n", out)

	fmt.Println("Powering down machine now...")
	if err := h.Stop(); err != nil {
		log.Error(err)
		return
	}
}

func
create
(
)
{
log
.
SetDebug
(
true
)
client
:=
libmachine
.
NewClient
(
"
"
,
"
"
)
defer
client
.
Close
(
)
hostName
:=
"
"
// Set some options on the provider...
driver
:=
virtualbox
.
NewDriver
(
hostName
,
"
"
)
driver
.
CPU
=
2
driver
.
Memory
=
2048
data
,
err
:=
json
.
Marshal
(
driver
)
if
err
!=
{
log
.
Error
(
err
)
return
}
h
,
err
:=
client
.
NewHost
(
"
"
,
data
)
if
err
!=
{
log
.
Error
(
err
)
return
}
h
.
HostOptions
.
EngineOptions
.
StorageDriver
=
"
"
if
err
:=
client
.
Create
(
h
)
;
err
!=
{
log
.
Error
(
err
)
return
}
out
,
err
:=
h
.
RunSSHCommand
(
"
"
)
if
err
!=
{
log
.
Error
(
err
)
return
}
fmt
.
Printf
(
"
\n
\n
"
,
out
)
fmt
.
Println
(
"
"
)
if
err
:=
h
.
Stop
(
)
;
err
!=
{
log
.
Error
(
err
)
return
}
}

// Sample Virtualbox create independent of Machine CLI.

Sample Virtualbox create independent of Machine CLI .


func streaming() {
	log.SetDebug(true)

	client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs")
	defer client.Close()

	hostName := "myfunhost"

	// Set some options on the provider...
	driver := virtualbox.NewDriver(hostName, "/tmp/automatic")
	data, err := json.Marshal(driver)
	if err != nil {
		log.Error(err)
		return
	}

	h, err := client.NewHost("virtualbox", data)
	if err != nil {
		log.Error(err)
		return
	}

	if err := client.Create(h); err != nil {
		log.Error(err)
		return
	}

	h.HostOptions.EngineOptions.StorageDriver = "overlay"

	sshClient, err := h.CreateSSHClient()
	if err != nil {
		log.Error(err)
		return
	}

	stdout, stderr, err := sshClient.Start("yes | head -n 10000")
	if err != nil {
		log.Error(err)
		return
	}
	defer func() {
		_ = stdout.Close()
		_ = stderr.Close()
	}()

	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		log.Error(err)
	}
	if err := sshClient.Wait(); err != nil {
		log.Error(err)
	}

	fmt.Println("Powering down machine now...")
	if err := h.Stop(); err != nil {
		log.Error(err)
		return
	}
}

func
streaming
(
)
{
log
.
SetDebug
(
true
)
client
:=
libmachine
.
NewClient
(
"
"
,
"
"
)
defer
client
.
Close
(
)
hostName
:=
"
"
// Set some options on the provider...
driver
:=
virtualbox
.
NewDriver
(
hostName
,
"
"
)
data
,
err
:=
json
.
Marshal
(
driver
)
if
err
!=
{
log
.
Error
(
err
)
return
}
h
,
err
:=
client
.
NewHost
(
"
"
,
data
)
if
err
!=
{
log
.
Error
(
err
)
return
}
if
err
:=
client
.
Create
(
h
)
;
err
!=
{
log
.
Error
(
err
)
return
}
h
.
HostOptions
.
EngineOptions
.
StorageDriver
=
"
"
sshClient
,
err
:=
h
.
CreateSSHClient
(
)
if
err
!=
{
log
.
Error
(
err
)
return
}
stdout
,
stderr
,
err
:=
sshClient
.
Start
(
"
"
)
if
err
!=
{
log
.
Error
(
err
)
return
}
defer
func
(
)
{
_
=
stdout
.
Close
(
)
_
=
stderr
.
Close
(
)
}
(
)
scanner
:=
bufio
.
NewScanner
(
stdout
)
for
scanner
.
Scan
(
)
{
fmt
.
Println
(
scanner
.
Text
(
)
)
}
if
err
:=
scanner
.
Err
(
)
;
err
!=
{
log
.
Error
(
err
)
}
if
err
:=
sshClient
.
Wait
(
)
;
err
!=
{
log
.
Error
(
err
)
}
fmt
.
Println
(
"
"
)
if
err
:=
h
.
Stop
(
)
;
err
!=
{
log
.
Error
(
err
)
return
}
}

// Streaming the output of an SSH session in virtualbox.

Streaming the output of an SSH session in virtualbox .


func NewDriver(hostName, storePath string) *Driver {
	return &Driver{
		DiskSize:             defaultDiskSize,
		MemSize:              defaultMemory,
		CPU:                  defaultCPU,
		DisableDynamicMemory: defaultDisableDynamicMemory,
		BaseDriver: &drivers.BaseDriver{
			MachineName: hostName,
			StorePath:   storePath,
		},
	}
}

func NewDriver ( hostName , storePath string ) * Driver { return & Driver { DiskSize : defaultDiskSize , MemSize : defaultMemory , CPU : defaultCPU , DisableDynamicMemory : defaultDisableDynamicMemory , BaseDriver : & drivers . BaseDriver { MachineName : hostName , StorePath : storePath , } , } }

// NewDriver creates a new Hyper-v driver with default settings.

NewDriver creates a new Hyper - v driver with default settings .


func (d *Driver) waitForIP() (string, error) {
	log.Infof("Waiting for host to start...")

	for {
		ip, _ := d.GetIP()
		if ip != "" {
			return ip, nil
		}

		time.Sleep(1 * time.Second)
	}
}

func ( d * Driver ) waitForIP ( ) ( string , error ) { log . Infof ( " " ) for { ip , _ := d . GetIP ( ) if ip != " " { return ip , nil } time . Sleep ( 1 * time . Second ) } }

// waitForIP waits until the host has a valid IP


func (d *Driver) waitStopped() error {
	log.Infof("Waiting for host to stop...")

	for {
		s, err := d.GetState()
		if err != nil {
			return err
		}

		if s != state.Running {
			return nil
		}

		time.Sleep(1 * time.Second)
	}
}

func ( d * Driver ) waitStopped ( ) error { log . Infof ( " " ) for { s , err := d . GetState ( ) if err != nil { return err } if s != state . Running { return nil } time . Sleep ( 1 * time . Second ) } }

// waitStopped waits until the host is stopped


func (d *Driver) Start() error {
	if err := cmd("Hyper-V\\Start-VM", d.MachineName); err != nil {
		return err
	}

	ip, err := d.waitForIP()
	if err != nil {
		return err
	}

	d.IPAddress = ip

	return nil
}

func ( d * Driver ) Start ( ) error { if err := cmd ( " \\ " , d . MachineName ) ; err != nil { return err } ip , err := d . waitForIP ( ) if err != nil { return err } d . IPAddress = ip return nil }


func (d *Driver) Stop() error {
	if err := cmd("Hyper-V\\Stop-VM", d.MachineName); err != nil {
		return err
	}

	if err := d.waitStopped(); err != nil {
		return err
	}

	d.IPAddress = ""

	return nil
}

func ( d * Driver ) Stop ( ) error { if err := cmd ( " \\ " , d . MachineName ) ; err != nil { return err } if err := d . waitStopped ( ) ; err != nil { return err } d . IPAddress = " " return nil }


func (d *Driver) Remove() error {
	s, err := d.GetState()
	if err != nil {
		return err
	}

	if s == state.Running {
		if err := d.Kill(); err != nil {
			return err
		}
	}

	return cmd("Hyper-V\\Remove-VM", d.MachineName, "-Force")
}

func ( d * Driver ) Remove ( ) error { s , err := d . GetState ( ) if err != nil { return err } if s == state . Running { if err := d . Kill ( ) ; err != nil { return err } } return cmd ( " \\ " , d . MachineName , " " ) }


func (d *Driver) generateDiskImage() (string, error) {
	diskImage := d.ResolveStorePath("disk.vhd")
	fixed := d.ResolveStorePath("fixed.vhd")

	// Resizing vhds requires administrator privileges
	// incase the user is only a hyper-v admin then create the disk at the target size to avoid resizing.
	isWindowsAdmin, err := isWindowsAdministrator()
	if err != nil {
		return "", err
	}
	fixedDiskSize := "10MB"
	if !isWindowsAdmin {
		fixedDiskSize = toMb(d.DiskSize)
	}

	log.Infof("Creating VHD")
	if err := cmd("Hyper-V\\New-VHD", "-Path", quote(fixed), "-SizeBytes", fixedDiskSize, "-Fixed"); err != nil {
		return "", err
	}

	tarBuf, err := mcnutils.MakeDiskImage(d.publicSSHKeyPath())
	if err != nil {
		return "", err
	}

	file, err := os.OpenFile(fixed, os.O_WRONLY, 0644)
	if err != nil {
		return "", err
	}
	defer file.Close()

	file.Seek(0, os.SEEK_SET)
	_, err = file.Write(tarBuf.Bytes())
	if err != nil {
		return "", err
	}
	file.Close()

	if err := cmd("Hyper-V\\Convert-VHD", "-Path", quote(fixed), "-DestinationPath", quote(diskImage), "-VHDType", "Dynamic", "-DeleteSource"); err != nil {
		return "", err
	}

	if isWindowsAdmin {
		if err := cmd("Hyper-V\\Resize-VHD", "-Path", quote(diskImage), "-SizeBytes", toMb(d.DiskSize)); err != nil {
			return "", err
		}
	}

	return diskImage, nil
}

// generateDiskImage creates a small fixed vhd, put the tar in, convert to dynamic, then resize

generateDiskImage creates a small fixed vhd put the tar in convert to dynamic then resize


func (d *BaseDriver) GetIP() (string, error) {
	if d.IPAddress == "" {
		return "", errors.New("IP address is not set")
	}
	return d.IPAddress, nil
}

func ( d * BaseDriver ) GetIP ( ) ( string , error ) { if d . IPAddress == " " { return " " , errors . New ( " " ) } return d . IPAddress , nil }


func (d *BaseDriver) GetSSHKeyPath() string {
	if d.SSHKeyPath == "" {
		d.SSHKeyPath = d.ResolveStorePath("id_rsa")
	}
	return d.SSHKeyPath
}

func ( d * BaseDriver ) GetSSHKeyPath ( ) string { if d . SSHKeyPath == " " { d . SSHKeyPath = d . ResolveStorePath ( " " ) } return d . SSHKeyPath }

// GetSSHKeyPath returns the ssh key path


func (d *BaseDriver) GetSSHPort() (int, error) {
	if d.SSHPort == 0 {
		d.SSHPort = DefaultSSHPort
	}

	return d.SSHPort, nil
}

func ( d * BaseDriver ) GetSSHPort ( ) ( int , error ) { if d . SSHPort == 0 { d . SSHPort = DefaultSSHPort } return d . SSHPort , nil }

// GetSSHPort returns the ssh port, 22 if not specified

GetSSHPort returns the ssh port 22 if not specified


func (d *BaseDriver) GetSSHUsername() string {
	if d.SSHUser == "" {
		d.SSHUser = DefaultSSHUser
	}
	return d.SSHUser
}

func ( d * BaseDriver ) GetSSHUsername ( ) string { if d . SSHUser == " " { d . SSHUser = DefaultSSHUser } return d . SSHUser }

// GetSSHUsername returns the ssh user name, root if not specified

GetSSHUsername returns the ssh user name root if not specified


func (d *BaseDriver) ResolveStorePath(file string) string {
	return filepath.Join(d.StorePath, "machines", d.MachineName, file)
}

func ( d * BaseDriver ) ResolveStorePath ( file string ) string { return filepath . Join ( d . StorePath , " " , d . MachineName , file ) }

// ResolveStorePath returns the store path where the machine is


func (d *BaseDriver) SetSwarmConfigFromFlags(flags DriverOptions) {
	d.SwarmMaster = flags.Bool("swarm-master")
	d.SwarmHost = flags.String("swarm-host")
	d.SwarmDiscovery = flags.String("swarm-discovery")
}

func ( d * BaseDriver ) SetSwarmConfigFromFlags ( flags DriverOptions ) { d . SwarmMaster = flags . Bool ( " " ) d . SwarmHost = flags . String ( " " ) d . SwarmDiscovery = flags . String ( " " ) }

// SetSwarmConfigFromFlags configures the driver for swarm


func (d *Driver) IsVTXDisabledInTheVM() (bool, error) {
	lines, err := d.readVBoxLog()
	if err != nil {
		return true, err
	}

	for _, line := range lines {
		if strings.Contains(line, "VT-x is disabled") && !strings.Contains(line, "Falling back to raw-mode: VT-x is disabled in the BIOS for all CPU modes") {
			return true, nil
		}
		if strings.Contains(line, "the host CPU does NOT support HW virtualization") {
			return true, nil
		}
		if strings.Contains(line, "VERR_VMX_UNABLE_TO_START_VM") {
			return true, nil
		}
		if strings.Contains(line, "Power up failed") && strings.Contains(line, "VERR_VMX_NO_VMX") {
			return true, nil
		}
	}

	return false, nil
}

func ( d * Driver ) IsVTXDisabledInTheVM ( ) ( bool , error ) { lines , err := d . readVBoxLog ( ) if err != nil { return true , err } for _ , line := range lines { if strings . Contains ( line , " " ) && ! strings . Contains ( line , " " ) { return true , nil } if strings . Contains ( line , " " ) { return true , nil } if strings . Contains ( line , " " ) { return true , nil } if strings . Contains ( line , " " ) && strings . Contains ( line , " " ) { return true , nil } } return false , nil }

// IsVTXDisabledInTheVM checks if VT-X is disabled in the started vm.

IsVTXDisabledInTheVM checks if VT - X is disabled in the started vm .


func (*b2dReleaseGetter) getReleaseTag(apiURL string) (string, error) {
	if apiURL == "" {
		apiURL = defaultURL
	}

	if !version.RC() {
		// Just go straight to the convenience URL for "/latest" if we
		// are a non-release candidate version.  "/latest" won't return
		// non-RCs, so that's what we use for stable releases of
		// Machine.
		apiURL = apiURL + "/latest"
	}

	client := getClient()
	req, err := getRequest(apiURL)
	if err != nil {
		return "", err
	}
	rsp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer rsp.Body.Close()

	// If we call the API endpoint
	// "/repos/boot2docker/boot2docker/releases" without specifying
	// "/latest", we will receive a list of releases instead of a single
	// one, and we should decode accordingly.
	if version.RC() {
		var tags []struct {
			TagName string `json:"tag_name"`
		}
		if err := json.NewDecoder(rsp.Body).Decode(&tags); err != nil {
			return "", err
		}
		t := tags[0]
		if t.TagName == "" {
			return "", errGitHubAPIResponse
		}
		return t.TagName, nil
	}

	// Otherwise, we get back just one release, which we can decode to get
	// the tag.
	var t struct {
		TagName string `json:"tag_name"`
	}
	if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil {
		return "", err
	}
	if t.TagName == "" {
		return "", errGitHubAPIResponse
	}
	return t.TagName, nil
}

// getReleaseTag gets the release tag of Boot2Docker from apiURL.

getReleaseTag gets the release tag of Boot2Docker from apiURL .


func (b *b2dReleaseGetter) getReleaseURL(apiURL string) (string, error) {
	if apiURL == "" {
		apiURL = defaultURL
	}

	// match github (enterprise) release urls:
	// https://api.github.com/repos/../../releases or
	// https://some.github.enterprise/api/v3/repos/../../releases
	re := regexp.MustCompile("(https?)://([^/]+)(/api/v3)?/repos/([^/]+)/([^/]+)/releases")
	matches := re.FindStringSubmatch(apiURL)
	if len(matches) != 6 {
		// does not match a github releases api URL
		return apiURL, nil
	}

	scheme, host, org, repo := matches[1], matches[2], matches[4], matches[5]
	if host == "api.github.com" {
		host = "github.com"
	}

	tag, err := b.getReleaseTag(apiURL)
	if err != nil {
		return "", err
	}

	log.Infof("Latest release for %s/%s/%s is %s", host, org, repo, tag)
	bugURL, ok := AUFSBugB2DVersions[tag]
	if ok {
		log.Warnf(`
Boot2Docker %s has a known issue with AUFS.
See here for more details: %s
Consider specifying another storage driver (e.g. 'overlay') using '--engine-storage-driver' instead.
`, tag, bugURL)
	}
	url := fmt.Sprintf("%s://%s/%s/%s/releases/download/%s/%s", scheme, host, org, repo, tag, b.isoFilename)
	return url, nil
}

// getReleaseURL gets the latest release URL of Boot2Docker.

getReleaseURL gets the latest release URL of Boot2Docker .


func (b *b2dISO) version() (string, error) {
	if b == nil {
		return "", nil
	}

	iso, err := os.Open(b.commonIsoPath)
	if err != nil {
		return "", err
	}
	defer iso.Close()

	isoMetadata := make([]byte, b.volumeIDLength)
	_, err = iso.ReadAt(isoMetadata, b.volumeIDOffset)
	if err != nil {
		return "", err
	}

	trimmedVersion := strings.TrimSpace(string(isoMetadata))

	versionIndex := strings.Index(trimmedVersion, versionPrefix)
	if versionIndex == -1 {
		return "", fmt.Errorf("Did not find prefix %q in version string", versionPrefix)
	}

	// Original magic file string looks similar to this: "Boot2Docker-v0.1.0              "
	// This will return "v0.1.0" given the above string
	vers := trimmedVersion[versionIndex+1:]

	log.Debug("local Boot2Docker ISO version: ", vers)
	return vers, nil
}

// version scans the volume ID in b and returns its version tag.

version scans the volume ID in b and returns its version tag .


func (b *B2dUtils) DownloadISO(dir, file, isoURL string) error {
	log.Infof("Downloading %s from %s...", b.path(), isoURL)
	return b.download(dir, file, isoURL)
}

func ( b * B2dUtils ) DownloadISO ( dir , file , isoURL string ) error { log . Infof ( " " , b . path ( ) , isoURL ) return b . download ( dir , file , isoURL ) }

// DownloadISO downloads boot2docker ISO image for the given tag and save it at dest.

DownloadISO downloads boot2docker ISO image for the given tag and save it at dest .


func (c *Client) Authenticate(d *openstack.Driver) error {
	if c.Provider != nil {
		return nil
	}

	log.Debug("Authenticating to Rackspace.", map[string]string{
		"Username": d.Username,
	})

	apiKey := c.driver.APIKey
	opts := gophercloud.AuthOptions{
		Username: d.Username,
		APIKey:   apiKey,
	}

	provider, err := rackspace.NewClient(rackspace.RackspaceUSIdentity)
	if err != nil {
		return err
	}

	provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%d", version.APIVersion))

	err = rackspace.Authenticate(provider, opts)
	if err != nil {
		return err
	}

	c.Provider = provider

	return nil
}

func ( c * Client ) Authenticate ( d * openstack . Driver ) error { if c . Provider != nil { return nil } log . Debug ( " " , map [ string ] string { " " : d . Username , } ) apiKey := c . driver . APIKey opts := gophercloud . AuthOptions { Username : d . Username , APIKey : apiKey , } provider , err := rackspace . NewClient ( rackspace . RackspaceUSIdentity ) if err != nil { return err } provider . UserAgent . Prepend ( fmt . Sprintf ( " " , version . APIVersion ) ) err = rackspace . Authenticate ( provider , opts ) if err != nil { return err } c . Provider = provider return nil }

// Authenticate creates a Rackspace-specific Gophercloud client.

Authenticate creates a Rackspace - specific Gophercloud client .


func (c *Client) GetInstanceIPAddresses(d *openstack.Driver) ([]openstack.IPAddress, error) {
	server, err := c.GetServerDetail(d)
	if err != nil {
		return nil, err
	}
	return []openstack.IPAddress{
		{
			Network:     "public",
			Address:     server.AccessIPv4,
			AddressType: openstack.Fixed,
		},
	}, nil
}

func ( c * Client ) GetInstanceIPAddresses ( d * openstack . Driver ) ( [ ] openstack . IPAddress , error ) { server , err := c . GetServerDetail ( d ) if err != nil { return nil , err } return [ ] openstack . IPAddress { { Network : " " , Address : server . AccessIPv4 , AddressType : openstack . Fixed , } , } , nil }

// GetInstanceIPAddresses can be short-circuited with the server's AccessIPv4Addr on Rackspace.

GetInstanceIPAddresses can be short - circuited with the server s AccessIPv4Addr on Rackspace .


func targetHost(c CommandLine, api libmachine.API) (string, error) {
	if len(c.Args()) == 0 {
		defaultExists, err := api.Exists(defaultMachineName)
		if err != nil {
			return "", fmt.Errorf("Error checking if host %q exists: %s", defaultMachineName, err)
		}

		if defaultExists {
			return defaultMachineName, nil
		}

		return "", ErrNoDefault
	}

	return c.Args()[0], nil
}

func targetHost ( c CommandLine , api libmachine . API ) ( string , error ) { if len ( c . Args ( ) ) == 0 { defaultExists , err := api . Exists ( defaultMachineName ) if err != nil { return " " , fmt . Errorf ( " " , defaultMachineName , err ) } if defaultExists { return defaultMachineName , nil } return " " , ErrNoDefault } return c . Args ( ) [ 0 ] , nil }

// targetHost returns a specific host name if one is indicated by the first CLI
// arg, or the default host name if no host is specified.

targetHost returns a specific host name if one is indicated by the first CLI arg or the default host name if no host is specified .


func machineCommand(actionName string, host *host.Host, errorChan chan<- error) {
	// TODO: These actions should have their own type.
	commands := map[string](func() error){
		"configureAuth":    host.ConfigureAuth,
		"configureAllAuth": host.ConfigureAllAuth,
		"start":            host.Start,
		"stop":             host.Stop,
		"restart":          host.Restart,
		"kill":             host.Kill,
		"upgrade":          host.Upgrade,
		"ip":               printIP(host),
		"provision":        host.Provision,
	}

	log.Debugf("command=%s machine=%s", actionName, host.Name)

	errorChan <- commands[actionName]()
}

// machineCommand maps the command name to the corresponding machine command.
// We run commands concurrently and communicate back an error if there was one.

machineCommand maps the command name to the corresponding machine command . We run commands concurrently and communicate back an error if there was one .


func runActionForeachMachine(actionName string, machines []*host.Host) []error {
	var (
		numConcurrentActions = 0
		errorChan            = make(chan error)
		errs                 = []error{}
	)

	for _, machine := range machines {
		numConcurrentActions++
		go machineCommand(actionName, machine, errorChan)
	}

	// TODO: We should probably only do 5-10 of these
	// at a time, since otherwise cloud providers might
	// rate limit us.
	for i := 0; i < numConcurrentActions; i++ {
		if err := <-errorChan; err != nil {
			errs = append(errs, err)
		}
	}

	close(errorChan)

	return errs
}

// runActionForeachMachine will run the command across multiple machines


func (api *Client) Create(h *host.Host) error {
	if err := cert.BootstrapCertificates(h.AuthOptions()); err != nil {
		return fmt.Errorf("Error generating certificates: %s", err)
	}

	log.Info("Running pre-create checks...")

	if err := h.Driver.PreCreateCheck(); err != nil {
		return mcnerror.ErrDuringPreCreate{
			Cause: err,
		}
	}

	if err := api.Save(h); err != nil {
		return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
	}

	log.Info("Creating machine...")

	if err := api.performCreate(h); err != nil {
		return fmt.Errorf("Error creating machine: %s", err)
	}

	log.Debug("Reticulating splines...")

	return nil
}

func ( api * Client ) Create ( h * host . Host ) error { if err := cert . BootstrapCertificates ( h . AuthOptions ( ) ) ; err != nil { return fmt . Errorf ( " " , err ) } log . Info ( " " ) if err := h . Driver . PreCreateCheck ( ) ; err != nil { return mcnerror . ErrDuringPreCreate { Cause : err , } } if err := api . Save ( h ) ; err != nil { return fmt . Errorf ( " " , err ) } log . Info ( " " ) if err := api . performCreate ( h ) ; err != nil { return fmt . Errorf ( " " , err ) } log . Debug ( " " ) return nil }

// Create is the wrapper method which covers all of the boilerplate around
// actually creating, provisioning, and persisting an instance in the store.

Create is the wrapper method which covers all of the boilerplate around actually creating provisioning and persisting an instance in the store .


func GenerateRandomID() string {
	for {
		id := make([]byte, 32)
		if _, err := io.ReadFull(rand.Reader, id); err != nil {
			panic(err) // This shouldn't happen
		}
		value := hex.EncodeToString(id)
		// if we try to parse the truncated for as an int and we don't have
		// an error then the value is all numeric and causes issues when
		// used as a hostname. ref #3869
		if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil {
			continue
		}
		return value
	}
}

// GenerateRandomID returns an unique id


func (d *Driver) GetCreateFlags() []mcnflag.Flag {
	return []mcnflag.Flag{
		mcnflag.StringFlag{
			EnvVar: "OS_USERNAME",
			Name:   "rackspace-username",
			Usage:  "Rackspace account username",
			Value:  "",
		},
		mcnflag.StringFlag{
			EnvVar: "OS_API_KEY",
			Name:   "rackspace-api-key",
			Usage:  "Rackspace API key",
			Value:  "",
		},
		mcnflag.StringFlag{
			EnvVar: "OS_REGION_NAME",
			Name:   "rackspace-region",
			Usage:  "Rackspace region name",
			Value:  defaultRegionName,
		},
		mcnflag.StringFlag{
			EnvVar: "OS_ENDPOINT_TYPE",
			Name:   "rackspace-endpoint-type",
			Usage:  "Rackspace endpoint type (adminURL, internalURL or the default publicURL)",
			Value:  defaultEndpointType,
		},
		mcnflag.StringFlag{
			EnvVar: "OS_IMAGE_ID",
			Name:   "rackspace-image-id",
			Usage:  "Rackspace image ID. Default: Ubuntu 16.04 LTS (Xenial Xerus) (PVHVM)",
		},
		mcnflag.StringFlag{
			EnvVar: "OS_FLAVOR_ID",
			Name:   "rackspace-flavor-id",
			Usage:  "Rackspace flavor ID. Default: General Purpose 1GB",
			Value:  defaultFlavorID,
		},
		mcnflag.StringFlag{
			EnvVar: "OS_SSH_USER",
			Name:   "rackspace-ssh-user",
			Usage:  "SSH user for the newly booted machine. Set to root by default",
			Value:  defaultSSHUser,
		},
		mcnflag.IntFlag{
			EnvVar: "OS_SSH_PORT",
			Name:   "rackspace-ssh-port",
			Usage:  "SSH port for the newly booted machine. Set to 22 by default",
			Value:  defaultSSHPort,
		},
		mcnflag.StringFlag{
			Name:  "rackspace-docker-install",
			Usage: "Set if docker have to be installed on the machine",
			Value: defaultDockerInstall,
		},
		mcnflag.IntFlag{
			EnvVar: "OS_ACTIVE_TIMEOUT",
			Name:   "rackspace-active-timeout",
			Usage:  "Rackspace active timeout",
			Value:  defaultActiveTimeout,
		},
	}
}

func ( d * Driver ) GetCreateFlags ( ) [ ] mcnflag . Flag { return [ ] mcnflag . Flag { mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultRegionName , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultEndpointType , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultFlavorID , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultSSHUser , } , mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultSSHPort , } , mcnflag . StringFlag { Name : " " , Usage : " " , Value : defaultDockerInstall , } , mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultActiveTimeout , } , } }

// GetCreateFlags registers the "machine create" flags recognized by this driver, including
// their help text and defaults.

GetCreateFlags registers the machine create flags recognized by this driver including their help text and defaults .


func NewDriver(machineName, storePath string) drivers.Driver {
	log.Debug("Instantiating Rackspace driver.", map[string]string{"machineName": machineName})

	inner := openstack.NewDerivedDriver(machineName, storePath)
	driver := &Driver{
		Driver: inner,
	}
	inner.SetClient(&Client{
		driver: driver,
	})

	return driver
}

func NewDriver ( machineName , storePath string ) drivers . Driver { log . Debug ( " " , map [ string ] string { " " : machineName } ) inner := openstack . NewDerivedDriver ( machineName , storePath ) driver := & Driver { Driver : inner , } inner . SetClient ( & Client { driver : driver , } ) return driver }

// NewDriver instantiates a Rackspace driver.

NewDriver instantiates a Rackspace driver .


func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
	d.ActiveTimeout = flags.Int("rackspace-active-timeout")
	d.Username = flags.String("rackspace-username")
	d.APIKey = flags.String("rackspace-api-key")
	d.Region = flags.String("rackspace-region")
	d.EndpointType = flags.String("rackspace-endpoint-type")
	d.ImageId = flags.String("rackspace-image-id")
	d.FlavorId = flags.String("rackspace-flavor-id")
	d.SSHUser = flags.String("rackspace-ssh-user")
	d.SSHPort = flags.Int("rackspace-ssh-port")
	d.SetSwarmConfigFromFlags(flags)

	if d.Region == "" {
		return missingEnvOrOption("Region", "OS_REGION_NAME", "--rackspace-region")
	}
	if d.Username == "" {
		return missingEnvOrOption("Username", "OS_USERNAME", "--rackspace-username")
	}
	if d.APIKey == "" {
		return missingEnvOrOption("API key", "OS_API_KEY", "--rackspace-api-key")
	}

	if d.ImageId == "" {
		// Default to the Ubuntu 16.04 image.
		// This is done here, rather than in the option registration, to keep the default value
		// from making "machine create --help" ugly.
		d.ImageId = "821ba5f4-712d-4ec8-9c65-a3fa4bc500f9"
	}

	if d.EndpointType != "publicURL" && d.EndpointType != "adminURL" && d.EndpointType != "internalURL" {
		return fmt.Errorf("invalid endpoint type %q (must be publicURL, adminURL or internalURL)", d.EndpointType)
	}

	return nil
}

// SetConfigFromFlags assigns and verifies the command-line arguments presented to the driver.

SetConfigFromFlags assigns and verifies the command - line arguments presented to the driver .


func (rd *RemoteDocker) URL() (string, error) {
	if rd.HostURL == "" {
		return "", fmt.Errorf("Docker Host URL not set")
	}

	return rd.HostURL, nil
}

func ( rd * RemoteDocker ) URL ( ) ( string , error ) { if rd . HostURL == " " { return " " , fmt . Errorf ( " " ) } return rd . HostURL , nil }


func (d *Driver) newAzureClient() (*azureutil.AzureClient, error) {
	env, ok := environments[d.Environment]
	if !ok {
		valid := make([]string, 0, len(environments))
		for k := range environments {
			valid = append(valid, k)
		}

		return nil, fmt.Errorf("Invalid Azure environment: %q, supported values: %s", d.Environment, strings.Join(valid, ", "))
	}

	var (
		token *azure.ServicePrincipalToken
		err   error
	)
	if d.ClientID != "" && d.ClientSecret != "" { // use Service Principal auth
		log.Debug("Using Azure service principal authentication.")
		token, err = azureutil.AuthenticateServicePrincipal(env, d.SubscriptionID, d.ClientID, d.ClientSecret)
		if err != nil {
			return nil, fmt.Errorf("Failed to authenticate using service principal credentials: %+v", err)
		}
	} else { // use browser-based device auth
		log.Debug("Using Azure device flow authentication.")
		token, err = azureutil.AuthenticateDeviceFlow(env, d.SubscriptionID)
		if err != nil {
			return nil, fmt.Errorf("Error creating Azure client: %v", err)
		}
	}
	return azureutil.New(env, d.SubscriptionID, token), nil
}

func
(
d
*
Driver
)
newAzureClient
(
)
(
*
azureutil
.
AzureClient
,
error
)
{
env
,
ok
:=
environments
[
d
.
Environment
]
if
!
ok
{
valid
:=
make
(
[
]
string
,
0
,
len
(
environments
)
)
for
k
:=
range
environments
{
valid
=
append
(
valid
,
k
)
}
return
,
fmt
.
Errorf
(
"
"
,
d
.
Environment
,
strings
.
Join
(
valid
,
"
"
)
)
}
var
(
token
*
azure
.
ServicePrincipalToken
err
error
)
if
d
.
ClientID
!=
"
"
&&
d
.
ClientSecret
!=
"
"
{
// use Service Principal auth
log
.
Debug
(
"
"
)
token
,
err
=
azureutil
.
AuthenticateServicePrincipal
(
env
,
d
.
SubscriptionID
,
d
.
ClientID
,
d
.
ClientSecret
)
if
err
!=
{
return
,
fmt
.
Errorf
(
"
"
,
err
)
}
}
else
{
// use browser-based device auth
log
.
Debug
(
"
"
)
token
,
err
=
azureutil
.
AuthenticateDeviceFlow
(
env
,
d
.
SubscriptionID
)
if
err
!=
{
return
,
fmt
.
Errorf
(
"
"
,
err
)
}
}
return
azureutil
.
New
(
env
,
d
.
SubscriptionID
,
token
)
,
}

// newAzureClient creates an AzureClient helper from the Driver context and
// initiates authentication if required.

newAzureClient creates an AzureClient helper from the Driver context and initiates authentication if required .


func (d *Driver) generateSSHKey(ctx *azureutil.DeploymentContext) error {
	privPath := d.GetSSHKeyPath()
	pubPath := privPath + ".pub"

	log.Debug("Creating SSH key...", logutil.Fields{
		"pub":  pubPath,
		"priv": privPath,
	})

	if err := ssh.GenerateSSHKey(privPath); err != nil {
		return err
	}
	log.Debug("SSH key pair generated.")

	publicKey, err := ioutil.ReadFile(pubPath)
	ctx.SSHPublicKey = string(publicKey)
	return err
}

func ( d * Driver ) generateSSHKey ( ctx * azureutil . DeploymentContext ) error { privPath := d . GetSSHKeyPath ( ) pubPath := privPath + " " log . Debug ( " " , logutil . Fields { " " : pubPath , " " : privPath , } ) if err := ssh . GenerateSSHKey ( privPath ) ; err != nil { return err } log . Debug ( " " ) publicKey , err := ioutil . ReadFile ( pubPath ) ctx . SSHPublicKey = string ( publicKey ) return err }

// generateSSHKey creates a ssh key pair locally and saves the public key file
// contents in OpenSSH format to the DeploymentContext.

generateSSHKey creates a ssh key pair locally and saves the public key file contents in OpenSSH format to the DeploymentContext .


func parseSecurityRuleProtocol(proto string) (network.SecurityRuleProtocol, error) {
	switch strings.ToLower(proto) {
	case "tcp":
		return network.TCP, nil
	case "udp":
		return network.UDP, nil
	case "*":
		return network.Asterisk, nil
	default:
		return "", fmt.Errorf("invalid protocol %s", proto)
	}
}

func parseSecurityRuleProtocol ( proto string ) ( network . SecurityRuleProtocol , error ) { switch strings . ToLower ( proto ) { case " " : return network . TCP , nil case " " : return network . UDP , nil case " " : return network . Asterisk , nil default : return " " , fmt . Errorf ( " " , proto ) } }

// parseSecurityRuleProtocol parses a protocol string into a network.SecurityRuleProtocol
// and returns error if the protocol is not supported

parseSecurityRuleProtocol parses a protocol string into a network . SecurityRuleProtocol and returns error if the protocol is not supported


func (s State) String() string {
	if int(s) >= 0 && int(s) < len(states) {
		return states[s]
	}
	return ""
}

func ( s State ) String ( ) string { if int ( s ) >= 0 && int ( s ) < len ( states ) { return states [ s ] } return " " }

// Given a State type, returns its string representation

Given a State type returns its string representation


func randomString(n int, alphabet string) string {
	r := timeSeed()
	b := make([]byte, n)
	for i := range b {
		b[i] = alphabet[r.Intn(len(alphabet))]
	}
	return string(b)
}

func randomString ( n int , alphabet string ) string { r := timeSeed ( ) b := make ( [ ] byte , n ) for i := range b { b [ i ] = alphabet [ r . Intn ( len ( alphabet ) ) ] } return string ( b ) }

// randomString generates a random string of given length using specified alphabet.

randomString generates a random string of given length using specified alphabet .


func (d *Driver) GetCreateFlags() []mcnflag.Flag {
	return []mcnflag.Flag{
		mcnflag.IntFlag{
			EnvVar: "VSPHERE_CPU_COUNT",
			Name:   "vmwarevsphere-cpu-count",
			Usage:  "vSphere CPU number for docker VM",
			Value:  defaultCpus,
		},
		mcnflag.IntFlag{
			EnvVar: "VSPHERE_MEMORY_SIZE",
			Name:   "vmwarevsphere-memory-size",
			Usage:  "vSphere size of memory for docker VM (in MB)",
			Value:  defaultMemory,
		},
		mcnflag.IntFlag{
			EnvVar: "VSPHERE_DISK_SIZE",
			Name:   "vmwarevsphere-disk-size",
			Usage:  "vSphere size of disk for docker VM (in MB)",
			Value:  defaultDiskSize,
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_BOOT2DOCKER_URL",
			Name:   "vmwarevsphere-boot2docker-url",
			Usage:  "vSphere URL for boot2docker image",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_VCENTER",
			Name:   "vmwarevsphere-vcenter",
			Usage:  "vSphere IP/hostname for vCenter",
		},
		mcnflag.IntFlag{
			EnvVar: "VSPHERE_VCENTER_PORT",
			Name:   "vmwarevsphere-vcenter-port",
			Usage:  "vSphere Port for vCenter",
			Value:  defaultSDKPort,
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_USERNAME",
			Name:   "vmwarevsphere-username",
			Usage:  "vSphere username",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_PASSWORD",
			Name:   "vmwarevsphere-password",
			Usage:  "vSphere password",
		},
		mcnflag.StringSliceFlag{
			EnvVar: "VSPHERE_NETWORK",
			Name:   "vmwarevsphere-network",
			Usage:  "vSphere network where the docker VM will be attached",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_DATASTORE",
			Name:   "vmwarevsphere-datastore",
			Usage:  "vSphere datastore for docker VM",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_DATACENTER",
			Name:   "vmwarevsphere-datacenter",
			Usage:  "vSphere datacenter for docker VM",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_FOLDER",
			Name:   "vmwarevsphere-folder",
			Usage:  "vSphere folder for the docker VM. This folder must already exist in the datacenter.",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_POOL",
			Name:   "vmwarevsphere-pool",
			Usage:  "vSphere resource pool for docker VM",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_HOSTSYSTEM",
			Name:   "vmwarevsphere-hostsystem",
			Usage:  "vSphere compute resource where the docker VM will be instantiated. This can be omitted if using a cluster with DRS.",
		},
		mcnflag.StringSliceFlag{
			EnvVar: "VSPHERE_CFGPARAM",
			Name:   "vmwarevsphere-cfgparam",
			Usage:  "vSphere vm configuration parameters (used for guestinfo)",
		},
		mcnflag.StringFlag{
			EnvVar: "VSPHERE_CLOUDINIT",
			Name:   "vmwarevsphere-cloudinit",
			Usage:  "vSphere cloud-init file or url to set in the guestinfo",
		},
	}
}

func ( d * Driver ) GetCreateFlags ( ) [ ] mcnflag . Flag { return [ ] mcnflag . Flag { mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultCpus , } , mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultMemory , } , mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultDiskSize , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . IntFlag { EnvVar : " " , Name : " " , Usage : " " , Value : defaultSDKPort , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringSliceFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringSliceFlag { EnvVar : " " , Name : " " , Usage : " " , } , mcnflag . StringFlag { EnvVar : " " , Name : " " , Usage : " " , } , } }

// GetCreateFlags registers the flags this driver adds to
// "docker-machine create"

GetCreateFlags registers the flags this driver adds to docker - machine create


func (d *Driver) generateKeyBundle() error {
	log.Debugf("Creating Tar key bundle...")

	magicString := "boot2docker, this is vmware speaking"

	tf, err := os.Create(d.ResolveStorePath("userdata.tar"))
	if err != nil {
		return err
	}
	defer tf.Close()
	var fileWriter = tf

	tw := tar.NewWriter(fileWriter)
	defer tw.Close()

	// magicString first so we can figure out who originally wrote the tar.
	file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
	if err := tw.WriteHeader(file); err != nil {
		return err
	}
	if _, err := tw.Write([]byte(magicString)); err != nil {
		return err
	}
	// .ssh/key.pub => authorized_keys
	file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
	if err := tw.WriteHeader(file); err != nil {
		return err
	}
	pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
	if err != nil {
		return err
	}
	file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
	if err := tw.WriteHeader(file); err != nil {
		return err
	}
	if _, err := tw.Write([]byte(pubKey)); err != nil {
		return err
	}
	file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
	if err := tw.WriteHeader(file); err != nil {
		return err
	}
	if _, err := tw.Write([]byte(pubKey)); err != nil {
		return err
	}
	err = tw.Close()
	return err
}

// Make a boot2docker userdata.tar key bundle

Make a boot2docker userdata . tar key bundle


func NewDriver(hostName, storePath string) *Driver {
	return &Driver{
		VBoxManager:         NewVBoxManager(),
		b2dUpdater:          NewB2DUpdater(),
		sshKeyGenerator:     NewSSHKeyGenerator(),
		diskCreator:         NewDiskCreator(),
		logsReader:          NewLogsReader(),
		ipWaiter:            NewIPWaiter(),
		randomInter:         NewRandomInter(),
		sleeper:             NewSleeper(),
		HostInterfaces:      NewHostInterfaces(),
		Memory:              defaultMemory,
		CPU:                 defaultCPU,
		DiskSize:            defaultDiskSize,
		NatNicType:          defaultHostOnlyNictype,
		HostOnlyCIDR:        defaultHostOnlyCIDR,
		HostOnlyNicType:     defaultHostOnlyNictype,
		HostOnlyPromiscMode: defaultHostOnlyPromiscMode,
		UIType:              defaultUIType,
		HostOnlyNoDHCP:      defaultHostOnlyNoDHCP,
		DNSProxy:            defaultDNSProxy,
		HostDNSResolver:     defaultDNSResolver,
		BaseDriver: &drivers.BaseDriver{
			MachineName: hostName,
			StorePath:   storePath,
		},
	}
}

func NewDriver ( hostName , storePath string ) * Driver { return & Driver { VBoxManager : NewVBoxManager ( ) , b2dUpdater : NewB2DUpdater ( ) , sshKeyGenerator : NewSSHKeyGenerator ( ) , diskCreator : NewDiskCreator ( ) , logsReader : NewLogsReader ( ) , ipWaiter : NewIPWaiter ( ) , randomInter : NewRandomInter ( ) , sleeper : NewSleeper ( ) , HostInterfaces : NewHostInterfaces ( ) , Memory : defaultMemory , CPU : defaultCPU , DiskSize : defaultDiskSize , NatNicType : defaultHostOnlyNictype , HostOnlyCIDR : defaultHostOnlyCIDR , HostOnlyNicType : defaultHostOnlyNictype , HostOnlyPromiscMode : defaultHostOnlyPromiscMode , UIType : defaultUIType , HostOnlyNoDHCP : defaultHostOnlyNoDHCP , DNSProxy : defaultDNSProxy , HostDNSResolver : defaultDNSResolver , BaseDriver : & drivers . BaseDriver { MachineName : hostName , StorePath : storePath , } , } }

// NewDriver creates a new VirtualBox driver with default settings.

NewDriver creates a new VirtualBox driver with default settings .


func (d *Driver) PreCreateCheck() error {
	// Check that VBoxManage exists and works
	version, err := d.vbmOut("--version")
	if err != nil {
		return err
	}

	// Check that VBoxManage is of a supported version
	if err = checkVBoxManageVersion(strings.TrimSpace(version)); err != nil {
		return err
	}

	if !d.NoVTXCheck {
		if isHyperVInstalled() {
			return ErrNotCompatibleWithHyperV
		}

		if d.IsVTXDisabled() {
			return ErrMustEnableVTX
		}
	}

	// Downloading boot2docker to cache should be done here to make sure
	// that a download failure will not leave a machine half created.
	if err := d.b2dUpdater.UpdateISOCache(d.StorePath, d.Boot2DockerURL); err != nil {
		return err
	}

	// Check that Host-only interfaces are ok
	if _, err = listHostOnlyAdapters(d.VBoxManager); err != nil {
		return err
	}

	return nil
}

// PreCreateCheck checks that VBoxManage exists and works


func validateNoIPCollisions(hif HostInterfaces, hostOnlyNet *net.IPNet, currHostOnlyNets map[string]*hostOnlyNetwork) error {
	hostOnlyByCIDR := map[string]*hostOnlyNetwork{}
	//listHostOnlyAdapters returns a map w/ virtualbox net names as key.  Rekey to CIDRs
	for _, n := range currHostOnlyNets {
		ipnet := net.IPNet{IP: n.IPv4.IP, Mask: n.IPv4.Mask}
		hostOnlyByCIDR[ipnet.String()] = n
	}

	m, err := listHostInterfaces(hif, hostOnlyByCIDR)
	if err != nil {
		return err
	}

	collision, err := checkIPNetCollision(hostOnlyNet, m)
	if err != nil {
		return err
	}

	if collision {
		return ErrNetworkAddrCollision
	}
	return nil
}

// validateNoIPCollisions ensures no conflicts between the host's network interfaces and the vbox host-only network that
// will be used for machine vm instances.

validateNoIPCollisions ensures no conflicts between the host s network interfaces and the vbox host - only network that will be used for machine vm instances .


func getAvailableTCPPort(port int) (int, error) {
	for i := 0; i <= 10; i++ {
		ln, err := net.Listen("tcp4", fmt.Sprintf("127.0.0.1:%d", port))
		if err != nil {
			return 0, err
		}
		defer ln.Close()
		addr := ln.Addr().String()
		addrParts := strings.SplitN(addr, ":", 2)
		p, err := strconv.Atoi(addrParts[1])
		if err != nil {
			return 0, err
		}
		if p != 0 {
			port = p
			return port, nil
		}
		port = 0 // Throw away the port hint before trying again
		time.Sleep(1)
	}
	return 0, fmt.Errorf("unable to allocate tcp port")
}

// Select an available port, trying the specified
// port first, falling back on an OS selected port.

Select an available port trying the specified port first falling back on an OS selected port .


func setPortForwarding(d *Driver, interfaceNum int, mapName, protocol string, guestPort, desiredHostPort int) (int, error) {
	actualHostPort, err := getAvailableTCPPort(desiredHostPort)
	if err != nil {
		return -1, err
	}
	if desiredHostPort != actualHostPort && desiredHostPort != 0 {
		log.Debugf("NAT forwarding host port for guest port %d (%s) changed from %d to %d",
			guestPort, mapName, desiredHostPort, actualHostPort)
	}
	cmd := fmt.Sprintf("--natpf%d", interfaceNum)
	d.vbm("modifyvm", d.MachineName, cmd, "delete", mapName)
	if err := d.vbm("modifyvm", d.MachineName,
		cmd, fmt.Sprintf("%s,%s,127.0.0.1,%d,,%d", mapName, protocol, actualHostPort, guestPort)); err != nil {
		return -1, err
	}
	return actualHostPort, nil
}

func setPortForwarding ( d * Driver , interfaceNum int , mapName , protocol string , guestPort , desiredHostPort int ) ( int , error ) { actualHostPort , err := getAvailableTCPPort ( desiredHostPort ) if err != nil { return - 1 , err } if desiredHostPort != actualHostPort && desiredHostPort != 0 { log . Debugf ( " " , guestPort , mapName , desiredHostPort , actualHostPort ) } cmd := fmt . Sprintf ( " " , interfaceNum ) d . vbm ( " " , d . MachineName , cmd , " " , mapName ) if err := d . vbm ( " " , d . MachineName , cmd , fmt . Sprintf ( " " , mapName , protocol , actualHostPort , guestPort ) ) ; err != nil { return - 1 , err } return actualHostPort , nil }


func getRandomIPinSubnet(d *Driver, baseIP net.IP) (net.IP, error) {
	var dhcpAddr net.IP

	nAddr := baseIP.To4()
	// select pseudo-random DHCP addr; make sure not to clash with the host
	// only try 5 times and bail if no random received
	for i := 0; i < 5; i++ {
		n := d.randomInter.RandomInt(24) + 1
		if byte(n) != nAddr[3] {
			dhcpAddr = net.IPv4(nAddr[0], nAddr[1], nAddr[2], byte(n))
			break
		}
	}

	if dhcpAddr == nil {
		return nil, ErrUnableToGenerateRandomIP
	}

	return dhcpAddr, nil
}

// getRandomIPinSubnet returns a pseudo-random net.IP in the same
// subnet as the IP passed

getRandomIPinSubnet returns a pseudo - random net . IP in the same subnet as the IP passed


func Detect() (string, error) {
	shell := os.Getenv("SHELL")

	if shell == "" {
		fmt.Printf("The default lines below are for a sh/bash shell, you can specify the shell you're using, with the --shell flag.\n\n")
		return "", ErrUnknownShell
	}

	return filepath.Base(shell), nil
}

func Detect ( ) ( string , error ) { shell := os . Getenv ( " " ) if shell == " " { fmt . Printf ( " \n \n " ) return " " , ErrUnknownShell } return filepath . Base ( shell ) , nil }


func vaultRenewDuration(s *Secret) time.Duration {
	// Handle whether this is an auth or a regular secret.
	base := s.LeaseDuration
	if s.Auth != nil && s.Auth.LeaseDuration > 0 {
		base = s.Auth.LeaseDuration
	}

	// Ensure we have a lease duration, since sometimes this can be zero.
	if base <= 0 {
		base = int(VaultDefaultLeaseDuration.Seconds())
	}

	// Convert to float seconds.
	sleep := float64(time.Duration(base) * time.Second)

	if vaultSecretRenewable(s) {
		// Renew at 1/3 the remaining lease. This will give us an opportunity to retry
		// at least one more time should the first renewal fail.
		sleep = sleep / 3.0

		// Use some randomness so many clients do not hit Vault simultaneously.
		sleep = sleep * (rand.Float64() + 1) / 2.0
	} else {
		// For non-renewable leases set the renew duration to use much of the secret
		// lease as possible. Use a stagger over 85%-95% of the lease duration so that
		// many clients do not hit Vault simultaneously.
		sleep = sleep * (.85 + rand.Float64()*0.1)
	}

	return time.Duration(sleep)
}

// vaultRenewDuration accepts a secret and returns the recommended amount of
// time to sleep.

vaultRenewDuration accepts a secret and returns the recommended amount of time to sleep .


func printVaultWarnings(d Dependency, warnings []string) {
	for _, w := range warnings {
		log.Printf("[WARN] %s: %s", d, w)
	}
}

func printVaultWarnings ( d Dependency , warnings [ ] string ) { for _ , w := range warnings { log . Printf ( " " , d , w ) } }

// printVaultWarnings prints warnings for a given dependency.

printVaultWarnings prints warnings for a given dependency .


func vaultSecretRenewable(s *Secret) bool {
	if s.Auth != nil {
		return s.Auth.Renewable
	}
	return s.Renewable
}

func vaultSecretRenewable ( s * Secret ) bool { if s . Auth != nil { return s . Auth . Renewable } return s . Renewable }

// vaultSecretRenewable determines if the given secret is renewable.

vaultSecretRenewable determines if the given secret is renewable .


func transformSecret(theirs *api.Secret) *Secret {
	var ours Secret
	updateSecret(&ours, theirs)
	return &ours
}

func transformSecret ( theirs * api . Secret ) * Secret { var ours Secret updateSecret ( & ours , theirs ) return & ours }

// transformSecret transforms an api secret into our secret. This does not deep
// copy underlying deep data structures, so it's not safe to modify the vault
// secret as that may modify the data in the transformed secret.

transformSecret transforms an api secret into our secret . This does not deep copy underlying deep data structures so it s not safe to modify the vault secret as that may modify the data in the transformed secret .


func updateSecret(ours *Secret, theirs *api.Secret) {
	if theirs.RequestID != "" {
		ours.RequestID = theirs.RequestID
	}

	if theirs.LeaseID != "" {
		ours.LeaseID = theirs.LeaseID
	}

	if theirs.LeaseDuration != 0 {
		ours.LeaseDuration = theirs.LeaseDuration
	}

	if theirs.Renewable {
		ours.Renewable = theirs.Renewable
	}

	if len(theirs.Data) != 0 {
		ours.Data = theirs.Data
	}

	if len(theirs.Warnings) != 0 {
		ours.Warnings = theirs.Warnings
	}

	if theirs.Auth != nil {
		if ours.Auth == nil {
			ours.Auth = &SecretAuth{}
		}

		if theirs.Auth.ClientToken != "" {
			ours.Auth.ClientToken = theirs.Auth.ClientToken
		}

		if theirs.Auth.Accessor != "" {
			ours.Auth.Accessor = theirs.Auth.Accessor
		}

		if len(theirs.Auth.Policies) != 0 {
			ours.Auth.Policies = theirs.Auth.Policies
		}

		if len(theirs.Auth.Metadata) != 0 {
			ours.Auth.Metadata = theirs.Auth.Metadata
		}

		if theirs.Auth.LeaseDuration != 0 {
			ours.Auth.LeaseDuration = theirs.Auth.LeaseDuration
		}

		if theirs.Auth.Renewable {
			ours.Auth.Renewable = theirs.Auth.Renewable
		}
	}

	if theirs.WrapInfo != nil {
		if ours.WrapInfo == nil {
			ours.WrapInfo = &SecretWrapInfo{}
		}

		if theirs.WrapInfo.Token != "" {
			ours.WrapInfo.Token = theirs.WrapInfo.Token
		}

		if theirs.WrapInfo.TTL != 0 {
			ours.WrapInfo.TTL = theirs.WrapInfo.TTL
		}

		if !theirs.WrapInfo.CreationTime.IsZero() {
			ours.WrapInfo.CreationTime = theirs.WrapInfo.CreationTime
		}

		if theirs.WrapInfo.WrappedAccessor != "" {
			ours.WrapInfo.WrappedAccessor = theirs.WrapInfo.WrappedAccessor
		}
	}
}

func updateSecret ( ours * Secret , theirs * api . Secret ) { if theirs . RequestID != " " { ours . RequestID = theirs . RequestID } if theirs . LeaseID != " " { ours . LeaseID = theirs . LeaseID } if theirs . LeaseDuration != 0 { ours . LeaseDuration = theirs . LeaseDuration } if theirs . Renewable { ours . Renewable = theirs . Renewable } if len ( theirs . Data ) != 0 { ours . Data = theirs . Data } if len ( theirs . Warnings ) != 0 { ours . Warnings = theirs . Warnings } if theirs . Auth != nil { if ours . Auth == nil { ours . Auth = & SecretAuth { } } if theirs . Auth . ClientToken != " " { ours . Auth . ClientToken = theirs . Auth . ClientToken } if theirs . Auth . Accessor != " " { ours . Auth . Accessor = theirs . Auth . Accessor } if len ( theirs . Auth . Policies ) != 0 { ours . Auth . Policies = theirs . Auth . Policies } if len ( theirs . Auth . Metadata ) != 0 { ours . Auth . Metadata = theirs . Auth . Metadata } if theirs . Auth . LeaseDuration != 0 { ours . Auth . LeaseDuration = theirs . Auth . LeaseDuration } if theirs . Auth . Renewable { ours . Auth . Renewable = theirs . Auth . Renewable } } if theirs . WrapInfo != nil { if ours . WrapInfo == nil { ours . WrapInfo = & SecretWrapInfo { } } if theirs . WrapInfo . Token != " " { ours . WrapInfo . Token = theirs . WrapInfo . Token } if theirs . WrapInfo . TTL != 0 { ours . WrapInfo . TTL = theirs . WrapInfo . TTL } if ! theirs . WrapInfo . CreationTime . IsZero ( ) { ours . WrapInfo . CreationTime = theirs . WrapInfo . CreationTime } if theirs . WrapInfo . WrappedAccessor != " " { ours . WrapInfo . WrappedAccessor = theirs . WrapInfo . WrappedAccessor } } }

// updateSecret updates our secret with the new data from the api, careful to
// not overwrite missing data. Renewals don't include the original secret, and
// we don't want to delete that data accidentally.

updateSecret updates our secret with the new data from the api careful to not overwrite missing data . Renewals don t include the original secret and we don t want to delete that data accidentally .


func (c *TemplateConfig) Display() string {
	if c == nil {
		return ""
	}

	source := c.Source
	if StringPresent(c.Contents) {
		source = String("(dynamic)")
	}

	return fmt.Sprintf("%q => %q",
		StringVal(source),
		StringVal(c.Destination),
	)
}

func ( c * TemplateConfig ) Display ( ) string { if c == nil { return " " } source := c . Source if StringPresent ( c . Contents ) { source = String ( " " ) } return fmt . Sprintf ( " " , StringVal ( source ) , StringVal ( c . Destination ) , ) }

// Display is the human-friendly form of this configuration. It tries to
// describe this template in as much detail as possible in a single line, so
// log consumers can uniquely identify it.

Display is the human - friendly form of this configuration . It tries to describe this template in as much detail as possible in a single line so log consumers can uniquely identify it .


func NewVaultWriteQuery(s string, d map[string]interface{}) (*VaultWriteQuery, error) {
	s = strings.TrimSpace(s)
	s = strings.Trim(s, "/")
	if s == "" {
		return nil, fmt.Errorf("vault.write: invalid format: %q", s)
	}

	return &VaultWriteQuery{
		stopCh:   make(chan struct{}, 1),
		path:     s,
		data:     d,
		dataHash: sha1Map(d),
	}, nil
}

func NewVaultWriteQuery ( s string , d map [ string ] interface { } ) ( * VaultWriteQuery , error ) { s = strings . TrimSpace ( s ) s = strings . Trim ( s , " " ) if s == " " { return nil , fmt . Errorf ( " " , s ) } return & VaultWriteQuery { stopCh : make ( chan struct { } , 1 ) , path : s , data : d , dataHash : sha1Map ( d ) , } , nil }

// NewVaultWriteQuery creates a new datacenter dependency.

NewVaultWriteQuery creates a new datacenter dependency .


func sha1Map(m map[string]interface{}) string {
	keys := make([]string, 0, len(m))
	for k, _ := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	h := sha1.New()
	for _, k := range keys {
		io.WriteString(h, fmt.Sprintf("%s=%q", k, m[k]))
	}

	return fmt.Sprintf("%.4x", h.Sum(nil))
}

func sha1Map ( m map [ string ] interface { } ) string { keys := make ( [ ] string , 0 , len ( m ) ) for k , _ := range m { keys = append ( keys , k ) } sort . Strings ( keys ) h := sha1 . New ( ) for _ , k := range keys { io . WriteString ( h , fmt . Sprintf ( " " , k , m [ k ] ) ) } return fmt . Sprintf ( " " , h . Sum ( nil ) ) }

// sha1Map returns the sha1 hash of the data in the map. The reason this data is
// hashed is because it appears in the output and could contain sensitive
// information.

sha1Map returns the sha1 hash of the data in the map . The reason this data is hashed is because it appears in the output and could contain sensitive information .


func NewView(i *NewViewInput) (*View, error) {
	return &View{
		dependency: i.Dependency,
		clients:    i.Clients,
		maxStale:   i.MaxStale,
		once:       i.Once,
		retryFunc:  i.RetryFunc,
		stopCh:     make(chan struct{}, 1),
		vaultGrace: i.VaultGrace,
	}, nil
}

func NewView ( i * NewViewInput ) ( * View , error ) { return & View { dependency : i . Dependency , clients : i . Clients , maxStale : i . MaxStale , once : i . Once , retryFunc : i . RetryFunc , stopCh : make ( chan struct { } , 1 ) , vaultGrace : i . VaultGrace , } , nil }

// NewView constructs a new view with the given inputs.

NewView constructs a new view with the given inputs .


func (v *View) Data() interface{} {
	v.dataLock.RLock()
	defer v.dataLock.RUnlock()
	return v.data
}

func ( v * View ) Data ( ) interface { } { v . dataLock . RLock ( ) defer v . dataLock . RUnlock ( ) return v . data }

// Data returns the most-recently-received data from Consul for this View.

Data returns the most - recently - received data from Consul for this View .


func (v *View) DataAndLastIndex() (interface{}, uint64) {
	v.dataLock.RLock()
	defer v.dataLock.RUnlock()
	return v.data, v.lastIndex
}

func ( v * View ) DataAndLastIndex ( ) ( interface { } , uint64 ) { v . dataLock . RLock ( ) defer v . dataLock . RUnlock ( ) return v . data , v . lastIndex }

// DataAndLastIndex returns the most-recently-received data from Consul for
// this view, along with the last index. This is atomic so you will get the
// index that goes with the data you are fetching.

DataAndLastIndex returns the most - recently - received data from Consul for this view along with the last index . This is atomic so you will get the index that goes with the data you are fetching .


func (v *View) poll(viewCh chan<- *View, errCh chan<- error) {
	var retries int

	for {
		doneCh := make(chan struct{}, 1)
		successCh := make(chan struct{}, 1)
		fetchErrCh := make(chan error, 1)
		go v.fetch(doneCh, successCh, fetchErrCh)

	WAIT:
		select {
		case <-doneCh:
			// Reset the retry to avoid exponentially incrementing retries when we
			// have some successful requests
			retries = 0

			log.Printf("[TRACE] (view) %s received data", v.dependency)
			select {
			case <-v.stopCh:
				return
			case viewCh <- v:
			}

			// If we are operating in once mode, do not loop - we received data at
			// least once which is the API promise here.
			if v.once {
				return
			}
		case <-successCh:
			// We successfully received a non-error response from the server. This
			// does not mean we have data (that's dataCh's job), but rather this
			// just resets the counter indicating we communicated successfully. For
			// example, Consul make have an outage, but when it returns, the view
			// is unchanged. We have to reset the counter retries, but not update the
			// actual template.
			log.Printf("[TRACE] (view) %s successful contact, resetting retries", v.dependency)
			retries = 0
			goto WAIT
		case err := <-fetchErrCh:
			if v.retryFunc != nil {
				retry, sleep := v.retryFunc(retries)
				if retry {
					log.Printf("[WARN] (view) %s (retry attempt %d after %q)",
						err, retries+1, sleep)
					select {
					case <-time.After(sleep):
						retries++
						continue
					case <-v.stopCh:
						return
					}
				}
			}

			log.Printf("[ERR] (view) %s (exceeded maximum retries)", err)

			// Push the error back up to the watcher
			select {
			case <-v.stopCh:
				return
			case errCh <- err:
				return
			}
		case <-v.stopCh:
			log.Printf("[TRACE] (view) %s stopping poll (received on view stopCh)", v.dependency)
			return
		}
	}
}

// poll queries the Consul instance for data using the fetch function, but also
// accounts for interrupts on the interrupt channel. This allows the poll
// function to be fired in a goroutine, but then halted even if the fetch
// function is in the middle of a blocking query.

poll queries the Consul instance for data using the fetch function but also accounts for interrupts on the interrupt channel . This allows the poll function to be fired in a goroutine but then halted even if the fetch function is in the middle of a blocking query .


func (v *View) fetch(doneCh, successCh chan<- struct{}, errCh chan<- error) {
	log.Printf("[TRACE] (view) %s starting fetch", v.dependency)

	var allowStale bool
	if v.maxStale != 0 {
		allowStale = true
	}

	for {
		// If the view was stopped, short-circuit this loop. This prevents a bug
		// where a view can get "lost" in the event Consul Template is reloaded.
		select {
		case <-v.stopCh:
			return
		default:
		}

		data, rm, err := v.dependency.Fetch(v.clients, &dep.QueryOptions{
			AllowStale: allowStale,
			WaitTime:   defaultWaitTime,
			WaitIndex:  v.lastIndex,
			VaultGrace: v.vaultGrace,
		})
		if err != nil {
			if err == dep.ErrStopped {
				log.Printf("[TRACE] (view) %s reported stop", v.dependency)
			} else {
				errCh <- err
			}
			return
		}

		if rm == nil {
			errCh <- fmt.Errorf("received nil response metadata - this is a bug " +
				"and should be reported")
			return
		}

		// If we got this far, we received data successfully. That data might not
		// trigger a data update (because we could continue below), but we need to
		// inform the poller to reset the retry count.
		log.Printf("[TRACE] (view) %s marking successful data response", v.dependency)
		select {
		case successCh <- struct{}{}:
		default:
		}

		if allowStale && rm.LastContact > v.maxStale {
			allowStale = false
			log.Printf("[TRACE] (view) %s stale data (last contact exceeded max_stale)", v.dependency)
			continue
		}

		if v.maxStale != 0 {
			allowStale = true
		}

		if rm.LastIndex == v.lastIndex {
			log.Printf("[TRACE] (view) %s no new data (index was the same)", v.dependency)
			continue
		}

		v.dataLock.Lock()
		if rm.LastIndex < v.lastIndex {
			log.Printf("[TRACE] (view) %s had a lower index, resetting", v.dependency)
			v.lastIndex = 0
			v.dataLock.Unlock()
			continue
		}
		v.lastIndex = rm.LastIndex

		if v.receivedData && reflect.DeepEqual(data, v.data) {
			log.Printf("[TRACE] (view) %s no new data (contents were the same)", v.dependency)
			v.dataLock.Unlock()
			continue
		}

		if data == nil && rm.Block {
			log.Printf("[TRACE] (view) %s asked for blocking query", v.dependency)
			v.dataLock.Unlock()
			continue
		}

		v.data = data
		v.receivedData = true
		v.dataLock.Unlock()

		close(doneCh)
		return
	}
}

// fetch queries the Consul instance for the attached dependency. This API
// promises that either data will be written to doneCh or an error will be
// written to errCh. It is designed to be run in a goroutine that selects the
// result of doneCh and errCh. It is assumed that only one instance of fetch
// is running per View and therefore no locking or mutexes are used.

fetch queries the Consul instance for the attached dependency . This API promises that either data will be written to doneCh or an error will be written to errCh . It is designed to be run in a goroutine that selects the result of doneCh and errCh . It is assumed that only one instance of fetch is running per View and therefore no locking or mutexes are used .


func NewCatalogNodeQuery(s string) (*CatalogNodeQuery, error) {
	if s != "" && !CatalogNodeQueryRe.MatchString(s) {
		return nil, fmt.Errorf("catalog.node: invalid format: %q", s)
	}

	m := regexpMatch(CatalogNodeQueryRe, s)
	return &CatalogNodeQuery{
		dc:     m["dc"],
		name:   m["name"],
		stopCh: make(chan struct{}, 1),
	}, nil
}

func NewCatalogNodeQuery ( s string ) ( * CatalogNodeQuery , error ) { if s != " " && ! CatalogNodeQueryRe . MatchString ( s ) { return nil , fmt . Errorf ( " " , s ) } m := regexpMatch ( CatalogNodeQueryRe , s ) return & CatalogNodeQuery { dc : m [ " " ] , name : m [ " " ] , stopCh : make ( chan struct { } , 1 ) , } , nil }

// NewCatalogNodeQuery parses the given string into a dependency. If the name is
// empty then the name of the local agent is used.

NewCatalogNodeQuery parses the given string into a dependency . If the name is empty then the name of the local agent is used .


func (d *CatalogNodeQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	select {
	case <-d.stopCh:
		return nil, nil, ErrStopped
	default:
	}

	opts = opts.Merge(&QueryOptions{
		Datacenter: d.dc,
	})

	// Grab the name
	name := d.name

	if name == "" {
		log.Printf("[TRACE] %s: getting local agent name", d)
		var err error
		name, err = clients.Consul().Agent().NodeName()
		if err != nil {
			return nil, nil, errors.Wrapf(err, d.String())
		}
	}

	log.Printf("[TRACE] %s: GET %s", d, &url.URL{
		Path:     "/v1/catalog/node/" + name,
		RawQuery: opts.String(),
	})
	node, qm, err := clients.Consul().Catalog().Node(name, opts.ToConsulOpts())
	if err != nil {
		return nil, nil, errors.Wrap(err, d.String())
	}

	log.Printf("[TRACE] %s: returned response", d)

	rm := &ResponseMetadata{
		LastIndex:   qm.LastIndex,
		LastContact: qm.LastContact,
	}

	if node == nil {
		log.Printf("[WARN] %s: no node exists with the name %q", d, name)
		var node CatalogNode
		return &node, rm, nil
	}

	services := make([]*CatalogNodeService, 0, len(node.Services))
	for _, v := range node.Services {
		services = append(services, &CatalogNodeService{
			ID:                v.ID,
			Service:           v.Service,
			Tags:              ServiceTags(deepCopyAndSortTags(v.Tags)),
			Meta:              v.Meta,
			Port:              v.Port,
			Address:           v.Address,
			EnableTagOverride: v.EnableTagOverride,
		})
	}
	sort.Stable(ByService(services))

	detail := &CatalogNode{
		Node: &Node{
			ID:              node.Node.ID,
			Node:            node.Node.Node,
			Address:         node.Node.Address,
			Datacenter:      node.Node.Datacenter,
			TaggedAddresses: node.Node.TaggedAddresses,
			Meta:            node.Node.Meta,
		},
		Services: services,
	}

	return detail, rm, nil
}

func
(
d
*
CatalogNodeQuery
)
Fetch
(
clients
*
ClientSet
,
opts
*
QueryOptions
)
(
interface
{
}
,
*
ResponseMetadata
,
error
)
{
select
{
case
<-
d
.
stopCh
:
return
,
,
ErrStopped
default
:
}
opts
=
opts
.
Merge
(
&
QueryOptions
{
Datacenter
:
d
.
dc
,
}
)
// Grab the name
name
:=
d
.
name
if
name
==
"
"
{
log
.
Printf
(
"
"
,
d
)
var
err
error
name
,
err
=
clients
.
Consul
(
)
.
Agent
(
)
.
NodeName
(
)
if
err
!=
{
return
,
,
errors
.
Wrapf
(
err
,
d
.
String
(
)
)
}
}
log
.
Printf
(
"
"
,
d
,
&
url
.
URL
{
Path
:
"
"
+
name
,
RawQuery
:
opts
.
String
(
)
,
}
)
node
,
qm
,
err
:=
clients
.
Consul
(
)
.
Catalog
(
)
.
Node
(
name
,
opts
.
ToConsulOpts
(
)
)
if
err
!=
{
return
,
,
errors
.
Wrap
(
err
,
d
.
String
(
)
)
}
log
.
Printf
(
"
"
,
d
)
rm
:=
&
ResponseMetadata
{
LastIndex
:
qm
.
LastIndex
,
LastContact
:
qm
.
LastContact
,
}
if
node
==
{
log
.
Printf
(
"
"
,
d
,
name
)
var
node
CatalogNode
return
&
node
,
rm
,
}
services
:=
make
(
[
]
*
CatalogNodeService
,
0
,
len
(
node
.
Services
)
)
for
_
,
v
:=
range
node
.
Services
{
services
=
append
(
services
,
&
CatalogNodeService
{
ID
:
v
.
ID
,
Service
:
v
.
Service
,
Tags
:
ServiceTags
(
deepCopyAndSortTags
(
v
.
Tags
)
)
,
Meta
:
v
.
Meta
,
Port
:
v
.
Port
,
Address
:
v
.
Address
,
EnableTagOverride
:
v
.
EnableTagOverride
,
}
)
}
sort
.
Stable
(
ByService
(
services
)
)
detail
:=
&
CatalogNode
{
Node
:
&
Node
{
ID
:
node
.
Node
.
ID
,
Node
:
node
.
Node
.
Node
,
Address
:
node
.
Node
.
Address
,
Datacenter
:
node
.
Node
.
Datacenter
,
TaggedAddresses
:
node
.
Node
.
TaggedAddresses
,
Meta
:
node
.
Node
.
Meta
,
}
,
Services
:
services
,
}
return
detail
,
rm
,
}

// Fetch queries the Consul API defined by the given client and returns a
// of CatalogNode object.

Fetch queries the Consul API defined by the given client and returns a of CatalogNode object .


func (c *AuthConfig) String() string {
	if !BoolVal(c.Enabled) {
		return ""
	}

	if c.Password != nil {
		return fmt.Sprintf("%s:%s", StringVal(c.Username), StringVal(c.Password))
	}

	return StringVal(c.Username)
}

func ( c * AuthConfig ) String ( ) string { if ! BoolVal ( c . Enabled ) { return " " } if c . Password != nil { return fmt . Sprintf ( " " , StringVal ( c . Username ) , StringVal ( c . Password ) ) } return StringVal ( c . Username ) }

// String is the string representation of this authentication. If authentication
// is not enabled, this returns the empty string. The username and password will
// be separated by a colon.

String is the string representation of this authentication . If authentication is not enabled this returns the empty string . The username and password will be separated by a colon .


func NewVaultListQuery(s string) (*VaultListQuery, error) {
	s = strings.TrimSpace(s)
	s = strings.Trim(s, "/")
	if s == "" {
		return nil, fmt.Errorf("vault.list: invalid format: %q", s)
	}

	return &VaultListQuery{
		stopCh: make(chan struct{}, 1),
		path:   s,
	}, nil
}

func NewVaultListQuery ( s string ) ( * VaultListQuery , error ) { s = strings . TrimSpace ( s ) s = strings . Trim ( s , " " ) if s == " " { return nil , fmt . Errorf ( " " , s ) } return & VaultListQuery { stopCh : make ( chan struct { } , 1 ) , path : s , } , nil }

// NewVaultListQuery creates a new datacenter dependency.

NewVaultListQuery creates a new datacenter dependency .


func (b *Brain) Remember(d dep.Dependency, data interface{}) {
	b.Lock()
	defer b.Unlock()

	b.data[d.String()] = data
	b.receivedData[d.String()] = struct{}{}
}

func ( b * Brain ) Remember ( d dep . Dependency , data interface { } ) { b . Lock ( ) defer b . Unlock ( ) b . data [ d . String ( ) ] = data b . receivedData [ d . String ( ) ] = struct { } { } }

// Remember accepts a dependency and the data to store associated with that
// dep. This function converts the given data to a proper type and stores
// it interally.

Remember accepts a dependency and the data to store associated with that dep . This function converts the given data to a proper type and stores it interally .


func (b *Brain) Recall(d dep.Dependency) (interface{}, bool) {
	b.RLock()
	defer b.RUnlock()

	// If we have not received data for this dependency, return now.
	if _, ok := b.receivedData[d.String()]; !ok {
		return nil, false
	}

	return b.data[d.String()], true
}

// Recall gets the current value for the given dependency in the Brain.

Recall gets the current value for the given dependency in the Brain .


func (b *Brain) ForceSet(hashCode string, data interface{}) {
	b.Lock()
	defer b.Unlock()

	b.data[hashCode] = data
	b.receivedData[hashCode] = struct{}{}
}

func ( b * Brain ) ForceSet ( hashCode string , data interface { } ) { b . Lock ( ) defer b . Unlock ( ) b . data [ hashCode ] = data b . receivedData [ hashCode ] = struct { } { } }

// ForceSet is used to force set the value of a dependency
// for a given hash code

ForceSet is used to force set the value of a dependency for a given hash code


func (b *Brain) Forget(d dep.Dependency) {
	b.Lock()
	defer b.Unlock()

	delete(b.data, d.String())
	delete(b.receivedData, d.String())
}

func ( b * Brain ) Forget ( d dep . Dependency ) { b . Lock ( ) defer b . Unlock ( ) delete ( b . data , d . String ( ) ) delete ( b . receivedData , d . String ( ) ) }

// Forget accepts a dependency and removes all associated data with this
// dependency. It also resets the "receivedData" internal map.

Forget accepts a dependency and removes all associated data with this dependency . It also resets the receivedData internal map .


func NewCatalogDatacentersQuery(ignoreFailing bool) (*CatalogDatacentersQuery, error) {
	return &CatalogDatacentersQuery{
		ignoreFailing: ignoreFailing,
		stopCh:        make(chan struct{}, 1),
	}, nil
}

func NewCatalogDatacentersQuery ( ignoreFailing bool ) ( * CatalogDatacentersQuery , error ) { return & CatalogDatacentersQuery { ignoreFailing : ignoreFailing , stopCh : make ( chan struct { } , 1 ) , } , nil }

// NewCatalogDatacentersQuery creates a new datacenter dependency.

NewCatalogDatacentersQuery creates a new datacenter dependency .


func (d *CatalogDatacentersQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	opts = opts.Merge(&QueryOptions{})

	log.Printf("[TRACE] %s: GET %s", d, &url.URL{
		Path:     "/v1/catalog/datacenters",
		RawQuery: opts.String(),
	})

	// This is pretty ghetto, but the datacenters endpoint does not support
	// blocking queries, so we are going to "fake it until we make it". When we
	// first query, the LastIndex will be "0", meaning we should immediately
	// return data, but future calls will include a LastIndex. If we have a
	// LastIndex in the query metadata, sleep for 15 seconds before asking Consul
	// again.
	//
	// This is probably okay given the frequency in which datacenters actually
	// change, but is technically not edge-triggering.
	if opts.WaitIndex != 0 {
		log.Printf("[TRACE] %s: long polling for %s", d, CatalogDatacentersQuerySleepTime)

		select {
		case <-d.stopCh:
			return nil, nil, ErrStopped
		case <-time.After(CatalogDatacentersQuerySleepTime):
		}
	}

	result, err := clients.Consul().Catalog().Datacenters()
	if err != nil {
		return nil, nil, errors.Wrapf(err, d.String())
	}

	// If the user opted in for skipping "down" datacenters, figure out which
	// datacenters are down.
	if d.ignoreFailing {
		dcs := make([]string, 0, len(result))
		for _, dc := range result {
			if _, _, err := clients.Consul().Catalog().Services(&api.QueryOptions{
				Datacenter:        dc,
				AllowStale:        false,
				RequireConsistent: true,
			}); err == nil {
				dcs = append(dcs, dc)
			}
		}
		result = dcs
	}

	log.Printf("[TRACE] %s: returned %d results", d, len(result))

	sort.Strings(result)

	return respWithMetadata(result)
}

// Fetch queries the Consul API defined by the given client and returns a slice
// of strings representing the datacenters

Fetch queries the Consul API defined by the given client and returns a slice of strings representing the datacenters


func NewCatalogNodesQuery(s string) (*CatalogNodesQuery, error) {
	if !CatalogNodesQueryRe.MatchString(s) {
		return nil, fmt.Errorf("catalog.nodes: invalid format: %q", s)
	}

	m := regexpMatch(CatalogNodesQueryRe, s)
	return &CatalogNodesQuery{
		dc:     m["dc"],
		near:   m["near"],
		stopCh: make(chan struct{}, 1),
	}, nil
}

func NewCatalogNodesQuery ( s string ) ( * CatalogNodesQuery , error ) { if ! CatalogNodesQueryRe . MatchString ( s ) { return nil , fmt . Errorf ( " " , s ) } m := regexpMatch ( CatalogNodesQueryRe , s ) return & CatalogNodesQuery { dc : m [ " " ] , near : m [ " " ] , stopCh : make ( chan struct { } , 1 ) , } , nil }

// NewCatalogNodesQuery parses the given string into a dependency. If the name is
// empty then the name of the local agent is used.

NewCatalogNodesQuery parses the given string into a dependency . If the name is empty then the name of the local agent is used .


func (d *CatalogNodesQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	select {
	case <-d.stopCh:
		return nil, nil, ErrStopped
	default:
	}

	opts = opts.Merge(&QueryOptions{
		Datacenter: d.dc,
		Near:       d.near,
	})

	log.Printf("[TRACE] %s: GET %s", d, &url.URL{
		Path:     "/v1/catalog/nodes",
		RawQuery: opts.String(),
	})
	n, qm, err := clients.Consul().Catalog().Nodes(opts.ToConsulOpts())
	if err != nil {
		return nil, nil, errors.Wrap(err, d.String())
	}

	log.Printf("[TRACE] %s: returned %d results", d, len(n))

	nodes := make([]*Node, 0, len(n))
	for _, node := range n {
		nodes = append(nodes, &Node{
			ID:              node.ID,
			Node:            node.Node,
			Address:         node.Address,
			Datacenter:      node.Datacenter,
			TaggedAddresses: node.TaggedAddresses,
			Meta:            node.Meta,
		})
	}

	// Sort unless the user explicitly asked for nearness
	if d.near == "" {
		sort.Stable(ByNode(nodes))
	}

	rm := &ResponseMetadata{
		LastIndex:   qm.LastIndex,
		LastContact: qm.LastContact,
	}

	return nodes, rm, nil
}

// Fetch queries the Consul API defined by the given client and returns a slice
// of Node objects

Fetch queries the Consul API defined by the given client and returns a slice of Node objects


func Parse(s string) (os.Signal, error) {
	sig, ok := SignalLookup[strings.ToUpper(s)]
	if !ok {
		return nil, fmt.Errorf("invalid signal %q - valid signals are %q",
			s, ValidSignals)
	}
	return sig, nil
}

func Parse ( s string ) ( os . Signal , error ) { sig , ok := SignalLookup [ strings . ToUpper ( s ) ] if ! ok { return nil , fmt . Errorf ( " " , s , ValidSignals ) } return sig , nil }

// Parse parses the given string as a signal. If the signal is not found,
// an error is returned.

Parse parses the given string as a signal . If the signal is not found an error is returned .


func DefaultVaultConfig() *VaultConfig {
	v := &VaultConfig{
		Retry:     DefaultRetryConfig(),
		SSL:       DefaultSSLConfig(),
		Transport: DefaultTransportConfig(),
	}

	// Force SSL when communicating with Vault.
	v.SSL.Enabled = Bool(true)

	return v
}

// DefaultVaultConfig returns a configuration that is populated with the
// default values.

DefaultVaultConfig returns a configuration that is populated with the default values .


func NewTemplate(i *NewTemplateInput) (*Template, error) {
	if i == nil {
		i = &NewTemplateInput{}
	}

	// Validate that we are either given the path or the explicit contents
	if i.Source != "" && i.Contents != "" {
		return nil, ErrTemplateContentsAndSource
	} else if i.Source == "" && i.Contents == "" {
		return nil, ErrTemplateMissingContentsAndSource
	}

	var t Template
	t.source = i.Source
	t.contents = i.Contents
	t.leftDelim = i.LeftDelim
	t.rightDelim = i.RightDelim
	t.errMissingKey = i.ErrMissingKey

	if i.Source != "" {
		contents, err := ioutil.ReadFile(i.Source)
		if err != nil {
			return nil, errors.Wrap(err, "failed to read template")
		}
		t.contents = string(contents)
	}

	// Compute the MD5, encode as hex
	hash := md5.Sum([]byte(t.contents))
	t.hexMD5 = hex.EncodeToString(hash[:])

	return &t, nil
}

// NewTemplate creates and parses a new Consul Template template at the given
// path. If the template does not exist, an error is returned. During
// initialization, the template is read and is parsed for dependencies. Any
// errors that occur are returned.

NewTemplate creates and parses a new Consul Template template at the given path . If the template does not exist an error is returned . During initialization the template is read and is parsed for dependencies . Any errors that occur are returned .


func (t *Template) Execute(i *ExecuteInput) (*ExecuteResult, error) {
	if i == nil {
		i = &ExecuteInput{}
	}

	var used, missing dep.Set

	tmpl := template.New("")
	tmpl.Delims(t.leftDelim, t.rightDelim)
	tmpl.Funcs(funcMap(&funcMapInput{
		t:       tmpl,
		brain:   i.Brain,
		env:     i.Env,
		used:    &used,
		missing: &missing,
	}))

	if t.errMissingKey {
		tmpl.Option("missingkey=error")
	} else {
		tmpl.Option("missingkey=zero")
	}

	tmpl, err := tmpl.Parse(t.contents)
	if err != nil {
		return nil, errors.Wrap(err, "parse")
	}

	// Execute the template into the writer
	var b bytes.Buffer
	if err := tmpl.Execute(&b, nil); err != nil {
		return nil, errors.Wrap(err, "execute")
	}

	return &ExecuteResult{
		Used:    &used,
		Missing: &missing,
		Output:  b.Bytes(),
	}, nil
}

func
(
t
*
Template
)
Execute
(
i
*
ExecuteInput
)
(
*
ExecuteResult
,
error
)
{
if
i
==
{
i
=
&
ExecuteInput
{
}
}
var
used
,
missing
dep
.
Set
tmpl
:=
template
.
New
(
"
"
)
tmpl
.
Delims
(
t
.
leftDelim
,
t
.
rightDelim
)
tmpl
.
Funcs
(
funcMap
(
&
funcMapInput
{
t
:
tmpl
,
brain
:
i
.
Brain
,
env
:
i
.
Env
,
used
:
&
used
,
missing
:
&
missing
,
}
)
)
if
t
.
errMissingKey
{
tmpl
.
Option
(
"
"
)
}
else
{
tmpl
.
Option
(
"
"
)
}
tmpl
,
err
:=
tmpl
.
Parse
(
t
.
contents
)
if
err
!=
{
return
,
errors
.
Wrap
(
err
,
"
"
)
}
// Execute the template into the writer
var
b
bytes
.
Buffer
if
err
:=
tmpl
.
Execute
(
&
b
,
)
;
err
!=
{
return
,
errors
.
Wrap
(
err
,
"
"
)
}
return
&
ExecuteResult
{
Used
:
&
used
,
Missing
:
&
missing
,
Output
:
b
.
Bytes
(
)
,
}
,
}

// Execute evaluates this template in the provided context.

Execute evaluates this template in the provided context .


func funcMap(i *funcMapInput) template.FuncMap {
	var scratch Scratch

	return template.FuncMap{
		// API functions
		"datacenters":  datacentersFunc(i.brain, i.used, i.missing),
		"file":         fileFunc(i.brain, i.used, i.missing),
		"key":          keyFunc(i.brain, i.used, i.missing),
		"keyExists":    keyExistsFunc(i.brain, i.used, i.missing),
		"keyOrDefault": keyWithDefaultFunc(i.brain, i.used, i.missing),
		"ls":           lsFunc(i.brain, i.used, i.missing),
		"node":         nodeFunc(i.brain, i.used, i.missing),
		"nodes":        nodesFunc(i.brain, i.used, i.missing),
		"secret":       secretFunc(i.brain, i.used, i.missing),
		"secrets":      secretsFunc(i.brain, i.used, i.missing),
		"service":      serviceFunc(i.brain, i.used, i.missing),
		"services":     servicesFunc(i.brain, i.used, i.missing),
		"tree":         treeFunc(i.brain, i.used, i.missing),

		// Scratch
		"scratch": func() *Scratch { return &scratch },

		// Helper functions
		"base64Decode":    base64Decode,
		"base64Encode":    base64Encode,
		"base64URLDecode": base64URLDecode,
		"base64URLEncode": base64URLEncode,
		"byKey":           byKey,
		"byTag":           byTag,
		"contains":        contains,
		"containsAll":     containsSomeFunc(true, true),
		"containsAny":     containsSomeFunc(false, false),
		"containsNone":    containsSomeFunc(true, false),
		"containsNotAll":  containsSomeFunc(false, true),
		"env":             envFunc(i.env),
		"executeTemplate": executeTemplateFunc(i.t),
		"explode":         explode,
		"in":              in,
		"indent":          indent,
		"loop":            loop,
		"join":            join,
		"trimSpace":       trimSpace,
		"parseBool":       parseBool,
		"parseFloat":      parseFloat,
		"parseInt":        parseInt,
		"parseJSON":       parseJSON,
		"parseUint":       parseUint,
		"plugin":          plugin,
		"regexReplaceAll": regexReplaceAll,
		"regexMatch":      regexMatch,
		"replaceAll":      replaceAll,
		"timestamp":       timestamp,
		"toLower":         toLower,
		"toJSON":          toJSON,
		"toJSONPretty":    toJSONPretty,
		"toTitle":         toTitle,
		"toTOML":          toTOML,
		"toUpper":         toUpper,
		"toYAML":          toYAML,
		"split":           split,

		// Math functions
		"add":      add,
		"subtract": subtract,
		"multiply": multiply,
		"divide":   divide,
		"modulo":   modulo,
	}
}

func
funcMap
(
i
*
funcMapInput
)
template
.
FuncMap
{
var
scratch
Scratch
return
template
.
FuncMap
{
// API functions
"
"
:
datacentersFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
fileFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
keyFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
keyExistsFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
keyWithDefaultFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
lsFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
nodeFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
nodesFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
secretFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
secretsFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
serviceFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
servicesFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
"
"
:
treeFunc
(
i
.
brain
,
i
.
used
,
i
.
missing
)
,
// Scratch
"
"
:
func
(
)
*
Scratch
{
return
&
scratch
}
,
// Helper functions
"
"
:
base64Decode
,
"
"
:
base64Encode
,
"
"
:
base64URLDecode
,
"
"
:
base64URLEncode
,
"
"
:
byKey
,
"
"
:
byTag
,
"
"
:
contains
,
"
"
:
containsSomeFunc
(
true
,
true
)
,
"
"
:
containsSomeFunc
(
false
,
false
)
,
"
"
:
containsSomeFunc
(
true
,
false
)
,
"
"
:
containsSomeFunc
(
false
,
true
)
,
"
"
:
envFunc
(
i
.
env
)
,
"
"
:
executeTemplateFunc
(
i
.
t
)
,
"
"
:
explode
,
"
"
:
in
,
"
"
:
indent
,
"
"
:
loop
,
"
"
:
join
,
"
"
:
trimSpace
,
"
"
:
parseBool
,
"
"
:
parseFloat
,
"
"
:
parseInt
,
"
"
:
parseJSON
,
"
"
:
parseUint
,
"
"
:
plugin
,
"
"
:
regexReplaceAll
,
"
"
:
regexMatch
,
"
"
:
replaceAll
,
"
"
:
timestamp
,
"
"
:
toLower
,
"
"
:
toJSON
,
"
"
:
toJSONPretty
,
"
"
:
toTitle
,
"
"
:
toTOML
,
"
"
:
toUpper
,
"
"
:
toYAML
,
"
"
:
split
,
// Math functions
"
"
:
add
,
"
"
:
subtract
,
"
"
:
multiply
,
"
"
:
divide
,
"
"
:
modulo
,
}
}

// funcMap is the map of template functions to their respective functions.

funcMap is the map of template functions to their respective functions .


func StringToFileModeFunc() mapstructure.DecodeHookFunc {
	return func(
		f reflect.Type,
		t reflect.Type,
		data interface{}) (interface{}, error) {
		if f.Kind() != reflect.String {
			return data, nil
		}
		if t != reflect.TypeOf(os.FileMode(0)) {
			return data, nil
		}

		// Convert it by parsing
		v, err := strconv.ParseUint(data.(string), 8, 12)
		if err != nil {
			return data, err
		}
		return os.FileMode(v), nil
	}
}

func
StringToFileModeFunc
(
)
mapstructure
.
DecodeHookFunc
{
return
func
(
f
reflect
.
Type
,
t
reflect
.
Type
,
data
interface
{
}
)
(
interface
{
}
,
error
)
{
if
f
.
Kind
(
)
!=
reflect
.
String
{
return
data
,
}
if
t
!=
reflect
.
TypeOf
(
os
.
FileMode
(
0
)
)
{
return
data
,
}
// Convert it by parsing
v
,
err
:=
strconv
.
ParseUint
(
data
.
(
string
)
,
8
,
12
)
if
err
!=
{
return
data
,
err
}
return
os
.
FileMode
(
v
)
,
}
}

// StringToFileModeFunc returns a function that converts strings to os.FileMode
// value. This is designed to be used with mapstructure for parsing out a
// filemode value.

StringToFileModeFunc returns a function that converts strings to os . FileMode value . This is designed to be used with mapstructure for parsing out a filemode value .


func StringToWaitDurationHookFunc() mapstructure.DecodeHookFunc {
	return func(
		f reflect.Type,
		t reflect.Type,
		data interface{}) (interface{}, error) {
		if f.Kind() != reflect.String {
			return data, nil
		}
		if t != reflect.TypeOf(WaitConfig{}) {
			return data, nil
		}

		// Convert it by parsing
		return ParseWaitConfig(data.(string))
	}
}

func
StringToWaitDurationHookFunc
(
)
mapstructure
.
DecodeHookFunc
{
return
func
(
f
reflect
.
Type
,
t
reflect
.
Type
,
data
interface
{
}
)
(
interface
{
}
,
error
)
{
if
f
.
Kind
(
)
!=
reflect
.
String
{
return
data
,
}
if
t
!=
reflect
.
TypeOf
(
WaitConfig
{
}
)
{
return
data
,
}
// Convert it by parsing
return
ParseWaitConfig
(
data
.
(
string
)
)
}
}

// StringToWaitDurationHookFunc returns a function that converts strings to wait
// value. This is designed to be used with mapstructure for parsing out a wait
// value.

StringToWaitDurationHookFunc returns a function that converts strings to wait value . This is designed to be used with mapstructure for parsing out a wait value .


func ConsulStringToStructFunc() mapstructure.DecodeHookFunc {
	return func(
		f reflect.Type,
		t reflect.Type,
		data interface{}) (interface{}, error) {
		if t == reflect.TypeOf(ConsulConfig{}) && f.Kind() == reflect.String {
			log.Println("[WARN] consul now accepts a stanza instead of a string. " +
				"Update your configuration files and change consul = \"\" to " +
				"consul { } instead.")
			return &ConsulConfig{
				Address: String(data.(string)),
			}, nil
		}

		return data, nil
	}
}

func ConsulStringToStructFunc ( ) mapstructure . DecodeHookFunc { return func ( f reflect . Type , t reflect . Type , data interface { } ) ( interface { } , error ) { if t == reflect . TypeOf ( ConsulConfig { } ) && f . Kind ( ) == reflect . String { log . Println ( " " + " \" \" " + " " ) return & ConsulConfig { Address : String ( data . ( string ) ) , } , nil } return data , nil } }

// ConsulStringToStructFunc checks if the value set for the key should actually
// be a struct and sets the appropriate value in the struct. This is for
// backwards-compatability with older versions of Consul Template.

ConsulStringToStructFunc checks if the value set for the key should actually be a struct and sets the appropriate value in the struct . This is for backwards - compatability with older versions of Consul Template .


func (s *Scratch) Key(k string) bool {
	s.RLock()
	defer s.RUnlock()
	_, ok := s.values[k]
	return ok
}

func ( s * Scratch ) Key ( k string ) bool { s . RLock ( ) defer s . RUnlock ( ) _ , ok := s . values [ k ] return ok }

// Key returns a boolean indicating whether the given key exists in the map.

Key returns a boolean indicating whether the given key exists in the map .


func (s *Scratch) Get(k string) interface{} {
	s.RLock()
	defer s.RUnlock()
	return s.values[k]
}

func ( s * Scratch ) Get ( k string ) interface { } { s . RLock ( ) defer s . RUnlock ( ) return s . values [ k ] }

// Get returns a value previously set by Add or Set


func (s *Scratch) Set(k string, v interface{}) string {
	s.init()

	s.Lock()
	defer s.Unlock()
	s.values[k] = v
	return ""
}

func ( s * Scratch ) Set ( k string , v interface { } ) string { s . init ( ) s . Lock ( ) defer s . Unlock ( ) s . values [ k ] = v return " " }

// Set stores the value v at the key k. It will overwrite an existing value
// if present.

Set stores the value v at the key k . It will overwrite an existing value if present .


func (s *Scratch) SetX(k string, v interface{}) string {
	s.init()

	s.Lock()
	defer s.Unlock()
	if _, ok := s.values[k]; !ok {
		s.values[k] = v
	}
	return ""
}

func ( s * Scratch ) SetX ( k string , v interface { } ) string { s . init ( ) s . Lock ( ) defer s . Unlock ( ) if _ , ok := s . values [ k ] ; ! ok { s . values [ k ] = v } return " " }

// SetX behaves the same as Set, except it will not overwrite existing keys if
// already present.

SetX behaves the same as Set except it will not overwrite existing keys if already present .


func (s *Scratch) MapSet(k, mk string, v interface{}) (string, error) {
	s.init()

	s.Lock()
	defer s.Unlock()
	return s.mapSet(k, mk, v, true)
}

func ( s * Scratch ) MapSet ( k , mk string , v interface { } ) ( string , error ) { s . init ( ) s . Lock ( ) defer s . Unlock ( ) return s . mapSet ( k , mk , v , true ) }

// MapSet stores the value v into a key mk in the map named k.

MapSet stores the value v into a key mk in the map named k .


func (s *Scratch) MapSetX(k, mk string, v interface{}) (string, error) {
	s.init()

	s.Lock()
	defer s.Unlock()
	return s.mapSet(k, mk, v, false)
}

func ( s * Scratch ) MapSetX ( k , mk string , v interface { } ) ( string , error ) { s . init ( ) s . Lock ( ) defer s . Unlock ( ) return s . mapSet ( k , mk , v , false ) }

// MapSetX behaves the same as MapSet, except it will not overwrite the map
// key if it already exists.

MapSetX behaves the same as MapSet except it will not overwrite the map key if it already exists .


func (s *Scratch) mapSet(k, mk string, v interface{}, o bool) (string, error) {
	if _, ok := s.values[k]; !ok {
		s.values[k] = make(map[string]interface{})
	}

	typed, ok := s.values[k].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("%q is not a map", k)
	}

	if _, ok := typed[mk]; o || !ok {
		typed[mk] = v
	}
	return "", nil
}

func ( s * Scratch ) mapSet ( k , mk string , v interface { } , o bool ) ( string , error ) { if _ , ok := s . values [ k ] ; ! ok { s . values [ k ] = make ( map [ string ] interface { } ) } typed , ok := s . values [ k ] . ( map [ string ] interface { } ) if ! ok { return " " , fmt . Errorf ( " " , k ) } if _ , ok := typed [ mk ] ; o || ! ok { typed [ mk ] = v } return " " , nil }

// mapSet is sets the value in the map, overwriting if o is true. This function
// does not perform locking; callers should lock before invoking.

mapSet is sets the value in the map overwriting if o is true . This function does not perform locking ; callers should lock before invoking .