<commit_before>/*
 * This file is a part of linuxdeploy - tool for
 * creating standalone applications for Linux
 *
 * Copyright (C) 2017 Taras Kushnir <kushnirTV@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the MIT License.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

package main

import (
  "log"
  "os"
  "strings"
  "sync"
  "path/filepath"
)

const (
  // constants for parameter of deployRecursively() method
  DEPLOY_EVERYTHING = false
  DEPLOY_LIBRARIES = true
  LDD_DEPENDENCY = true
  ORDINARY_FILE = false
)

type DeployRequest struct {
  sourcePath string // relative or absolute path of file to process
  sourceRoot string // if empty then sourcePath is absolute path
  targetPath string // target *relative* path
  isLddDependency bool // if true, check ldd dependencies
}

func (dp *DeployRequest) FullPath() string {
  if len(dp.sourceRoot) == 0 {
    return dp.sourcePath
  } else {
    return filepath.Join(dp.sourceRoot, dp.sourcePath)
  }
}

func (dp *DeployRequest) Basename() string {
  return filepath.Base(dp.sourcePath)
}

func (dp *DeployRequest) SourceDir() string {
  return filepath.Dir(dp.sourcePath)
}

type AppDeployer struct {
  waitGroup sync.WaitGroup
  processedLibs map[string]bool

  libsChannel chan *DeployRequest
  copyChannel chan *DeployRequest
  stripChannel chan string
  rpathChannel chan string
  qtChannel chan *DeployRequest

  qtDeployer *QtDeployer
  additionalLibPaths []string
  destinationPath string
  targetExePath string
}

func (ad *AppDeployer) DeployApp() {
  if err := ad.qtDeployer.queryQtEnv(); err != nil {
    log.Println(err)
  }

  ad.waitGroup.Add(1)
  go ad.processMainExe()

  go ad.processCopyRequests()
  go ad.processRunPathChangeRequests()
  go ad.processQtLibs()

  log.Printf("Waiting for processing to finish")
  ad.waitGroup.Wait()
  log.Printf("Processing has finished")

  close(ad.libsChannel)
  close(ad.copyChannel)
  close(ad.qtChannel)
  close(ad.rpathChannel)
}

func (ad *AppDeployer) deployLibrary(sourceRoot, sourcePath, targetPath string) {
  ad.waitGroup.Add(1)
  go func() {
    ad.libsChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: sourcePath,
      targetPath: targetPath,
      isLddDependency: true,
    }
  }()
}

func (ad *AppDeployer) copyFile(sourceRoot, sourcePath, targetPath string, isLddDependency bool) {
  ad.waitGroup.Add(1)
  go func() {
    ad.copyChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: sourcePath,
      targetPath: targetPath,
      isLddDependency: isLddDependency,
    }
  }()
}

func (ad *AppDeployer) accountLibrary(libpath string) {
  log.Printf("Processed library %v", libpath)
  ad.processedLibs[libpath] = true
}

func (ad *AppDeployer) isLibraryDeployed(libpath string) bool {
  _, ok := ad.processedLibs[libpath]
  return ok
}

func (ad *AppDeployer) processMainExe() {
  dependencies, err := ad.findLddDependencies(ad.targetExePath)
  if err != nil { log.Fatal(err) }

  ad.accountLibrary(ad.targetExePath)
  ad.copyFile("", ad.targetExePath, ".", LDD_DEPENDENCY)

  for _, dependPath := range dependencies {
    if !ad.isLibraryDeployed(dependPath) {
      ad.deployLibrary("", dependPath, "lib")
    } else {
      log.Printf("Dependency seems to be processed: %v", dependPath)
    }
  }

  go ad.processLibs()

  ad.waitGroup.Done()
}

func (ad *AppDeployer) processCopyRequests() {
  for copyRequest := range ad.copyChannel {
    ad.processCopyRequest(copyRequest)
    ad.waitGroup.Done()
  }
}

func (ad *AppDeployer) processCopyRequest(copyRequest *DeployRequest) {
  var destinationPath, destinationPrefix string

  if len(copyRequest.sourceRoot) == 0 {
    // absolute path
    destinationPrefix = copyRequest.targetPath
  } else {
    destinationPrefix = filepath.Join(copyRequest.targetPath, copyRequest.SourceDir())
  }

  sourcePath := copyRequest.FullPath()
  destinationPath = filepath.Join(ad.destinationPath, destinationPrefix, filepath.Base(copyRequest.sourcePath))

  ensureDirExists(destinationPath)

  log.Printf("Copying %v to %v", sourcePath, destinationPath)
  err := copyFile(sourcePath, destinationPath)

  if err == nil && copyRequest.isLddDependency {
    ad.waitGroup.Add(1)
    go func(qtRequest *DeployRequest) {
      ad.qtChannel <- qtRequest
    }(copyRequest)

    ad.waitGroup.Add(1)
    go func(fullpath string) {
      ad.rpathChannel <- fullpath
    }(destinationPath)
  } else {
    log.Println(err)
  }

  // TODO: submit to strip/patchelf/etc. if copyRequest.isLddDependency
}

// copies one file
func (ad *AppDeployer) copyOnce(sourceRoot, sourcePath, targetPath string) error {
  path := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Copying once %v into %v", path, targetPath)
  relativePath, err := filepath.Rel(sourceRoot, path)
  if err != nil {
    log.Println(err)
  }

  ad.waitGroup.Add(1)
  go func() {
    ad.copyChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: relativePath,
      targetPath: targetPath,
      isLddDependency: false,
    }
  }()

  return err
}

// copies everything without inspection
func (ad *AppDeployer) copyRecursively(sourceRoot, sourcePath, targetPath string) error {
  rootpath := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Copying recursively %v into %v", rootpath, targetPath)

  err := filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    relativePath, err := filepath.Rel(sourceRoot, path)
    if err != nil {
      log.Println(err)
    }

    ad.copyFile(sourceRoot, relativePath, targetPath, ORDINARY_FILE)

    return nil
  })

  return err
}

// inspects libraries for dependencies and copies other files
func (ad *AppDeployer) deployRecursively(sourceRoot, sourcePath, targetPath string, onlyLibraries bool) error {
  rootpath := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Deploying recursively %v in %v", sourceRoot, sourcePath)

  err := filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    basename := filepath.Base(path)
    isLibrary := strings.Contains(basename, ".so")

    if !isLibrary && onlyLibraries {
      return nil
    }

    relativePath, err := filepath.Rel(sourceRoot, path)
    if err != nil {
      log.Println(err)
    }

    if isLibrary {
      ad.deployLibrary(sourceRoot, relativePath, targetPath)
    } else {
      ad.copyFile(sourceRoot, relativePath, targetPath, ORDINARY_FILE)
    }

    return nil
  })

  return err
}
<commit_msg>Cosmetic improvements<commit_after>/*
 * This file is a part of linuxdeploy - tool for
 * creating standalone applications for Linux
 *
 * Copyright (C) 2017 Taras Kushnir <kushnirTV@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the MIT License.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

package main

import (
  "log"
  "os"
  "strings"
  "sync"
  "path/filepath"
)

const (
  // constants for parameter of deployRecursively() method
  DEPLOY_EVERYTHING = false
  DEPLOY_LIBRARIES = true
  LDD_DEPENDENCY = true
  ORDINARY_FILE = false
)

type DeployRequest struct {
  sourcePath string // relative or absolute path of file to process
  sourceRoot string // if empty then sourcePath is absolute path
  targetPath string // target *relative* path
  isLddDependency bool // if true, check ldd dependencies
}

func (dp *DeployRequest) FullPath() string {
  if len(dp.sourceRoot) == 0 {
    return dp.sourcePath
  } else {
    return filepath.Join(dp.sourceRoot, dp.sourcePath)
  }
}

func (dp *DeployRequest) Basename() string {
  return filepath.Base(dp.sourcePath)
}

func (dp *DeployRequest) SourceDir() string {
  return filepath.Dir(dp.sourcePath)
}

type AppDeployer struct {
  waitGroup sync.WaitGroup
  processedLibs map[string]bool

  libsChannel chan *DeployRequest
  copyChannel chan *DeployRequest
  stripChannel chan string
  rpathChannel chan string
  qtChannel chan *DeployRequest

  qtDeployer *QtDeployer
  additionalLibPaths []string
  destinationPath string
  targetExePath string
}

func (ad *AppDeployer) DeployApp() {
  if err := ad.qtDeployer.queryQtEnv(); err != nil {
    log.Println(err)
  }

  ad.waitGroup.Add(1)
  go ad.processMainExe()

  go ad.processCopyRequests()
  go ad.processRunPathChangeRequests()
  go ad.processQtLibs()

  log.Printf("Waiting for processing to finish")
  ad.waitGroup.Wait()
  log.Printf("Processing has finished")

  close(ad.libsChannel)
  close(ad.copyChannel)
  close(ad.qtChannel)
  close(ad.rpathChannel)
}

func (ad *AppDeployer) deployLibrary(sourceRoot, sourcePath, targetPath string) {
  ad.waitGroup.Add(1)
  go func() {
    ad.libsChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: sourcePath,
      targetPath: targetPath,
      isLddDependency: true,
    }
  }()
}

func (ad *AppDeployer) copyFile(sourceRoot, sourcePath, targetPath string, isLddDependency bool) {
  ad.waitGroup.Add(1)
  go func() {
    ad.copyChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: sourcePath,
      targetPath: targetPath,
      isLddDependency: isLddDependency,
    }
  }()
}

func (ad *AppDeployer) accountLibrary(libpath string) {
  log.Printf("Processed library %v", libpath)
  ad.processedLibs[libpath] = true
}

func (ad *AppDeployer) isLibraryDeployed(libpath string) bool {
  _, ok := ad.processedLibs[libpath]
  return ok
}

func (ad *AppDeployer) processMainExe() {
  dependencies, err := ad.findLddDependencies(ad.targetExePath)
  if err != nil { log.Fatal(err) }

  ad.accountLibrary(ad.targetExePath)
  ad.copyFile("", ad.targetExePath, ".", LDD_DEPENDENCY)

  for _, dependPath := range dependencies {
    if !ad.isLibraryDeployed(dependPath) {
      ad.deployLibrary("", dependPath, "lib")
    } else {
      log.Printf("Dependency seems to be processed: %v", dependPath)
    }
  }

  go ad.processLibs()

  ad.waitGroup.Done()
}

func (ad *AppDeployer) processCopyRequests() {
  for copyRequest := range ad.copyChannel {
    ad.processCopyRequest(copyRequest)
    ad.waitGroup.Done()
  }
}

func (ad *AppDeployer) processCopyRequest(copyRequest *DeployRequest) {
  var destinationPath, destinationPrefix string

  if len(copyRequest.sourceRoot) == 0 {
    // absolute path
    destinationPrefix = copyRequest.targetPath
  } else {
    destinationPrefix = filepath.Join(copyRequest.targetPath, copyRequest.SourceDir())
  }

  sourcePath := copyRequest.FullPath()
  destinationPath = filepath.Join(ad.destinationPath, destinationPrefix, filepath.Base(copyRequest.sourcePath))

  ensureDirExists(destinationPath)

  log.Printf("Copying %v to %v", sourcePath, destinationPath)
  err := copyFile(sourcePath, destinationPath)

  if err == nil && copyRequest.isLddDependency {
    ad.waitGroup.Add(1)
    go func(qtRequest *DeployRequest) {
      ad.qtChannel <- qtRequest
    }(copyRequest)

    ad.changeRPath(destinationPath)
  } else {
    log.Println(err)
  }

  // TODO: submit to strip/patchelf/etc. if copyRequest.isLddDependency
}

func (ad *AppDeployer) changeRPath(fullpath string) {
  ad.waitGroup.Add(1)
  go func() {
    ad.rpathChannel <- fullpath
  }()
}

// copies one file
func (ad *AppDeployer) copyOnce(sourceRoot, sourcePath, targetPath string) error {
  path := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Copying once %v into %v", path, targetPath)
  relativePath, err := filepath.Rel(sourceRoot, path)
  if err != nil {
    log.Println(err)
  }

  ad.waitGroup.Add(1)
  go func() {
    ad.copyChannel <- &DeployRequest{
      sourceRoot: sourceRoot,
      sourcePath: relativePath,
      targetPath: targetPath,
      isLddDependency: false,
    }
  }()

  return err
}

// copies everything without inspection
func (ad *AppDeployer) copyRecursively(sourceRoot, sourcePath, targetPath string) error {
  rootpath := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Copying recursively %v into %v", rootpath, targetPath)

  err := filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    relativePath, err := filepath.Rel(sourceRoot, path)
    if err != nil {
      log.Println(err)
    }

    ad.copyFile(sourceRoot, relativePath, targetPath, ORDINARY_FILE)

    return nil
  })

  return err
}

// inspects libraries for dependencies and copies other files
func (ad *AppDeployer) deployRecursively(sourceRoot, sourcePath, targetPath string, onlyLibraries bool) error {
  rootpath := filepath.Join(sourceRoot, sourcePath)
  log.Printf("Deploying recursively %v in %v", sourceRoot, sourcePath)

  err := filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    basename := filepath.Base(path)
    isLibrary := strings.Contains(basename, ".so")

    if !isLibrary && onlyLibraries {
      return nil
    }

    relativePath, err := filepath.Rel(sourceRoot, path)
    if err != nil {
      log.Println(err)
    }

    if isLibrary {
      ad.deployLibrary(sourceRoot, relativePath, targetPath)
    } else {
      ad.copyFile(sourceRoot, relativePath, targetPath, ORDINARY_FILE)
    }

    return nil
  })

  return err
}
<|endoftext|>


<commit_before>package rados

// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
import "C"

import (
	"unsafe"

	"github.com/ceph/go-ceph/internal/cutil"
)

func radosBufferFree(p unsafe.Pointer) {
	C.rados_buffer_free((*C.char)(p))
}

// MonCommand sends a command to one of the monitors
func (c *Conn) MonCommand(args []byte) ([]byte, string, error) {
	return c.MonCommandWithInputBuffer(args, nil)
}

// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) ([]byte, string, error) {
	ci := cutil.NewCommandInput([][]byte{args}, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_mon_command(
		c.cluster,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}

// PGCommand sends a command to one of the PGs
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommand(pgid []byte, args [][]byte) ([]byte, string, error) {
	return c.PGCommandWithInputBuffer(pgid, args, nil)
}

// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) ([]byte, string, error) {
	name := C.CString(string(pgid))
	defer C.free(unsafe.Pointer(name))
	ci := cutil.NewCommandInput(args, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_pg_command(
		c.cluster,
		name,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}

// MgrCommand sends a command to a ceph-mgr.
func (c *Conn) MgrCommand(args [][]byte) ([]byte, string, error) {
	return c.MgrCommandWithInputBuffer(args, nil)
}

// MgrCommandWithInputBuffer sends a command, with an input buffer, to a ceph-mgr.
//
// Implements:
//  int rados_mgr_command(rados_t cluster, const char **cmd,
//                         size_t cmdlen, const char *inbuf,
//                         size_t inbuflen, char **outbuf,
//                         size_t *outbuflen, char **outs,
//                          size_t *outslen);
func (c *Conn) MgrCommandWithInputBuffer(args [][]byte, inputBuffer []byte) ([]byte, string, error) {
	ci := cutil.NewCommandInput(args, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_mgr_command(
		c.cluster,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}
<commit_msg>rados: add OsdCommand & OsdCommandWithInputBuffer functions<commit_after>package rados

// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
import "C"

import (
	"unsafe"

	"github.com/ceph/go-ceph/internal/cutil"
)

func radosBufferFree(p unsafe.Pointer) {
	C.rados_buffer_free((*C.char)(p))
}

// MonCommand sends a command to one of the monitors
func (c *Conn) MonCommand(args []byte) ([]byte, string, error) {
	return c.MonCommandWithInputBuffer(args, nil)
}

// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) ([]byte, string, error) {
	ci := cutil.NewCommandInput([][]byte{args}, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_mon_command(
		c.cluster,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}

// PGCommand sends a command to one of the PGs
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommand(pgid []byte, args [][]byte) ([]byte, string, error) {
	return c.PGCommandWithInputBuffer(pgid, args, nil)
}

// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) ([]byte, string, error) {
	name := C.CString(string(pgid))
	defer C.free(unsafe.Pointer(name))
	ci := cutil.NewCommandInput(args, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_pg_command(
		c.cluster,
		name,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}

// MgrCommand sends a command to a ceph-mgr.
func (c *Conn) MgrCommand(args [][]byte) ([]byte, string, error) {
	return c.MgrCommandWithInputBuffer(args, nil)
}

// MgrCommandWithInputBuffer sends a command, with an input buffer, to a ceph-mgr.
//
// Implements:
//  int rados_mgr_command(rados_t cluster, const char **cmd,
//                         size_t cmdlen, const char *inbuf,
//                         size_t inbuflen, char **outbuf,
//                         size_t *outbuflen, char **outs,
//                          size_t *outslen);
func (c *Conn) MgrCommandWithInputBuffer(args [][]byte, inputBuffer []byte) ([]byte, string, error) {
	ci := cutil.NewCommandInput(args, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_mgr_command(
		c.cluster,
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}

// OsdCommand sends a command to the specified ceph OSD.
func (c *Conn) OsdCommand(osd int, args [][]byte) ([]byte, string, error) {
	return c.OsdCommandWithInputBuffer(osd, args, nil)
}

// OsdCommandWithInputBuffer sends a command, with an input buffer, to the
// specified ceph OSD.
//
// Implements:
//  int rados_osd_command(rados_t cluster, int osdid,
//                                       const char **cmd, size_t cmdlen,
//                                       const char *inbuf, size_t inbuflen,
//                                       char **outbuf, size_t *outbuflen,
//                                       char **outs, size_t *outslen);
func (c *Conn) OsdCommandWithInputBuffer(
	osd int, args [][]byte, inputBuffer []byte) ([]byte, string, error) {

	ci := cutil.NewCommandInput(args, inputBuffer)
	defer ci.Free()
	co := cutil.NewCommandOutput().SetFreeFunc(radosBufferFree)
	defer co.Free()

	ret := C.rados_osd_command(
		c.cluster,
		C.int(osd),
		(**C.char)(ci.Cmd()),
		C.size_t(ci.CmdLen()),
		(*C.char)(ci.InBuf()),
		C.size_t(ci.InBufLen()),
		(**C.char)(co.OutBuf()),
		(*C.size_t)(co.OutBufLen()),
		(**C.char)(co.Outs()),
		(*C.size_t)(co.OutsLen()))
	buf, status := co.GoValues()
	return buf, status, getError(ret)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"errors"
	_ "github.com/lib/pq"
	"io"
	"log"
	"net"
	"os"
	"path"
	"strings"
	"time"
)

var startupPacketSizeInvalid = errors.New("Terminating connection that provided an abnormally sized startup message packet")
var unsupportedProtocolVersion = errors.New("Unexpected protocol version number; expected 196608")
var incorrectlyFormattedPacket = errors.New("Incorrectly formatted protocol packet")

type startupMessage map[string]string

func readStartupMessage(conn net.Conn) (*startupMessage, error) {
	return readStartupMessageInternal(conn, true)
}

func readStartupMessageInternal(conn net.Conn, allowRecursion bool) (*startupMessage, error) {
	var startupMessageSize int32
	err := binary.Read(conn, binary.BigEndian, &startupMessageSize)
	if err != nil {
		return nil, err
	}

	if startupMessageSize < 0 || startupMessageSize > 8096 {
		return nil, startupPacketSizeInvalid
	}

	log.Printf("startup packet was %v bytes", startupMessageSize)

	startupMessageData := make([]byte, startupMessageSize-4)
	_, err = io.ReadFull(conn, startupMessageData)
	if err != nil {
		return nil, err
	}

	log.Printf("startup packet read")

	var protocolVersionNumber int32
	buf := bytes.NewBuffer(startupMessageData)
	err = binary.Read(buf, binary.BigEndian, &protocolVersionNumber)
	if err != nil {
		return nil, err
	}

	if protocolVersionNumber == 80877103 && allowRecursion {
		log.Printf("SSLRequest received; returning N")
		conn.Write([]byte{'N'})
		return readStartupMessageInternal(conn, false)
	} else if protocolVersionNumber != 196608 {
		return nil, unsupportedProtocolVersion
	}

	startupMessageData = startupMessageData[4:]
	startupParameters := make(startupMessage)
	for {
		nextZero := bytes.IndexByte(startupMessageData, 0)
		if nextZero == -1 {
			return nil, incorrectlyFormattedPacket
		} else if nextZero == 0 {
			break
		}

		key := string(startupMessageData[:nextZero])
		startupMessageData = startupMessageData[nextZero+1:]

		nextZero = bytes.IndexByte(startupMessageData, 0)
		if nextZero == -1 {
			return nil, incorrectlyFormattedPacket
		}
		value := string(startupMessageData[:nextZero])
		startupMessageData = startupMessageData[nextZero+1:]

		log.Printf("key = %v, value = %v", key, value)
		startupParameters[key] = value
	}

	return &startupParameters, nil
}

func handleIncomingConnection(conn net.Conn, masterRequestChannel, replicaRequestChannel chan<- serverRequest) {
	defer conn.Close()

	// One-minute timeout to read the startup message
	conn.SetReadDeadline(time.Now().Add(time.Minute))

	startupMessage, err := readStartupMessage(conn)
	if err != nil {
		log.Print(err)
		return
	}
	startupParameters := *startupMessage

	// Reset read deadline to no timeout
	conn.SetReadDeadline(time.Time{})

	// Check if we're going to connect to a replica or to the master
	dbName, ok := startupParameters["database"]
	wantReplica := false
	if !ok {
		dbName, ok = startupParameters["user"]
		if !ok {
			log.Printf("Expected database or user parameter, neither found")
			return
		}
	}
	if strings.HasSuffix(dbName, "_replica") {
		wantReplica = true
		startupParameters["database"] = dbName[:len(dbName)-8]
		log.Printf("Rewriting database name from %v to %v", dbName, startupParameters["database"])
	}

	// Fetch a backend server, either a master or a replica
	responseChannel := make(chan *string)
	request := serverRequest{responseChannel}
	if wantReplica {
		replicaRequestChannel <- request
	} else {
		masterRequestChannel <- request
	}
	backend := <-responseChannel
	if backend == nil {
		// FIXME: it'd be nice to return an error message to the client for some of these failures...
		log.Println("Unable to find satisfactory backend server")
		return
	}

	// Create the new startup message w/ the possibly different startupParameters
	newStartupMessageExcludingSize := &bytes.Buffer{}
	newStartupMessageExcludingSize.Grow(1024)
	binary.Write(newStartupMessageExcludingSize, binary.BigEndian, 196608)
	for key, value := range startupParameters {
		newStartupMessageExcludingSize.Write([]byte(key))
		newStartupMessageExcludingSize.Write([]byte{0})
		newStartupMessageExcludingSize.Write([]byte(value))
		newStartupMessageExcludingSize.Write([]byte{0})
	}
	// Terminating startup packet byte
	newStartupMessageExcludingSize.Write([]byte{0})

	// Send the new connection our startup packet
	log.Printf("backend to connect to: %v", *backend)
	upstream, err := net.Dial(network(*backend))
	if err != nil {
		log.Print(err)
		return
	}
	err = binary.Write(upstream, binary.BigEndian, int32(newStartupMessageExcludingSize.Len()+4))
	if err != nil {
		log.Print(err)
		return
	}
	_, err = upstream.Write(newStartupMessageExcludingSize.Bytes())
	if err != nil {
		log.Print(err)
		return
	}

	// Stream data between the two network connections
	log.Printf("Beginning dual Copy invocations")
	go func() {
		numCopied, err := io.Copy(upstream, conn)
		log.Printf("Copy(upstream, conn) -> %v, %v", numCopied, err)
	}()
	numCopied, err := io.Copy(conn, upstream)
	log.Printf("Copy(conn, upstream) -> %v, %v", numCopied, err)
	if err != nil {
		log.Print(err)
		return
	}

	log.Printf("Connection closed softly")
}

//// BEGIN: Copy/hacked from lib/pq
func network(name string) (string, string) {
	o := make(Values)

	// A number of defaults are applied here, in this order:
	//
	// * Very low precedence defaults applied in every situation
	// * Environment variables
	// * Explicitly passed connection information
	o.Set("host", "localhost")
	o.Set("port", "5432")

	for k, v := range parseEnviron(os.Environ()) {
		o.Set(k, v)
	}

	parseOpts(name, o)

	// Don't care about user, just host & port
	//// If a user is not provided by any other means, the last
	//// resort is to use the current operating system provided user
	//// name.
	//if o.Get("user") == "" {
	//  u, err := userCurrent()
	//  if err != nil {
	//      return nil, err
	//  } else {
	//      o.Set("user", u)
	//  }
	//}

	host := o.Get("host")

	if strings.HasPrefix(host, "/") {
		sockPath := path.Join(host, ".s.PGSQL."+o.Get("port"))
		return "unix", sockPath
	}

	return "tcp", host + ":" + o.Get("port")
}

type Values map[string]string

func (vs Values) Set(k, v string) {
	vs[k] = v
}

func (vs Values) Get(k string) (v string) {
	return vs[k]
}

func parseOpts(name string, o Values) {
	if len(name) == 0 {
		return
	}

	name = strings.TrimSpace(name)

	ps := strings.Split(name, " ")
	for _, p := range ps {
		kv := strings.Split(p, "=")
		if len(kv) < 2 {
			log.Fatalf("invalid option: %q", p)
		}
		o.Set(kv[0], kv[1])
	}
}

// parseEnviron tries to mimic some of libpq's environment handling
//
// To ease testing, it does not directly reference os.Environ, but is
// designed to accept its output.
//
// Environment-set connection information is intended to have a higher
// precedence than a library default but lower than any explicitly
// passed information (such as in the URL or connection string).
func parseEnviron(env []string) (out map[string]string) {
	out = make(map[string]string)

	for _, v := range env {
		parts := strings.SplitN(v, "=", 2)

		accrue := func(keyname string) {
			out[keyname] = parts[1]
		}

		// The order of these is the same as is seen in the
		// PostgreSQL 9.1 manual, with omissions briefly
		// noted.
		switch parts[0] {
		case "PGHOST":
			accrue("host")
		case "PGHOSTADDR":
			accrue("hostaddr")
		case "PGPORT":
			accrue("port")
		case "PGDATABASE":
			accrue("dbname")
		case "PGUSER":
			accrue("user")
		case "PGPASSWORD":
			accrue("password")
		// skip PGPASSFILE, PGSERVICE, PGSERVICEFILE,
		// PGREALM
		case "PGOPTIONS":
			accrue("options")
		case "PGAPPNAME":
			accrue("application_name")
		case "PGSSLMODE":
			accrue("sslmode")
		case "PGREQUIRESSL":
			accrue("requiressl")
		case "PGSSLCERT":
			accrue("sslcert")
		case "PGSSLKEY":
			accrue("sslkey")
		case "PGSSLROOTCERT":
			accrue("sslrootcert")
		case "PGSSLCRL":
			accrue("sslcrl")
		case "PGREQUIREPEER":
			accrue("requirepeer")
		case "PGKRBSRVNAME":
			accrue("krbsrvname")
		case "PGGSSLIB":
			accrue("gsslib")
		case "PGCONNECT_TIMEOUT":
			accrue("connect_timeout")
		case "PGCLIENTENCODING":
			accrue("client_encoding")
			// skip PGDATESTYLE, PGTZ, PGGEQO, PGSYSCONFDIR,
			// PGLOCALEDIR
		}
	}

	return out
}

//// END: Copy/hacked from lib/pq
<commit_msg>Send errors back to client when possible; fix protocol version<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"errors"
	_ "github.com/lib/pq"
	"io"
	"log"
	"net"
	"os"
	"path"
	"strings"
	"time"
)

var startupPacketSizeInvalid = errors.New("Terminating connection that provided an abnormally sized startup message packet")
var unsupportedProtocolVersion = errors.New("Unexpected protocol version number; expected 196608")
var incorrectlyFormattedPacket = errors.New("Incorrectly formatted protocol packet")

type startupMessage map[string]string

func sendError(conn net.Conn, errorMessage string) {
	errorMessageExcludingSize := &bytes.Buffer{}
	errorMessageExcludingSize.Grow(1024)

	errorMessageExcludingSize.Write([]byte("S"))
	errorMessageExcludingSize.Write([]byte("ERROR"))
	errorMessageExcludingSize.Write([]byte{0})

	errorMessageExcludingSize.Write([]byte("C"))
	errorMessageExcludingSize.Write([]byte("08000")) // connection exception
	errorMessageExcludingSize.Write([]byte{0})

	errorMessageExcludingSize.Write([]byte("M"))
	errorMessageExcludingSize.Write([]byte(errorMessage))
	errorMessageExcludingSize.Write([]byte{0})

	// Terminating ErrorResponse byte
	errorMessageExcludingSize.Write([]byte{0})

	// Send the error message on the connection.  No error handling here; the connection
	// isn't likely to live for long now anyways. :-)
	conn.Write([]byte{'E'})
	binary.Write(conn, binary.BigEndian, int32(errorMessageExcludingSize.Len()+4))
	conn.Write(errorMessageExcludingSize.Bytes())
}

func readStartupMessage(conn net.Conn) (*startupMessage, error) {
	return readStartupMessageInternal(conn, true)
}

func readStartupMessageInternal(conn net.Conn, allowRecursion bool) (*startupMessage, error) {
	var startupMessageSize int32
	err := binary.Read(conn, binary.BigEndian, &startupMessageSize)
	if err != nil {
		return nil, err
	}

	if startupMessageSize < 0 || startupMessageSize > 8096 {
		sendError(conn, "Startup packet size invalid")
		return nil, startupPacketSizeInvalid
	}

	log.Printf("startup packet was %v bytes", startupMessageSize)

	startupMessageData := make([]byte, startupMessageSize-4)
	_, err = io.ReadFull(conn, startupMessageData)
	if err != nil {
		sendError(conn, "Socket read error")
		return nil, err
	}

	log.Printf("startup packet read")

	var protocolVersionNumber int32
	buf := bytes.NewBuffer(startupMessageData)
	err = binary.Read(buf, binary.BigEndian, &protocolVersionNumber)
	if err != nil {
		sendError(conn, "Socket read error")
		return nil, err
	}

	if protocolVersionNumber == 80877103 && allowRecursion {
		log.Printf("SSLRequest received; returning N")
		conn.Write([]byte{'N'})
		return readStartupMessageInternal(conn, false)
	} else if protocolVersionNumber == 80877102 {
		log.Printf("CancelRequest packet received; not supported yet!")
		return nil, unsupportedProtocolVersion
	} else if protocolVersionNumber != 196608 {
		sendError(conn, "Unsupported protocol version")
		return nil, unsupportedProtocolVersion
	}

	startupMessageData = startupMessageData[4:]
	startupParameters := make(startupMessage)
	for {
		nextZero := bytes.IndexByte(startupMessageData, 0)
		if nextZero == -1 {
			sendError(conn, "Malformed startup packet")
			return nil, incorrectlyFormattedPacket
		} else if nextZero == 0 {
			break
		}

		key := string(startupMessageData[:nextZero])
		startupMessageData = startupMessageData[nextZero+1:]

		nextZero = bytes.IndexByte(startupMessageData, 0)
		if nextZero == -1 {
			sendError(conn, "Malformed startup packet")
			return nil, incorrectlyFormattedPacket
		}
		value := string(startupMessageData[:nextZero])
		startupMessageData = startupMessageData[nextZero+1:]

		log.Printf("key = %v, value = %v", key, value)
		startupParameters[key] = value
	}

	return &startupParameters, nil
}

func handleIncomingConnection(conn net.Conn, masterRequestChannel, replicaRequestChannel chan<- serverRequest) {
	defer conn.Close()

	// One-minute timeout to read the startup message
	conn.SetReadDeadline(time.Now().Add(time.Minute))

	startupMessage, err := readStartupMessage(conn)
	if err != nil {
		log.Print(err)
		return
	}
	startupParameters := *startupMessage

	// Reset read deadline to no timeout
	conn.SetReadDeadline(time.Time{})

	// Check if we're going to connect to a replica or to the master
	dbName, ok := startupParameters["database"]
	wantReplica := false
	if !ok {
		dbName, ok = startupParameters["user"]
		if !ok {
			sendError(conn, "Missing database or user parameter")
			log.Printf("Expected database or user parameter, neither found")
			return
		}
	}
	if strings.HasSuffix(dbName, "_replica") {
		wantReplica = true
		startupParameters["database"] = dbName[:len(dbName)-8]
		log.Printf("Rewriting database name from %v to %v", dbName, startupParameters["database"])
	}

	// Fetch a backend server, either a master or a replica
	responseChannel := make(chan *string)
	request := serverRequest{responseChannel}
	if wantReplica {
		replicaRequestChannel <- request
	} else {
		masterRequestChannel <- request
	}
	backend := <-responseChannel
	if backend == nil {
		sendError(conn, "Unable to find satisfactory backend server")
		log.Println("Unable to find satisfactory backend server")
		return
	}

	// Create the new startup message w/ the possibly different startupParameters
	var protocolVersion int32 = 196608
	newStartupMessageExcludingSize := &bytes.Buffer{}
	newStartupMessageExcludingSize.Grow(1024)
	binary.Write(newStartupMessageExcludingSize, binary.BigEndian, protocolVersion)
	for key, value := range startupParameters {
		newStartupMessageExcludingSize.Write([]byte(key))
		newStartupMessageExcludingSize.Write([]byte{0})
		newStartupMessageExcludingSize.Write([]byte(value))
		newStartupMessageExcludingSize.Write([]byte{0})
	}
	// Terminating startup packet byte
	newStartupMessageExcludingSize.Write([]byte{0})

	// Send the new connection our startup packet
	log.Printf("backend to connect to: %v", *backend)
	upstream, err := net.Dial(network(*backend))
	if err != nil {
		sendError(conn, "Unable to connect to backend server")
		log.Print(err)
		return
	}
	err = binary.Write(upstream, binary.BigEndian, int32(newStartupMessageExcludingSize.Len()+4))
	if err != nil {
		sendError(conn, "Backend network error")
		log.Print(err)
		return
	}
	_, err = upstream.Write(newStartupMessageExcludingSize.Bytes())
	if err != nil {
		sendError(conn, "Backend network error")
		log.Print(err)
		return
	}

	// Stream data between the two network connections
	log.Printf("Beginning dual Copy invocations")
	go func() {
		numCopied, err := io.Copy(upstream, conn)
		log.Printf("Copy(upstream, conn) -> %v, %v", numCopied, err)
	}()
	numCopied, err := io.Copy(conn, upstream)
	log.Printf("Copy(conn, upstream) -> %v, %v", numCopied, err)
	if err != nil {
		log.Print(err)
		return
	}

	log.Printf("Connection closed softly")
}

//// BEGIN: Copy/hacked from lib/pq
func network(name string) (string, string) {
	o := make(Values)

	// A number of defaults are applied here, in this order:
	//
	// * Very low precedence defaults applied in every situation
	// * Environment variables
	// * Explicitly passed connection information
	o.Set("host", "localhost")
	o.Set("port", "5432")

	for k, v := range parseEnviron(os.Environ()) {
		o.Set(k, v)
	}

	parseOpts(name, o)

	// Don't care about user, just host & port
	//// If a user is not provided by any other means, the last
	//// resort is to use the current operating system provided user
	//// name.
	//if o.Get("user") == "" {
	//  u, err := userCurrent()
	//  if err != nil {
	//      return nil, err
	//  } else {
	//      o.Set("user", u)
	//  }
	//}

	host := o.Get("host")

	if strings.HasPrefix(host, "/") {
		sockPath := path.Join(host, ".s.PGSQL."+o.Get("port"))
		return "unix", sockPath
	}

	return "tcp", host + ":" + o.Get("port")
}

type Values map[string]string

func (vs Values) Set(k, v string) {
	vs[k] = v
}

func (vs Values) Get(k string) (v string) {
	return vs[k]
}

func parseOpts(name string, o Values) {
	if len(name) == 0 {
		return
	}

	name = strings.TrimSpace(name)

	ps := strings.Split(name, " ")
	for _, p := range ps {
		kv := strings.Split(p, "=")
		if len(kv) < 2 {
			log.Fatalf("invalid option: %q", p)
		}
		o.Set(kv[0], kv[1])
	}
}

// parseEnviron tries to mimic some of libpq's environment handling
//
// To ease testing, it does not directly reference os.Environ, but is
// designed to accept its output.
//
// Environment-set connection information is intended to have a higher
// precedence than a library default but lower than any explicitly
// passed information (such as in the URL or connection string).
func parseEnviron(env []string) (out map[string]string) {
	out = make(map[string]string)

	for _, v := range env {
		parts := strings.SplitN(v, "=", 2)

		accrue := func(keyname string) {
			out[keyname] = parts[1]
		}

		// The order of these is the same as is seen in the
		// PostgreSQL 9.1 manual, with omissions briefly
		// noted.
		switch parts[0] {
		case "PGHOST":
			accrue("host")
		case "PGHOSTADDR":
			accrue("hostaddr")
		case "PGPORT":
			accrue("port")
		case "PGDATABASE":
			accrue("dbname")
		case "PGUSER":
			accrue("user")
		case "PGPASSWORD":
			accrue("password")
		// skip PGPASSFILE, PGSERVICE, PGSERVICEFILE,
		// PGREALM
		case "PGOPTIONS":
			accrue("options")
		case "PGAPPNAME":
			accrue("application_name")
		case "PGSSLMODE":
			accrue("sslmode")
		case "PGREQUIRESSL":
			accrue("requiressl")
		case "PGSSLCERT":
			accrue("sslcert")
		case "PGSSLKEY":
			accrue("sslkey")
		case "PGSSLROOTCERT":
			accrue("sslrootcert")
		case "PGSSLCRL":
			accrue("sslcrl")
		case "PGREQUIREPEER":
			accrue("requirepeer")
		case "PGKRBSRVNAME":
			accrue("krbsrvname")
		case "PGGSSLIB":
			accrue("gsslib")
		case "PGCONNECT_TIMEOUT":
			accrue("connect_timeout")
		case "PGCLIENTENCODING":
			accrue("client_encoding")
			// skip PGDATESTYLE, PGTZ, PGGEQO, PGSYSCONFDIR,
			// PGLOCALEDIR
		}
	}

	return out
}

//// END: Copy/hacked from lib/pq
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package plugin

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"k8s.io/cli-runtime/pkg/genericclioptions"
)

func TestPluginPathsAreUnaltered(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	tempDir2, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins2")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	// cleanup
	defer func() {
		if err := os.RemoveAll(tempDir); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
		if err := os.RemoveAll(tempDir2); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
	}()

	ioStreams, _, _, errOut := genericclioptions.NewTestIOStreams()
	verifier := newFakePluginPathVerifier()
	pluginPaths := []string{tempDir, tempDir2}
	o := &PluginListOptions{
		Verifier:  verifier,
		IOStreams: ioStreams,

		PluginPaths: pluginPaths,
	}

	// write at least one valid plugin file
	if _, err := ioutil.TempFile(tempDir, "kubectl-"); err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	if _, err := ioutil.TempFile(tempDir2, "kubectl-"); err != nil {
		t.Fatalf("unexpected error %v", err)
	}

	if err := o.Run(); err != nil {
		t.Fatalf("unexpected error %v - %v", err, errOut.String())
	}

	// ensure original paths remain unaltered
	if len(verifier.seenUnsorted) != len(pluginPaths) {
		t.Fatalf("saw unexpected plugin paths. Expecting %v, got %v", pluginPaths, verifier.seenUnsorted)
	}
	for actual := range verifier.seenUnsorted {
		if !strings.HasPrefix(verifier.seenUnsorted[actual], pluginPaths[actual]) {
			t.Fatalf("expected PATH slice to be unaltered. Expecting %v, but got %v", pluginPaths[actual], verifier.seenUnsorted[actual])
		}
	}
}

func TestPluginPathsAreValid(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	// cleanup
	defer func() {
		if err := os.RemoveAll(tempDir); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
	}()

	tc := []struct {
		name               string
		pluginPaths        []string
		pluginFile         func() (*os.File, error)
		verifier           *fakePluginPathVerifier
		expectVerifyErrors []error
		expectErr          string
		expectErrOut       string
		expectOut          string
	}{
		{
			name:         "ensure no plugins found if no files begin with kubectl- prefix",
			pluginPaths:  []string{tempDir},
			verifier:     newFakePluginPathVerifier(),
			pluginFile:   func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "notkubectl-")
			},
			expectErr:    "error: unable to find any kubectl plugins in your PATH\n",
		},
		{
			name:         "ensure de-duplicated plugin-paths slice",
			pluginPaths:  []string{tempDir, tempDir},
			verifier:     newFakePluginPathVerifier(),
			pluginFile:   func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "kubectl-")
			},
			expectOut:    "The following compatible plugins are available:",
		},
		{
			name:         "ensure no errors when empty string or blank path are specified",
			pluginPaths:  []string{tempDir, "", " "},
			verifier:     newFakePluginPathVerifier(),
			pluginFile:   func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "kubectl-")
			},
			expectOut:    "The following compatible plugins are available:",
		},
	}

	for _, test := range tc {
		t.Run(test.name, func(t *testing.T) {
			ioStreams, _, out, errOut := genericclioptions.NewTestIOStreams()
			o := &PluginListOptions{
				Verifier:  test.verifier,
				IOStreams: ioStreams,

				PluginPaths: test.pluginPaths,
			}

			// create files
			if test.pluginFile != nil {
				if _, err := test.pluginFile(); err != nil {
					t.Fatalf("unexpected error creating plugin file: %v", err)
				}
			}

			for _, expected := range test.expectVerifyErrors {
				for _, actual := range test.verifier.errors {
					if expected != actual {
						t.Fatalf("unexpected error: expected %v, but got %v", expected, actual)
					}
				}
			}

			err := o.Run()
			if err == nil && len(test.expectErr) > 0 {
				t.Fatalf("unexpected non-error: expected %v, but got nothing", test.expectErr)
			} else if err != nil && len(test.expectErr) == 0 {
				t.Fatalf("unexpected error: expected nothing, but got %v", err.Error())
			} else if err != nil && err.Error() != test.expectErr {
				t.Fatalf("unexpected error: expected %v, but got %v", test.expectErr, err.Error())
			}

			if len(test.expectErrOut) == 0 && errOut.Len() > 0 {
				t.Fatalf("unexpected error output: expected nothing, but got %v", errOut.String())
			} else if len(test.expectErrOut) > 0 && !strings.Contains(errOut.String(), test.expectErrOut) {
				t.Fatalf("unexpected error output: expected to contain %v, but got %v", test.expectErrOut, errOut.String())
			}

			if len(test.expectOut) == 0 && out.Len() > 0 {
				t.Fatalf("unexpected output: expected nothing, but got %v", out.String())
			} else if len(test.expectOut) > 0 && !strings.Contains(out.String(), test.expectOut) {
				t.Fatalf("unexpected output: expected to contain %v, but got %v", test.expectOut, out.String())
			}
		})
	}
}

type duplicatePathError struct {
	path string
}

func (d *duplicatePathError) Error() string {
	return fmt.Sprintf("path %q already visited", d.path)
}

type fakePluginPathVerifier struct {
	errors       []error
	seen         map[string]bool
	seenUnsorted []string
}

func (f *fakePluginPathVerifier) Verify(path string) []error {
	if f.seen[path] {
		err := &duplicatePathError{path}
		f.errors = append(f.errors, err)
		return []error{err}
	}
	f.seen[path] = true
	f.seenUnsorted = append(f.seenUnsorted, path)
	return nil
}

func newFakePluginPathVerifier() *fakePluginPathVerifier {
	return &fakePluginPathVerifier{seen: make(map[string]bool)}
}
<commit_msg>Fixed code formatting issues discovered by verify-gofmt<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package plugin

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"k8s.io/cli-runtime/pkg/genericclioptions"
)

func TestPluginPathsAreUnaltered(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	tempDir2, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins2")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	// cleanup
	defer func() {
		if err := os.RemoveAll(tempDir); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
		if err := os.RemoveAll(tempDir2); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
	}()

	ioStreams, _, _, errOut := genericclioptions.NewTestIOStreams()
	verifier := newFakePluginPathVerifier()
	pluginPaths := []string{tempDir, tempDir2}
	o := &PluginListOptions{
		Verifier:  verifier,
		IOStreams: ioStreams,

		PluginPaths: pluginPaths,
	}

	// write at least one valid plugin file
	if _, err := ioutil.TempFile(tempDir, "kubectl-"); err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	if _, err := ioutil.TempFile(tempDir2, "kubectl-"); err != nil {
		t.Fatalf("unexpected error %v", err)
	}

	if err := o.Run(); err != nil {
		t.Fatalf("unexpected error %v - %v", err, errOut.String())
	}

	// ensure original paths remain unaltered
	if len(verifier.seenUnsorted) != len(pluginPaths) {
		t.Fatalf("saw unexpected plugin paths. Expecting %v, got %v", pluginPaths, verifier.seenUnsorted)
	}
	for actual := range verifier.seenUnsorted {
		if !strings.HasPrefix(verifier.seenUnsorted[actual], pluginPaths[actual]) {
			t.Fatalf("expected PATH slice to be unaltered. Expecting %v, but got %v", pluginPaths[actual], verifier.seenUnsorted[actual])
		}
	}
}

func TestPluginPathsAreValid(t *testing.T) {
	tempDir, err := ioutil.TempDir(os.TempDir(), "test-cmd-plugins")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	// cleanup
	defer func() {
		if err := os.RemoveAll(tempDir); err != nil {
			panic(fmt.Errorf("unexpected cleanup error: %v", err))
		}
	}()

	tc := []struct {
		name               string
		pluginPaths        []string
		pluginFile         func() (*os.File, error)
		verifier           *fakePluginPathVerifier
		expectVerifyErrors []error
		expectErr          string
		expectErrOut       string
		expectOut          string
	}{
		{
			name:        "ensure no plugins found if no files begin with kubectl- prefix",
			pluginPaths: []string{tempDir},
			verifier:    newFakePluginPathVerifier(),
			pluginFile: func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "notkubectl-")
			},
			expectErr: "error: unable to find any kubectl plugins in your PATH\n",
		},
		{
			name:        "ensure de-duplicated plugin-paths slice",
			pluginPaths: []string{tempDir, tempDir},
			verifier:    newFakePluginPathVerifier(),
			pluginFile: func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "kubectl-")
			},
			expectOut: "The following compatible plugins are available:",
		},
		{
			name:        "ensure no errors when empty string or blank path are specified",
			pluginPaths: []string{tempDir, "", " "},
			verifier:    newFakePluginPathVerifier(),
			pluginFile: func() (*os.File, error) {
				return ioutil.TempFile(tempDir, "kubectl-")
			},
			expectOut: "The following compatible plugins are available:",
		},
	}

	for _, test := range tc {
		t.Run(test.name, func(t *testing.T) {
			ioStreams, _, out, errOut := genericclioptions.NewTestIOStreams()
			o := &PluginListOptions{
				Verifier:  test.verifier,
				IOStreams: ioStreams,

				PluginPaths: test.pluginPaths,
			}

			// create files
			if test.pluginFile != nil {
				if _, err := test.pluginFile(); err != nil {
					t.Fatalf("unexpected error creating plugin file: %v", err)
				}
			}

			for _, expected := range test.expectVerifyErrors {
				for _, actual := range test.verifier.errors {
					if expected != actual {
						t.Fatalf("unexpected error: expected %v, but got %v", expected, actual)
					}
				}
			}

			err := o.Run()
			if err == nil && len(test.expectErr) > 0 {
				t.Fatalf("unexpected non-error: expected %v, but got nothing", test.expectErr)
			} else if err != nil && len(test.expectErr) == 0 {
				t.Fatalf("unexpected error: expected nothing, but got %v", err.Error())
			} else if err != nil && err.Error() != test.expectErr {
				t.Fatalf("unexpected error: expected %v, but got %v", test.expectErr, err.Error())
			}

			if len(test.expectErrOut) == 0 && errOut.Len() > 0 {
				t.Fatalf("unexpected error output: expected nothing, but got %v", errOut.String())
			} else if len(test.expectErrOut) > 0 && !strings.Contains(errOut.String(), test.expectErrOut) {
				t.Fatalf("unexpected error output: expected to contain %v, but got %v", test.expectErrOut, errOut.String())
			}

			if len(test.expectOut) == 0 && out.Len() > 0 {
				t.Fatalf("unexpected output: expected nothing, but got %v", out.String())
			} else if len(test.expectOut) > 0 && !strings.Contains(out.String(), test.expectOut) {
				t.Fatalf("unexpected output: expected to contain %v, but got %v", test.expectOut, out.String())
			}
		})
	}
}

type duplicatePathError struct {
	path string
}

func (d *duplicatePathError) Error() string {
	return fmt.Sprintf("path %q already visited", d.path)
}

type fakePluginPathVerifier struct {
	errors       []error
	seen         map[string]bool
	seenUnsorted []string
}

func (f *fakePluginPathVerifier) Verify(path string) []error {
	if f.seen[path] {
		err := &duplicatePathError{path}
		f.errors = append(f.errors, err)
		return []error{err}
	}
	f.seen[path] = true
	f.seenUnsorted = append(f.seenUnsorted, path)
	return nil
}

func newFakePluginPathVerifier() *fakePluginPathVerifier {
	return &fakePluginPathVerifier{seen: make(map[string]bool)}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
	"time"

	log "code.google.com/p/log4go"
	"github.com/influxdb/influxdb/_vendor/raft"
	"github.com/influxdb/influxdb/configuration"
	"github.com/influxdb/influxdb/coordinator"
	"github.com/influxdb/influxdb/server"
	"github.com/jmhodges/levigo"
)

func setupLogging(loggingLevel, logFile string) {
	level := log.DEBUG
	switch loggingLevel {
	case "fine":
		level = log.FINE
	case "debug":
		level = log.DEBUG
	case "info":
		level = log.INFO
	case "warn":
		level = log.WARNING
	case "error":
		level = log.ERROR
	default:
		log.Error("Unknown log level %s. Defaulting to DEBUG", loggingLevel)
	}

	log.Global = make(map[string]*log.Filter)

	facility, ok := GetSysLogFacility(logFile)
	if ok {
		flw, err := NewSysLogWriter(facility)
		if err != nil {
			fmt.Fprintf(os.Stderr, "NewSysLogWriter: %s\n", err.Error())
			return
		}
		log.AddFilter("syslog", level, flw)
	} else if logFile == "stdout" {
		flw := log.NewConsoleLogWriter()
		log.AddFilter("stdout", level, flw)
	} else {
		logFileDir := filepath.Dir(logFile)
		os.MkdirAll(logFileDir, 0744)

		flw := log.NewFileLogWriter(logFile, false)
		log.AddFilter("file", level, flw)

		flw.SetFormat("[%D %T] [%L] (%S) %M")
		flw.SetRotate(true)
		flw.SetRotateSize(0)
		flw.SetRotateLines(0)
		flw.SetRotateDaily(true)
	}

	log.Info("Redirectoring logging to %s", logFile)
}

func main() {
	if start() != nil {
		os.Exit(1)
	}

	os.Exit(0)
}

func start() error {
	fileName := flag.String("config", "config.sample.toml", "Config file")
	wantsVersion := flag.Bool("v", false, "Get version number")
	resetRootPassword := flag.Bool("reset-root", false, "Reset root password")
	hostname := flag.String("hostname", "", "Override the hostname, the `hostname` config option will be overridden")
	raftPort := flag.Int("raft-port", 0, "Override the raft port, the `raft.port` config option will be overridden")
	protobufPort := flag.Int("protobuf-port", 0, "Override the protobuf port, the `protobuf_port` config option will be overridden")
	pidFile := flag.String("pidfile", "", "the pid file")
	repairLeveldb := flag.Bool("repair-ldb", false, "set to true to repair the leveldb files")
	stdout := flag.Bool("stdout", false, "Log to stdout overriding the configuration")
	syslog := flag.String("syslog", "", "Log to syslog facility overriding the configuration")

	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	v := fmt.Sprintf("InfluxDB v%s (git: %s) (leveldb: %d.%d)", version, gitSha, levigo.GetLevelDBMajorVersion(), levigo.GetLevelDBMinorVersion())
	if wantsVersion != nil && *wantsVersion {
		fmt.Println(v)
		return nil
	}
	config, err := configuration.LoadConfiguration(*fileName)

	if err != nil {
		return err
	}

	// override the hostname if it was specified on the command line
	if hostname != nil && *hostname != "" {
		config.Hostname = *hostname
	}

	if raftPort != nil && *raftPort != 0 {
		config.RaftServerPort = *raftPort
	}

	if protobufPort != nil && *protobufPort != 0 {
		config.ProtobufPort = *protobufPort
	}

	config.Version = v
	config.InfluxDBVersion = version

	if *stdout {
		config.LogFile = "stdout"
	}

	if *syslog != "" {
		config.LogFile = *syslog
	}

	setupLogging(config.LogLevel, config.LogFile)

	if config.RaftDebug {
		log.Info("Turning on raft debug logging")
		raft.SetLogLevel(raft.Trace)
	}

	if *repairLeveldb {
		log.Info("Repairing leveldb")
		files, err := ioutil.ReadDir(config.DataDir)
		if err != nil {
			panic(err)
		}
		o := levigo.NewOptions()
		defer o.Close()
		for _, f := range files {
			p := path.Join(config.DataDir, f.Name())
			log.Info("Repairing %s", p)
			if err := levigo.RepairDatabase(p, o); err != nil {
				panic(err)
			}
		}
	}

	if pidFile != nil && *pidFile != "" {
		pid := strconv.Itoa(os.Getpid())
		if err := ioutil.WriteFile(*pidFile, []byte(pid), 0644); err != nil {
			panic(err)
		}
	}

	if config.BindAddress == "" {
		log.Info("Starting Influx Server %s...", version)
	} else {
		log.Info("Starting Influx Server %s bound to %s...", version, config.BindAddress)
	}
	fmt.Printf(`
+---------------------------------------------+
|  _____        __ _            _____  ____   |
| |_   _|      / _| |          |  __ \|  _ \  |
|   | |  _ __ | |_| |_   ___  _| |  | | |_) | |
|   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |
|  _| |_| | | | | | | |_| |>  <| |__| | |_) | |
| |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |
+---------------------------------------------+

`)
	os.MkdirAll(config.RaftDir, 0744)
	os.MkdirAll(config.DataDir, 0744)
	server, err := server.NewServer(config)
	if err != nil {
		// sleep for the log to flush
		time.Sleep(time.Second)
		panic(err)
	}

	if err := startProfiler(server); err != nil {
		panic(err)
	}

	if *resetRootPassword {
		// TODO: make this not suck
		// This is ghetto as hell, but it'll work for now.
		go func() {
			time.Sleep(2 * time.Second) // wait for the raft server to join the cluster

			log.Warn("Resetting root's password to %s", coordinator.DEFAULT_ROOT_PWD)
			if err := server.RaftServer.CreateRootUser(); err != nil {
				panic(err)
			}
		}()
	}
	err = server.ListenAndServe()
	if err != nil {
		log.Error("ListenAndServe failed: ", err)
	}
	return err
}
<commit_msg>Fix #947: exit nice if no permission to write log<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
	"time"

	log "code.google.com/p/log4go"
	"github.com/influxdb/influxdb/_vendor/raft"
	"github.com/influxdb/influxdb/configuration"
	"github.com/influxdb/influxdb/coordinator"
	"github.com/influxdb/influxdb/server"
	"github.com/jmhodges/levigo"
)

func setupLogging(loggingLevel, logFile string) {
	level := log.DEBUG
	switch loggingLevel {
	case "fine":
		level = log.FINE
	case "debug":
		level = log.DEBUG
	case "info":
		level = log.INFO
	case "warn":
		level = log.WARNING
	case "error":
		level = log.ERROR
	default:
		log.Error("Unknown log level %s. Defaulting to DEBUG", loggingLevel)
	}

	log.Global = make(map[string]*log.Filter)

	facility, ok := GetSysLogFacility(logFile)
	if ok {
		flw, err := NewSysLogWriter(facility)
		if err != nil {
			fmt.Fprintf(os.Stderr, "NewSysLogWriter: %s\n", err.Error())
			return
		}
		log.AddFilter("syslog", level, flw)
	} else if logFile == "stdout" {
		flw := log.NewConsoleLogWriter()
		log.AddFilter("stdout", level, flw)
	} else {
		logFileDir := filepath.Dir(logFile)
		os.MkdirAll(logFileDir, 0744)

		flw := log.NewFileLogWriter(logFile, false)
		if flw == nil {
			os.Exit(1)
		}
		log.AddFilter("file", level, flw)

		flw.SetFormat("[%D %T] [%L] (%S) %M")
		flw.SetRotate(true)
		flw.SetRotateSize(0)
		flw.SetRotateLines(0)
		flw.SetRotateDaily(true)
	}

	log.Info("Redirectoring logging to %s", logFile)
}

func main() {
	if start() != nil {
		os.Exit(1)
	}

	os.Exit(0)
}

func start() error {
	fileName := flag.String("config", "config.sample.toml", "Config file")
	wantsVersion := flag.Bool("v", false, "Get version number")
	resetRootPassword := flag.Bool("reset-root", false, "Reset root password")
	hostname := flag.String("hostname", "", "Override the hostname, the `hostname` config option will be overridden")
	raftPort := flag.Int("raft-port", 0, "Override the raft port, the `raft.port` config option will be overridden")
	protobufPort := flag.Int("protobuf-port", 0, "Override the protobuf port, the `protobuf_port` config option will be overridden")
	pidFile := flag.String("pidfile", "", "the pid file")
	repairLeveldb := flag.Bool("repair-ldb", false, "set to true to repair the leveldb files")
	stdout := flag.Bool("stdout", false, "Log to stdout overriding the configuration")
	syslog := flag.String("syslog", "", "Log to syslog facility overriding the configuration")

	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	v := fmt.Sprintf("InfluxDB v%s (git: %s) (leveldb: %d.%d)", version, gitSha, levigo.GetLevelDBMajorVersion(), levigo.GetLevelDBMinorVersion())
	if wantsVersion != nil && *wantsVersion {
		fmt.Println(v)
		return nil
	}
	config, err := configuration.LoadConfiguration(*fileName)

	if err != nil {
		return err
	}

	// override the hostname if it was specified on the command line
	if hostname != nil && *hostname != "" {
		config.Hostname = *hostname
	}

	if raftPort != nil && *raftPort != 0 {
		config.RaftServerPort = *raftPort
	}

	if protobufPort != nil && *protobufPort != 0 {
		config.ProtobufPort = *protobufPort
	}

	config.Version = v
	config.InfluxDBVersion = version

	if *stdout {
		config.LogFile = "stdout"
	}

	if *syslog != "" {
		config.LogFile = *syslog
	}

	setupLogging(config.LogLevel, config.LogFile)

	if config.RaftDebug {
		log.Info("Turning on raft debug logging")
		raft.SetLogLevel(raft.Trace)
	}

	if *repairLeveldb {
		log.Info("Repairing leveldb")
		files, err := ioutil.ReadDir(config.DataDir)
		if err != nil {
			panic(err)
		}
		o := levigo.NewOptions()
		defer o.Close()
		for _, f := range files {
			p := path.Join(config.DataDir, f.Name())
			log.Info("Repairing %s", p)
			if err := levigo.RepairDatabase(p, o); err != nil {
				panic(err)
			}
		}
	}

	if pidFile != nil && *pidFile != "" {
		pid := strconv.Itoa(os.Getpid())
		if err := ioutil.WriteFile(*pidFile, []byte(pid), 0644); err != nil {
			panic(err)
		}
	}

	if config.BindAddress == "" {
		log.Info("Starting Influx Server %s...", version)
	} else {
		log.Info("Starting Influx Server %s bound to %s...", version, config.BindAddress)
	}
	fmt.Printf(`
+---------------------------------------------+
|  _____        __ _            _____  ____   |
| |_   _|      / _| |          |  __ \|  _ \  |
|   | |  _ __ | |_| |_   ___  _| |  | | |_) | |
|   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |
|  _| |_| | | | | | | |_| |>  <| |__| | |_) | |
| |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |
+---------------------------------------------+

`)
	os.MkdirAll(config.RaftDir, 0744)
	os.MkdirAll(config.DataDir, 0744)
	server, err := server.NewServer(config)
	if err != nil {
		// sleep for the log to flush
		time.Sleep(time.Second)
		panic(err)
	}

	if err := startProfiler(server); err != nil {
		panic(err)
	}

	if *resetRootPassword {
		// TODO: make this not suck
		// This is ghetto as hell, but it'll work for now.
		go func() {
			time.Sleep(2 * time.Second) // wait for the raft server to join the cluster

			log.Warn("Resetting root's password to %s", coordinator.DEFAULT_ROOT_PWD)
			if err := server.RaftServer.CreateRootUser(); err != nil {
				panic(err)
			}
		}()
	}
	err = server.ListenAndServe()
	if err != nil {
		log.Error("ListenAndServe failed: ", err)
	}
	return err
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"net"
	"sort"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/errors"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/network"
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libnetwork"
	networktypes "github.com/docker/libnetwork/types"
	"golang.org/x/net/context"
)

// NetworkControllerEnabled checks if the networking stack is enabled.
// This feature depends on OS primitives and it's disabled in systems like Windows.
func (daemon *Daemon) NetworkControllerEnabled() bool {
	return daemon.netController != nil
}

// FindNetwork function finds a network for a given string that can represent network name or id
func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
	// Find by Name
	n, err := daemon.GetNetworkByName(idName)
	if err != nil && !isNoSuchNetworkError(err) {
		return nil, err
	}

	if n != nil {
		return n, nil
	}

	// Find by id
	return daemon.GetNetworkByID(idName)
}

func isNoSuchNetworkError(err error) bool {
	_, ok := err.(libnetwork.ErrNoSuchNetwork)
	return ok
}

// GetNetworkByID function returns a network whose ID begins with the given prefix.
// It fails with an error if no matching, or more than one matching, networks are found.
func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) {
	list := daemon.GetNetworksByID(partialID)

	if len(list) == 0 {
		return nil, libnetwork.ErrNoSuchNetwork(partialID)
	}
	if len(list) > 1 {
		return nil, libnetwork.ErrInvalidID(partialID)
	}
	return list[0], nil
}

// GetNetworkByName function returns a network for a given network name.
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
	c := daemon.netController
	if c == nil {
		return nil, libnetwork.ErrNoSuchNetwork(name)
	}
	if name == "" {
		name = c.Config().Daemon.DefaultNetwork
	}
	return c.NetworkByName(name)
}

// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
	c := daemon.netController
	if c == nil {
		return nil
	}
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		if strings.HasPrefix(nw.ID(), partialID) {
			list = append(list, nw)
		}
		return false
	}
	c.WalkNetworks(l)

	return list
}

// getAllNetworks returns a list containing all networks
func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
	c := daemon.netController
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		list = append(list, nw)
		return false
	}
	c.WalkNetworks(l)

	return list
}

func isIngressNetwork(name string) bool {
	return name == "ingress"
}

var ingressChan = make(chan struct{}, 1)

func ingressWait() func() {
	ingressChan <- struct{}{}
	return func() { <-ingressChan }
}

// SetupIngress setups ingress networking.
func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error {
	ip, _, err := net.ParseCIDR(nodeIP)
	if err != nil {
		return err
	}

	go func() {
		controller := daemon.netController
		controller.AgentInitWait()

		if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID {
			if err := controller.SandboxDestroy("ingress-sbox"); err != nil {
				logrus.Errorf("Failed to delete stale ingress sandbox: %v", err)
				return
			}

			// Cleanup any stale endpoints that might be left over during previous iterations
			epList := n.Endpoints()
			for _, ep := range epList {
				if err := ep.Delete(true); err != nil {
					logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
				}
			}

			if err := n.Delete(); err != nil {
				logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err)
				return
			}
		}

		if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
			// If it is any other error other than already
			// exists error log error and return.
			if _, ok := err.(libnetwork.NetworkNameError); !ok {
				logrus.Errorf("Failed creating ingress network: %v", err)
				return
			}

			// Otherwise continue down the call to create or recreate sandbox.
		}

		n, err := daemon.GetNetworkByID(create.ID)
		if err != nil {
			logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
			return
		}

		sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress())
		if err != nil {
			if _, ok := err.(networktypes.ForbiddenError); !ok {
				logrus.Errorf("Failed creating ingress sandbox: %v", err)
			}
			return
		}

		ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil))
		if err != nil {
			logrus.Errorf("Failed creating ingress endpoint: %v", err)
			return
		}

		if err := ep.Join(sb, nil); err != nil {
			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
		}
	}()

	return nil
}

// SetNetworkBootstrapKeys sets the bootstrap keys.
func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
	return daemon.netController.SetKeys(keys)
}

// UpdateAttachment notifies the attacher about the attachment config.
func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
	if daemon.clusterProvider == nil {
		return fmt.Errorf("cluster provider is not initialized")
	}

	if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
		return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
	}

	return nil
}

// WaitForDetachment makes the cluster manager wait for detachment of
// the container from the network.
func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
	if daemon.clusterProvider == nil {
		return fmt.Errorf("cluster provider is not initialized")
	}

	return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
}

// CreateManagedNetwork creates an agent network.
func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
	return err
}

// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
	resp, err := daemon.createNetwork(create, "", false)
	if err != nil {
		return nil, err
	}
	return resp, err
}

func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
	// If there is a pending ingress network creation wait here
	// since ingress network creation can happen via node download
	// from manager or task download.
	if isIngressNetwork(create.Name) {
		defer ingressWait()()
	}

	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
		return nil, errors.NewRequestForbiddenError(err)
	}

	var warning string
	nw, err := daemon.GetNetworkByName(create.Name)
	if err != nil {
		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
			return nil, err
		}
	}
	if nw != nil {
		if create.CheckDuplicate {
			return nil, libnetwork.NetworkNameError(create.Name)
		}
		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
	}

	c := daemon.netController
	driver := create.Driver
	if driver == "" {
		driver = c.Config().Daemon.DefaultDriver
	}

	nwOptions := []libnetwork.NetworkOption{
		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
		libnetwork.NetworkOptionDriverOpts(create.Options),
		libnetwork.NetworkOptionLabels(create.Labels),
	}

	if create.IPAM != nil {
		ipam := create.IPAM
		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
		if err != nil {
			return nil, err
		}
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
	}

	if create.Internal {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
	}
	if agent {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
	}

	if isIngressNetwork(create.Name) {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress())
	}

	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
	if err != nil {
		return nil, err
	}

	daemon.LogNetworkEvent(n, "create")
	return &types.NetworkCreateResponse{
		ID:      n.ID(),
		Warning: warning,
	}, nil
}

func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
	ipamV4Cfg := []*libnetwork.IpamConf{}
	ipamV6Cfg := []*libnetwork.IpamConf{}
	for _, d := range data {
		iCfg := libnetwork.IpamConf{}
		iCfg.PreferredPool = d.Subnet
		iCfg.SubPool = d.IPRange
		iCfg.Gateway = d.Gateway
		iCfg.AuxAddresses = d.AuxAddress
		ip, _, err := net.ParseCIDR(d.Subnet)
		if err != nil {
			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
		}
		if ip.To4() != nil {
			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
		} else {
			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
		}
	}
	return ipamV4Cfg, ipamV6Cfg, nil
}

// UpdateContainerServiceConfig updates a service configuration.
func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}

	container.NetworkSettings.Service = serviceConfig
	return nil
}

// ConnectContainerToNetwork connects the given container to the given
// network. If either cannot be found, an err is returned. If the
// network cannot be set up, an err is returned.
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}
	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
}

// DisconnectContainerFromNetwork disconnects the given container from
// the given network. If either cannot be found, an err is returned.
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		if force {
			return daemon.ForceEndpointDelete(containerName, networkName)
		}
		return err
	}
	return daemon.DisconnectFromNetwork(container, networkName, force)
}

// GetNetworkDriverList returns the list of plugins drivers
// registered for network.
func (daemon *Daemon) GetNetworkDriverList() []string {
	pluginList := []string{}
	pluginMap := make(map[string]bool)

	if !daemon.NetworkControllerEnabled() {
		return nil
	}
	networks := daemon.netController.Networks()

	for _, network := range networks {
		if !pluginMap[network.Type()] {
			pluginList = append(pluginList, network.Type())
			pluginMap[network.Type()] = true
		}
	}
	// TODO : Replace this with proper libnetwork API
	pluginList = append(pluginList, "overlay")

	sort.Strings(pluginList)

	return pluginList
}

// DeleteManagedNetwork deletes an agent network.
func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, true)
}

// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
func (daemon *Daemon) DeleteNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, false)
}

func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
	nw, err := daemon.FindNetwork(networkID)
	if err != nil {
		return err
	}

	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
		return errors.NewRequestForbiddenError(err)
	}

	if err := nw.Delete(); err != nil {
		return err
	}
	daemon.LogNetworkEvent(nw, "destroy")
	return nil
}

// GetNetworks returns a list of all networks
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
	return daemon.getAllNetworks()
}
<commit_msg>fix #26890 avoid duplicate overlay drivers in info<commit_after>package daemon

import (
	"fmt"
	"net"
	"sort"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/errors"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/network"
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libnetwork"
	networktypes "github.com/docker/libnetwork/types"
	"golang.org/x/net/context"
)

// NetworkControllerEnabled checks if the networking stack is enabled.
// This feature depends on OS primitives and it's disabled in systems like Windows.
func (daemon *Daemon) NetworkControllerEnabled() bool {
	return daemon.netController != nil
}

// FindNetwork function finds a network for a given string that can represent network name or id
func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
	// Find by Name
	n, err := daemon.GetNetworkByName(idName)
	if err != nil && !isNoSuchNetworkError(err) {
		return nil, err
	}

	if n != nil {
		return n, nil
	}

	// Find by id
	return daemon.GetNetworkByID(idName)
}

func isNoSuchNetworkError(err error) bool {
	_, ok := err.(libnetwork.ErrNoSuchNetwork)
	return ok
}

// GetNetworkByID function returns a network whose ID begins with the given prefix.
// It fails with an error if no matching, or more than one matching, networks are found.
func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) {
	list := daemon.GetNetworksByID(partialID)

	if len(list) == 0 {
		return nil, libnetwork.ErrNoSuchNetwork(partialID)
	}
	if len(list) > 1 {
		return nil, libnetwork.ErrInvalidID(partialID)
	}
	return list[0], nil
}

// GetNetworkByName function returns a network for a given network name.
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
	c := daemon.netController
	if c == nil {
		return nil, libnetwork.ErrNoSuchNetwork(name)
	}
	if name == "" {
		name = c.Config().Daemon.DefaultNetwork
	}
	return c.NetworkByName(name)
}

// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
	c := daemon.netController
	if c == nil {
		return nil
	}
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		if strings.HasPrefix(nw.ID(), partialID) {
			list = append(list, nw)
		}
		return false
	}
	c.WalkNetworks(l)

	return list
}

// getAllNetworks returns a list containing all networks
func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
	c := daemon.netController
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		list = append(list, nw)
		return false
	}
	c.WalkNetworks(l)

	return list
}

func isIngressNetwork(name string) bool {
	return name == "ingress"
}

var ingressChan = make(chan struct{}, 1)

func ingressWait() func() {
	ingressChan <- struct{}{}
	return func() { <-ingressChan }
}

// SetupIngress setups ingress networking.
func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error {
	ip, _, err := net.ParseCIDR(nodeIP)
	if err != nil {
		return err
	}

	go func() {
		controller := daemon.netController
		controller.AgentInitWait()

		if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID {
			if err := controller.SandboxDestroy("ingress-sbox"); err != nil {
				logrus.Errorf("Failed to delete stale ingress sandbox: %v", err)
				return
			}

			// Cleanup any stale endpoints that might be left over during previous iterations
			epList := n.Endpoints()
			for _, ep := range epList {
				if err := ep.Delete(true); err != nil {
					logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
				}
			}

			if err := n.Delete(); err != nil {
				logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err)
				return
			}
		}

		if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
			// If it is any other error other than already
			// exists error log error and return.
			if _, ok := err.(libnetwork.NetworkNameError); !ok {
				logrus.Errorf("Failed creating ingress network: %v", err)
				return
			}

			// Otherwise continue down the call to create or recreate sandbox.
		}

		n, err := daemon.GetNetworkByID(create.ID)
		if err != nil {
			logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
			return
		}

		sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress())
		if err != nil {
			if _, ok := err.(networktypes.ForbiddenError); !ok {
				logrus.Errorf("Failed creating ingress sandbox: %v", err)
			}
			return
		}

		ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil))
		if err != nil {
			logrus.Errorf("Failed creating ingress endpoint: %v", err)
			return
		}

		if err := ep.Join(sb, nil); err != nil {
			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
		}
	}()

	return nil
}

// SetNetworkBootstrapKeys sets the bootstrap keys.
func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
	return daemon.netController.SetKeys(keys)
}

// UpdateAttachment notifies the attacher about the attachment config.
func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
	if daemon.clusterProvider == nil {
		return fmt.Errorf("cluster provider is not initialized")
	}

	if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
		return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
	}

	return nil
}

// WaitForDetachment makes the cluster manager wait for detachment of
// the container from the network.
func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
	if daemon.clusterProvider == nil {
		return fmt.Errorf("cluster provider is not initialized")
	}

	return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
}

// CreateManagedNetwork creates an agent network.
func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
	return err
}

// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
	resp, err := daemon.createNetwork(create, "", false)
	if err != nil {
		return nil, err
	}
	return resp, err
}

func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
	// If there is a pending ingress network creation wait here
	// since ingress network creation can happen via node download
	// from manager or task download.
	if isIngressNetwork(create.Name) {
		defer ingressWait()()
	}

	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
		return nil, errors.NewRequestForbiddenError(err)
	}

	var warning string
	nw, err := daemon.GetNetworkByName(create.Name)
	if err != nil {
		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
			return nil, err
		}
	}
	if nw != nil {
		if create.CheckDuplicate {
			return nil, libnetwork.NetworkNameError(create.Name)
		}
		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
	}

	c := daemon.netController
	driver := create.Driver
	if driver == "" {
		driver = c.Config().Daemon.DefaultDriver
	}

	nwOptions := []libnetwork.NetworkOption{
		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
		libnetwork.NetworkOptionDriverOpts(create.Options),
		libnetwork.NetworkOptionLabels(create.Labels),
	}

	if create.IPAM != nil {
		ipam := create.IPAM
		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
		if err != nil {
			return nil, err
		}
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
	}

	if create.Internal {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
	}
	if agent {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
	}

	if isIngressNetwork(create.Name) {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress())
	}

	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
	if err != nil {
		return nil, err
	}

	daemon.LogNetworkEvent(n, "create")
	return &types.NetworkCreateResponse{
		ID:      n.ID(),
		Warning: warning,
	}, nil
}

func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
	ipamV4Cfg := []*libnetwork.IpamConf{}
	ipamV6Cfg := []*libnetwork.IpamConf{}
	for _, d := range data {
		iCfg := libnetwork.IpamConf{}
		iCfg.PreferredPool = d.Subnet
		iCfg.SubPool = d.IPRange
		iCfg.Gateway = d.Gateway
		iCfg.AuxAddresses = d.AuxAddress
		ip, _, err := net.ParseCIDR(d.Subnet)
		if err != nil {
			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
		}
		if ip.To4() != nil {
			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
		} else {
			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
		}
	}
	return ipamV4Cfg, ipamV6Cfg, nil
}

// UpdateContainerServiceConfig updates a service configuration.
func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}

	container.NetworkSettings.Service = serviceConfig
	return nil
}

// ConnectContainerToNetwork connects the given container to the given
// network. If either cannot be found, an err is returned. If the
// network cannot be set up, an err is returned.
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}
	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
}

// DisconnectContainerFromNetwork disconnects the given container from
// the given network. If either cannot be found, an err is returned.
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		if force {
			return daemon.ForceEndpointDelete(containerName, networkName)
		}
		return err
	}
	return daemon.DisconnectFromNetwork(container, networkName, force)
}

// GetNetworkDriverList returns the list of plugins drivers
// registered for network.
func (daemon *Daemon) GetNetworkDriverList() []string {
	if !daemon.NetworkControllerEnabled() {
		return nil
	}

	// TODO: Replace this with proper libnetwork API
	pluginList := []string{"overlay"}
	pluginMap := map[string]bool{"overlay": true}

	networks := daemon.netController.Networks()

	for _, network := range networks {
		if !pluginMap[network.Type()] {
			pluginList = append(pluginList, network.Type())
			pluginMap[network.Type()] = true
		}
	}

	sort.Strings(pluginList)

	return pluginList
}

// DeleteManagedNetwork deletes an agent network.
func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, true)
}

// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
func (daemon *Daemon) DeleteNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, false)
}

func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
	nw, err := daemon.FindNetwork(networkID)
	if err != nil {
		return err
	}

	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
		return errors.NewRequestForbiddenError(err)
	}

	if err := nw.Delete(); err != nil {
		return err
	}
	daemon.LogNetworkEvent(nw, "destroy")
	return nil
}

// GetNetworks returns a list of all networks
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
	return daemon.getAllNetworks()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"
//	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"testing"
)

// anonymous declarations to squash import errors for testing
var _ string = fmt.Sprint()
var _ []string = os.Args

func TestBalance(t *testing.T) {
	fmt.Printf("TestJson\n===\n")
	type balance struct {
		Publickey string
		Credits float64
	}
	server := "http://demo.factom.org:8088/v1/creditbalance"

	data := url.Values{
		"pubkey": {"wallet"},
	}

	resp, err := http.PostForm(server, data)
	if err != nil {
		t.Errorf(err.Error())
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	for {
		var bal balance
		if err := dec.Decode(&bal); err == io.EOF {
			break
		} else if err != nil {
			t.Errorf(err.Error())
		}
		fmt.Println("Entry Credit Balance:", bal.Credits)
	}
}
<commit_msg>updated test<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
//	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"testing"
)

// anonymous declarations to squash import errors for testing
var _ string = fmt.Sprint()
var _ []string = os.Args

func TestBalance(t *testing.T) {
	fmt.Printf("TestBalance\n===\n")
	type balance struct {
		Publickey string
		Credits float64
	}
	server := "http://demo.factom.org:8088/v1/creditbalance"

	data := url.Values{
		"pubkey": {"wallet"},
	}

	resp, err := http.PostForm(server, data)
	if err != nil {
		t.Errorf(err.Error())
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	for {
		var bal balance
		if err := dec.Decode(&bal); err == io.EOF {
			break
		} else if err != nil {
			t.Errorf(err.Error())
		}
		fmt.Println("Entry Credit Balance:", bal.Credits)
	}
}
<|endoftext|>


<commit_before>// Tuple objects

package py

var TupleType = ObjectType.NewType("tuple", "tuple() -> empty tuple\ntuple(iterable) -> tuple initialized from iterable's items\n\nIf the argument is a tuple, the return value is the same object.", TupleNew, nil)

type Tuple []Object

// Type of this Tuple object
func (o Tuple) Type() *Type {
	return TupleType
}

// TupleNew
func TupleNew(metatype *Type, args Tuple, kwargs StringDict) (res Object) {
	var iterable Object
	UnpackTuple(args, kwargs, "tuple", 0, 1, &iterable)
	if iterable != nil {
		return SequenceTuple(iterable)
	}
	return Tuple{}
}

// Copy a tuple object
func (t Tuple) Copy() Tuple {
	newT := make(Tuple, len(t))
	copy(newT, t)
	return newT
}
func (t Tuple) M__len__() Object {
	return Int(len(t))
}

func (t Tuple) M__bool__() Object {
	return NewBool(len(t) > 0)
}

func (t Tuple) M__iter__() Object {
	return NewIterator(t)
}

func (t Tuple) M__getitem__(key Object) Object {
	if slice, ok := key.(*Slice); ok {
		start, stop, step, slicelength := slice.GetIndices(len(t))
		if step == 1 {
			// Return a subslice since tuples are immutable
			return t[start:stop]
		}
		newTuple := make(Tuple, slicelength)
		for i, j := start, 0; j < slicelength; i, j = i+step, j+1 {
			newTuple[j] = t[i]
		}
		return newTuple
	}
	i := IndexIntCheck(key, len(t))
	return t[i]
}

func (a Tuple) M__add__(other Object) Object {
	if b, ok := other.(Tuple); ok {
		newTuple := make(Tuple, len(a)+len(b))
		copy(newTuple, a)
		copy(newTuple[len(b):], b)
		return newTuple
	}
	return NotImplemented
}

func (a Tuple) M__radd__(other Object) Object {
	if b, ok := other.(Tuple); ok {
		return b.M__add__(a)
	}
	return NotImplemented
}

func (a Tuple) M__iadd__(other Object) Object {
	return a.M__add__(other)
}

func (l Tuple) M__mul__(other Object) Object {
	if b, ok := convertToInt(other); ok {
		m := len(l)
		n := int(b) * m
		newTuple := make(Tuple, n)
		for i := 0; i < n; i += m {
			copy(newTuple[i:i+m], l)
		}
		return newTuple
	}
	return NotImplemented
}

func (a Tuple) M__rmul__(other Object) Object {
	return a.M__mul__(other)
}

func (a Tuple) M__imul__(other Object) Object {
	return a.M__mul__(other)
}

// Check interface is satisfied
var _ sequenceArithmetic = Tuple(nil)
var _ I__len__ = Tuple(nil)
var _ I__bool__ = Tuple(nil)
var _ I__iter__ = Tuple(nil)
var _ I__getitem__ = Tuple(nil)

// var _ richComparison = Tuple(nil)

func (a Tuple) M__eq__(other Object) Object {
	b, ok := other.(Tuple)
	if !ok {
		return NotImplemented
	}
	if len(a) != len(b) {
		return False
	}
	for i := range a {
		if Eq(a[i], b[i]) == False {
			return False
		}
	}
	return True
}

func (a Tuple) M__ne__(other Object) Object {
	b, ok := other.(Tuple)
	if !ok {
		return NotImplemented
	}
	if len(a) != len(b) {
		return True
	}
	for i := range a {
		if Eq(a[i], b[i]) == False {
			return True
		}
	}
	return False
}
<commit_msg>py: tuple - Reverse method<commit_after>// Tuple objects

package py

var TupleType = ObjectType.NewType("tuple", "tuple() -> empty tuple\ntuple(iterable) -> tuple initialized from iterable's items\n\nIf the argument is a tuple, the return value is the same object.", TupleNew, nil)

type Tuple []Object

// Type of this Tuple object
func (o Tuple) Type() *Type {
	return TupleType
}

// TupleNew
func TupleNew(metatype *Type, args Tuple, kwargs StringDict) (res Object) {
	var iterable Object
	UnpackTuple(args, kwargs, "tuple", 0, 1, &iterable)
	if iterable != nil {
		return SequenceTuple(iterable)
	}
	return Tuple{}
}

// Copy a tuple object
func (t Tuple) Copy() Tuple {
	newT := make(Tuple, len(t))
	copy(newT, t)
	return newT
}

// Reverses a tuple (in-place)
func (t Tuple) Reverse() {
	for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
		t[i], t[j] = t[j], t[i]
	}
}

func (t Tuple) M__len__() Object {
	return Int(len(t))
}

func (t Tuple) M__bool__() Object {
	return NewBool(len(t) > 0)
}

func (t Tuple) M__iter__() Object {
	return NewIterator(t)
}

func (t Tuple) M__getitem__(key Object) Object {
	if slice, ok := key.(*Slice); ok {
		start, stop, step, slicelength := slice.GetIndices(len(t))
		if step == 1 {
			// Return a subslice since tuples are immutable
			return t[start:stop]
		}
		newTuple := make(Tuple, slicelength)
		for i, j := start, 0; j < slicelength; i, j = i+step, j+1 {
			newTuple[j] = t[i]
		}
		return newTuple
	}
	i := IndexIntCheck(key, len(t))
	return t[i]
}

func (a Tuple) M__add__(other Object) Object {
	if b, ok := other.(Tuple); ok {
		newTuple := make(Tuple, len(a)+len(b))
		copy(newTuple, a)
		copy(newTuple[len(b):], b)
		return newTuple
	}
	return NotImplemented
}

func (a Tuple) M__radd__(other Object) Object {
	if b, ok := other.(Tuple); ok {
		return b.M__add__(a)
	}
	return NotImplemented
}

func (a Tuple) M__iadd__(other Object) Object {
	return a.M__add__(other)
}

func (l Tuple) M__mul__(other Object) Object {
	if b, ok := convertToInt(other); ok {
		m := len(l)
		n := int(b) * m
		newTuple := make(Tuple, n)
		for i := 0; i < n; i += m {
			copy(newTuple[i:i+m], l)
		}
		return newTuple
	}
	return NotImplemented
}

func (a Tuple) M__rmul__(other Object) Object {
	return a.M__mul__(other)
}

func (a Tuple) M__imul__(other Object) Object {
	return a.M__mul__(other)
}

// Check interface is satisfied
var _ sequenceArithmetic = Tuple(nil)
var _ I__len__ = Tuple(nil)
var _ I__bool__ = Tuple(nil)
var _ I__iter__ = Tuple(nil)
var _ I__getitem__ = Tuple(nil)

// var _ richComparison = Tuple(nil)

func (a Tuple) M__eq__(other Object) Object {
	b, ok := other.(Tuple)
	if !ok {
		return NotImplemented
	}
	if len(a) != len(b) {
		return False
	}
	for i := range a {
		if Eq(a[i], b[i]) == False {
			return False
		}
	}
	return True
}

func (a Tuple) M__ne__(other Object) Object {
	b, ok := other.(Tuple)
	if !ok {
		return NotImplemented
	}
	if len(a) != len(b) {
		return True
	}
	for i := range a {
		if Eq(a[i], b[i]) == False {
			return True
		}
	}
	return False
}
<|endoftext|>


<commit_before><commit_msg>Use govalidator<commit_after><|endoftext|>