<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/google/gops/internal"
	"github.com/google/gops/signal"
	"github.com/pkg/errors"
)

var cmds = map[string](func(addr net.TCPAddr) error){
	"stack":      stackTrace,
	"gc":         gc,
	"memstats":   memStats,
	"version":    version,
	"pprof-heap": pprofHeap,
	"pprof-cpu":  pprofCPU,
	"stats":      stats,
	"trace":      trace,
}

func stackTrace(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.StackTrace)
}

func gc(addr net.TCPAddr) error {
	_, err := cmd(addr, signal.GC)
	return err
}

func memStats(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.MemStats)
}

func version(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.Version)
}

func pprofHeap(addr net.TCPAddr) error {
	return pprof(addr, signal.HeapProfile)
}

func pprofCPU(addr net.TCPAddr) error {
	fmt.Println("Profiling CPU now, will take 30 secs...")
	return pprof(addr, signal.CPUProfile)
}

func trace(addr net.TCPAddr) error {
	fmt.Println("Tracing now, will take 5 secs...")
	out, err := cmd(addr, signal.Trace)
	if err != nil {
		return err
	}
	if len(out) == 0 {
		return errors.New("nothing has traced")
	}
	tmpfile, err := ioutil.TempFile("", "trace")
	if err != nil {
		return err
	}
	defer os.Remove(tmpfile.Name())
	if err := ioutil.WriteFile(tmpfile.Name(), out, 0); err != nil {
		return err
	}
	cmd := exec.Command("go", "tool", "trace", tmpfile.Name())
	cmd.Env = os.Environ()
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func pprof(addr net.TCPAddr, p byte) error {

	tmpDumpFile, err := ioutil.TempFile("", "profile")
	if err != nil {
		return err
	}
	{
		out, err := cmd(addr, p)
		if err != nil {
			return err
		}
		if len(out) == 0 {
			return errors.New("failed to read the profile")
		}
		defer os.Remove(tmpDumpFile.Name())
		if err := ioutil.WriteFile(tmpDumpFile.Name(), out, 0); err != nil {
			return err
		}
	}
	// Download running binary
	tmpBinFile, err := ioutil.TempFile("", "binary")
	if err != nil {
		return err
	}
	{

		out, err := cmd(addr, signal.BinaryDump)
		if err != nil {
			return errors.New("couldn't retrieve running binary's dump")
		}
		if len(out) == 0 {
			return errors.New("failed to read the binary")
		}
		defer os.Remove(tmpBinFile.Name())
		if err := ioutil.WriteFile(tmpBinFile.Name(), out, 0); err != nil {
			return err
		}
	}
	cmd := exec.Command("go", "tool", "pprof", tmpBinFile.Name(), tmpDumpFile.Name())
	cmd.Env = os.Environ()
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func stats(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.Stats)
}

func cmdWithPrint(addr net.TCPAddr, c byte) error {
	out, err := cmd(addr, c)
	if err != nil {
		return err
	}
	fmt.Printf("%s", out)
	return nil
}

// targetToAddr tries to parse the target string, be it remote host:port
// or local process's PID.
func targetToAddr(target string) (*net.TCPAddr, error) {
	if strings.Index(target, ":") != -1 {
		// addr host:port passed
		var err error
		addr, err := net.ResolveTCPAddr("tcp", target)
		if err != nil {
			return nil, errors.Wrap(err, "couldn't parse dst address")
		}
		return addr, nil
	}
	// try to find port by pid then, connect to local
	pid, err := strconv.Atoi(target)
	if err != nil {
		return nil, errors.Wrap(err, "couldn't parse PID")
	}
	port, err := internal.GetPort(pid)
	addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:"+port)
	return addr, nil
}

func cmd(addr net.TCPAddr, c byte) ([]byte, error) {
	conn, err := cmdLazy(addr, c)
	if err != nil {
		return nil, errors.Wrap(err, "couldn't get port by PID")
	}

	all, err := ioutil.ReadAll(conn)
	if err != nil {
		return nil, err
	}
	return all, nil
}

func cmdLazy(addr net.TCPAddr, c byte) (io.Reader, error) {
	conn, err := net.DialTCP("tcp", nil, &addr)
	if err != nil {
		return nil, err
	}
	if _, err := conn.Write([]byte{c}); err != nil {
		return nil, err
	}
	return conn, nil
}
<commit_msg>remove dependencies to github.com/pkg/errors<commit_after>package main

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/google/gops/internal"
	"github.com/google/gops/signal"
)

var cmds = map[string](func(addr net.TCPAddr) error){
	"stack":      stackTrace,
	"gc":         gc,
	"memstats":   memStats,
	"version":    version,
	"pprof-heap": pprofHeap,
	"pprof-cpu":  pprofCPU,
	"stats":      stats,
	"trace":      trace,
}

func stackTrace(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.StackTrace)
}

func gc(addr net.TCPAddr) error {
	_, err := cmd(addr, signal.GC)
	return err
}

func memStats(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.MemStats)
}

func version(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.Version)
}

func pprofHeap(addr net.TCPAddr) error {
	return pprof(addr, signal.HeapProfile)
}

func pprofCPU(addr net.TCPAddr) error {
	fmt.Println("Profiling CPU now, will take 30 secs...")
	return pprof(addr, signal.CPUProfile)
}

func trace(addr net.TCPAddr) error {
	fmt.Println("Tracing now, will take 5 secs...")
	out, err := cmd(addr, signal.Trace)
	if err != nil {
		return err
	}
	if len(out) == 0 {
		return errors.New("nothing has traced")
	}
	tmpfile, err := ioutil.TempFile("", "trace")
	if err != nil {
		return err
	}
	defer os.Remove(tmpfile.Name())
	if err := ioutil.WriteFile(tmpfile.Name(), out, 0); err != nil {
		return err
	}
	cmd := exec.Command("go", "tool", "trace", tmpfile.Name())
	cmd.Env = os.Environ()
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func pprof(addr net.TCPAddr, p byte) error {

	tmpDumpFile, err := ioutil.TempFile("", "profile")
	if err != nil {
		return err
	}
	{
		out, err := cmd(addr, p)
		if err != nil {
			return err
		}
		if len(out) == 0 {
			return errors.New("failed to read the profile")
		}
		defer os.Remove(tmpDumpFile.Name())
		if err := ioutil.WriteFile(tmpDumpFile.Name(), out, 0); err != nil {
			return err
		}
	}
	// Download running binary
	tmpBinFile, err := ioutil.TempFile("", "binary")
	if err != nil {
		return err
	}
	{
		out, err := cmd(addr, signal.BinaryDump)
		if err != nil {
			return fmt.Errorf("failed to read the binary: %v", err)
		}
		if len(out) == 0 {
			return errors.New("failed to read the binary")
		}
		defer os.Remove(tmpBinFile.Name())
		if err := ioutil.WriteFile(tmpBinFile.Name(), out, 0); err != nil {
			return err
		}
	}
	cmd := exec.Command("go", "tool", "pprof", tmpBinFile.Name(), tmpDumpFile.Name())
	cmd.Env = os.Environ()
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func stats(addr net.TCPAddr) error {
	return cmdWithPrint(addr, signal.Stats)
}

func cmdWithPrint(addr net.TCPAddr, c byte) error {
	out, err := cmd(addr, c)
	if err != nil {
		return err
	}
	fmt.Printf("%s", out)
	return nil
}

// targetToAddr tries to parse the target string, be it remote host:port
// or local process's PID.
func targetToAddr(target string) (*net.TCPAddr, error) {
	if strings.Index(target, ":") != -1 {
		// addr host:port passed
		var err error
		addr, err := net.ResolveTCPAddr("tcp", target)
		if err != nil {
			return nil, fmt.Errorf("couldn't parse dst address: %v", err)
		}
		return addr, nil
	}
	// try to find port by pid then, connect to local
	pid, err := strconv.Atoi(target)
	if err != nil {
		return nil, fmt.Errorf("couldn't parse PID: %v", err)
	}
	port, err := internal.GetPort(pid)
	addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:"+port)
	return addr, nil
}

func cmd(addr net.TCPAddr, c byte) ([]byte, error) {
	conn, err := cmdLazy(addr, c)
	if err != nil {
		return nil, fmt.Errorf("couldn't get port by PID: %v", err)
	}

	all, err := ioutil.ReadAll(conn)
	if err != nil {
		return nil, err
	}
	return all, nil
}

func cmdLazy(addr net.TCPAddr, c byte) (io.Reader, error) {
	conn, err := net.DialTCP("tcp", nil, &addr)
	if err != nil {
		return nil, err
	}
	if _, err := conn.Write([]byte{c}); err != nil {
		return nil, err
	}
	return conn, nil
}
<|endoftext|>


<commit_before>// Kindle Clippings reads the clippings file from a Kindle and output them as
// json.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"hawx.me/code/kindle-tools/kindle-clippings/clippings"
)

var (
	onlyType = flag.String("only", "", "")
)

const helpMsg = `Usage: kindle-clippings PATH [--only TYPE]

  Reads clippings from your Kindle and outputs them in json format to Stdout.

 PATH
     Path to Kindle, for example /media/johndoe/Kindle or /Volumes/Kindle.

 --only TYPE
     Only list items of the given type (Bookmark, Note or Highlight)
`

func main() {
	flag.Usage = func() {
		fmt.Println(helpMsg)
	}
	flag.Parse()

	if len(flag.Args()) != 1 {
		fmt.Println(helpMsg)
		return
	}

	path := filepath.Join(flag.Arg(0), "documents/My Clippings.txt")

	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	r := clippings.NewReader(file)
	items, err := r.ReadAll()
	if err != nil {
		fmt.Println("err: %v", err)
		return
	}

	if *onlyType != "" {
		var filtered []clippings.Clipping

		for _, item := range items {
			if item.Type == *onlyType {
				filtered = append(filtered, item)
			}
		}

		items = filtered
	}

	json.NewEncoder(os.Stdout).Encode(items)
}
<commit_msg>Add some more to package doc<commit_after>// Kindle Clippings reads the clippings file from a Kindle and output them as
// json.
//
// Usage:
//
//     kindle-clippings PATH [--only TYPE]
//
// where PATH is the path to the mounted Kindle. Json output is written to
// Stdout.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"hawx.me/code/kindle-tools/kindle-clippings/clippings"
)

var (
	onlyType = flag.String("only", "", "")
)

const helpMsg = `Usage: kindle-clippings PATH [--only TYPE]

  Reads clippings from your Kindle and outputs them in json format to Stdout.

 PATH
     Path to Kindle, for example /media/johndoe/Kindle or /Volumes/Kindle.

 --only TYPE
     Only list items of the given type (Bookmark, Note or Highlight)
`

func main() {
	flag.Usage = func() {
		fmt.Println(helpMsg)
	}
	flag.Parse()

	if len(flag.Args()) != 1 {
		fmt.Println(helpMsg)
		return
	}

	path := filepath.Join(flag.Arg(0), "documents/My Clippings.txt")

	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	r := clippings.NewReader(file)
	items, err := r.ReadAll()
	if err != nil {
		fmt.Println("err: %v", err)
		return
	}

	if *onlyType != "" {
		var filtered []clippings.Clipping

		for _, item := range items {
			if item.Type == *onlyType {
				filtered = append(filtered, item)
			}
		}

		items = filtered
	}

	json.NewEncoder(os.Stdout).Encode(items)
}
<|endoftext|>


<commit_before>package runner

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"
)

var (
	chunkSize = 4096
)

type WrappedCommand struct {
	Name      string
	Cmd       *exec.Cmd
	LogSource *LogSource
	ChunkChan chan LogChunk
	Output    []byte // buffered output if requested
}

// A wrapped command will ensure that all stdin/out/err gets piped
// into a buffer that can then be reported upstream to the Changes
// master server
func NewWrappedCommand(cmd *exec.Cmd) (*WrappedCommand, error) {
	return &WrappedCommand{
		Cmd:       cmd,
		ChunkChan: make(chan LogChunk),
	}, nil
}

// Build a new WrappedCommand out of an arbitrary script
// The script is written to disk and then executed ensuring that it can
// be fairly arbitrary and provide its own shebang
func NewWrappedScriptCommand(script string, name string) (*WrappedCommand, error) {
	f, err := ioutil.TempFile("", "script-")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	_, err = f.WriteString(script)
	if err != nil {
		return nil, err
	}

	info, err := f.Stat()
	if err != nil {
		return nil, err
	}

	err = f.Chmod((info.Mode() & os.ModePerm) | 0111)
	if err != nil {
		return nil, err
	}

	wc, err := NewWrappedCommand(exec.Command(f.Name()))
	wc.Name = name
	return wc, err
}

func (wc *WrappedCommand) CombinedOutputPipe() (io.ReadCloser, io.WriteCloser) {
	c := wc.Cmd

	pr, pw := io.Pipe()

	c.Stdout = pw
	c.Stderr = pw

	return pr, pw
}

func (wc *WrappedCommand) GetLabel() string {
	if wc.Name != "" {
		return wc.Name
	} else {
		return strings.Join(wc.Cmd.Args, " ")
	}
}

func (wc *WrappedCommand) Run(bufferOutput bool) (*os.ProcessState, error) {
	var err error

	defer close(wc.ChunkChan)

    stdin, err := wc.Cmd.StdinPipe()
    if err != nil {
        return nil, err
    }

	cmdreader, cmdwriter := wc.CombinedOutputPipe()

	cmdname := wc.GetLabel()
	log.Printf("[cmd] Executing %s", cmdname)
	processMessage(wc.ChunkChan, fmt.Sprintf(">> %s", cmdname))

	var buffer *bytes.Buffer
	var reader io.Reader = cmdreader

	// If user has requested to buffer command output, tee output to in memory buffer.
	if bufferOutput {
		buffer = &bytes.Buffer{}
		reader = io.TeeReader(cmdreader, buffer)
	}

	err = wc.Cmd.Start()

	if err != nil {
		log.Printf("[cmd] Start failed %s %s", wc.Cmd.Args, err.Error())
		processMessage(wc.ChunkChan, err.Error())
		return nil, err
	}

	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		processChunks(wc.ChunkChan, reader)
		log.Printf("[cmd] Stdout processed %s", wc.Cmd.Args)
		wg.Done()
	}()

	err = wc.Cmd.Wait()
	cmdwriter.Close()

	stdin.Close()

	wg.Wait()

	if err != nil {
		return nil, err
	}

	if bufferOutput {
		wc.Output = buffer.Bytes()
	}

	return wc.Cmd.ProcessState, nil
}

func processMessage(out chan LogChunk, payload string) {
	out <- LogChunk{
		Length:  len(payload),
		Payload: []byte(fmt.Sprintf("%s\n", payload)),
	}
}

type LogLine struct {
	line []byte
	err  error
}

func newLogLineReader(pipe io.Reader) <-chan *LogLine {
	r := bufio.NewReader(pipe)
	ch := make(chan *LogLine)

	go func() {
		for {
			line, err := r.ReadBytes('\n')
			l := &LogLine{line: line, err: err}
			ch <- l

			if err != nil {
				return
			}
		}
	}()

	return ch
}

func processChunks(out chan LogChunk, pipe io.Reader) {
	lines := newLogLineReader(pipe)

	finished := false
	for !finished {
		var payload []byte
		timeLimit := time.After(2 * time.Second)

		for len(payload) < chunkSize {
			var logLine *LogLine
			timeLimitExceeded := false

			select {
			case logLine = <-lines:
			case <-timeLimit:
				timeLimitExceeded = true
			}

			if timeLimitExceeded {
				break
			}

			payload = append(payload, logLine.line...)
			if logLine.err == io.EOF {
				finished = true
				break
			}

			if logLine.err != nil {
				finished = true
				line := []byte(fmt.Sprintf("%s", logLine.err))
				payload = append(payload, line...)
				break
			}
		}

		if len(payload) > 0 {
			l := LogChunk{
				Length:  len(payload),
				Payload: payload,
			}

			out <- l
		}
	}
}

func init() {
	flag.IntVar(&chunkSize, "log_chunk_size", 4096, "Size of log chunks to send to http server")
}
<commit_msg>go fmt<commit_after>package runner

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"
)

var (
	chunkSize = 4096
)

type WrappedCommand struct {
	Name      string
	Cmd       *exec.Cmd
	LogSource *LogSource
	ChunkChan chan LogChunk
	Output    []byte // buffered output if requested
}

// A wrapped command will ensure that all stdin/out/err gets piped
// into a buffer that can then be reported upstream to the Changes
// master server
func NewWrappedCommand(cmd *exec.Cmd) (*WrappedCommand, error) {
	return &WrappedCommand{
		Cmd:       cmd,
		ChunkChan: make(chan LogChunk),
	}, nil
}

// Build a new WrappedCommand out of an arbitrary script
// The script is written to disk and then executed ensuring that it can
// be fairly arbitrary and provide its own shebang
func NewWrappedScriptCommand(script string, name string) (*WrappedCommand, error) {
	f, err := ioutil.TempFile("", "script-")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	_, err = f.WriteString(script)
	if err != nil {
		return nil, err
	}

	info, err := f.Stat()
	if err != nil {
		return nil, err
	}

	err = f.Chmod((info.Mode() & os.ModePerm) | 0111)
	if err != nil {
		return nil, err
	}

	wc, err := NewWrappedCommand(exec.Command(f.Name()))
	wc.Name = name
	return wc, err
}

func (wc *WrappedCommand) CombinedOutputPipe() (io.ReadCloser, io.WriteCloser) {
	c := wc.Cmd

	pr, pw := io.Pipe()

	c.Stdout = pw
	c.Stderr = pw

	return pr, pw
}

func (wc *WrappedCommand) GetLabel() string {
	if wc.Name != "" {
		return wc.Name
	} else {
		return strings.Join(wc.Cmd.Args, " ")
	}
}

func (wc *WrappedCommand) Run(bufferOutput bool) (*os.ProcessState, error) {
	var err error

	defer close(wc.ChunkChan)

	stdin, err := wc.Cmd.StdinPipe()
	if err != nil {
		return nil, err
	}

	cmdreader, cmdwriter := wc.CombinedOutputPipe()

	cmdname := wc.GetLabel()
	log.Printf("[cmd] Executing %s", cmdname)
	processMessage(wc.ChunkChan, fmt.Sprintf(">> %s", cmdname))

	var buffer *bytes.Buffer
	var reader io.Reader = cmdreader

	// If user has requested to buffer command output, tee output to in memory buffer.
	if bufferOutput {
		buffer = &bytes.Buffer{}
		reader = io.TeeReader(cmdreader, buffer)
	}

	err = wc.Cmd.Start()

	if err != nil {
		log.Printf("[cmd] Start failed %s %s", wc.Cmd.Args, err.Error())
		processMessage(wc.ChunkChan, err.Error())
		return nil, err
	}

	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		processChunks(wc.ChunkChan, reader)
		log.Printf("[cmd] Stdout processed %s", wc.Cmd.Args)
		wg.Done()
	}()

	err = wc.Cmd.Wait()
	cmdwriter.Close()

	stdin.Close()

	wg.Wait()

	if err != nil {
		return nil, err
	}

	if bufferOutput {
		wc.Output = buffer.Bytes()
	}

	return wc.Cmd.ProcessState, nil
}

func processMessage(out chan LogChunk, payload string) {
	out <- LogChunk{
		Length:  len(payload),
		Payload: []byte(fmt.Sprintf("%s\n", payload)),
	}
}

type LogLine struct {
	line []byte
	err  error
}

func newLogLineReader(pipe io.Reader) <-chan *LogLine {
	r := bufio.NewReader(pipe)
	ch := make(chan *LogLine)

	go func() {
		for {
			line, err := r.ReadBytes('\n')
			l := &LogLine{line: line, err: err}
			ch <- l

			if err != nil {
				return
			}
		}
	}()

	return ch
}

func processChunks(out chan LogChunk, pipe io.Reader) {
	lines := newLogLineReader(pipe)

	finished := false
	for !finished {
		var payload []byte
		timeLimit := time.After(2 * time.Second)

		for len(payload) < chunkSize {
			var logLine *LogLine
			timeLimitExceeded := false

			select {
			case logLine = <-lines:
			case <-timeLimit:
				timeLimitExceeded = true
			}

			if timeLimitExceeded {
				break
			}

			payload = append(payload, logLine.line...)
			if logLine.err == io.EOF {
				finished = true
				break
			}

			if logLine.err != nil {
				finished = true
				line := []byte(fmt.Sprintf("%s", logLine.err))
				payload = append(payload, line...)
				break
			}
		}

		if len(payload) > 0 {
			l := LogChunk{
				Length:  len(payload),
				Payload: payload,
			}

			out <- l
		}
	}
}

func init() {
	flag.IntVar(&chunkSize, "log_chunk_size", 4096, "Size of log chunks to send to http server")
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016 Intel Corporation
//
// 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 virtcontainers

import (
	"net"

	"github.com/01org/ciao/ssntp/uuid"
	"github.com/containernetworking/cni/pkg/ns"
	types "github.com/containernetworking/cni/pkg/types/current"
)

// cnm is a network implementation for the CNM plugin.
type cnm struct {
	config NetworkConfig
}

func (n *cnm) createResult(iface net.Interface, addrs []net.Addr) (types.Result, error) {
	var ipConfigs []*types.IPConfig
	for _, addr := range addrs {
		ip, ipNet, err := net.ParseCIDR(addr.String())
		if err != nil {
			return types.Result{}, err
		}

		version := "6"
		if ip.To4() != nil {
			version = "4"
		}
		ipNet.IP = ip

		ipConfig := &types.IPConfig{
			Version:   version,
			Interface: iface.Index,
			Address:   *ipNet,
		}

		ipConfigs = append(ipConfigs, ipConfig)
	}

	ifaceList := []*types.Interface{
		{
			Name: iface.Name,
			Mac:  iface.HardwareAddr.String(),
		},
	}

	res := types.Result{
		Interfaces: ifaceList,
		IPs:        ipConfigs,
	}

	return res, nil
}

func (n *cnm) createEndpointsFromScan() ([]Endpoint, error) {
	var endpoints []Endpoint

	ifaces, err := net.Interfaces()
	if err != nil {
		return []Endpoint{}, err
	}

	uniqueID := uuid.Generate().String()

	idx := 0
	for _, iface := range ifaces {
		var endpoint Endpoint

		addrs, err := iface.Addrs()
		if err != nil {
			return []Endpoint{}, err
		}

		if iface.Name == "lo" {
			continue
		} else {
			endpoint, err = createNetworkEndpoint(idx, uniqueID, iface.Name)
			if err != nil {
				return []Endpoint{}, err
			}
		}

		endpoint.Properties, err = n.createResult(iface, addrs)
		if err != nil {
			return []Endpoint{}, err
		}

		endpoints = append(endpoints, endpoint)

		idx++
	}

	return endpoints, nil
}

// init initializes the network, setting a new network namespace for the CNM network.
func (n *cnm) init(config *NetworkConfig) error {
	if config.NetNSPath == "" {
		path, err := createNetNS()
		if err != nil {
			return err
		}

		config.NetNSPath = path
	}

	return nil
}

// run runs a callback in the specified network namespace.
func (n *cnm) run(networkNSPath string, cb func() error) error {
	return doNetNS(networkNSPath, func(_ ns.NetNS) error {
		return cb()
	})
}

// add adds all needed interfaces inside the network namespace for the CNM network.
func (n *cnm) add(pod Pod, config NetworkConfig) (NetworkNamespace, error) {
	endpoints, err := n.createEndpointsFromScan()
	if err != nil {
		return NetworkNamespace{}, err
	}

	networkNS := NetworkNamespace{
		NetNsPath: config.NetNSPath,
		Endpoints: endpoints,
	}

	err = doNetNS(networkNS.NetNsPath, func(_ ns.NetNS) error {
		for _, endpoint := range networkNS.Endpoints {
			err := bridgeNetworkPair(endpoint.NetPair)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return NetworkNamespace{}, err
	}

	err = addNetDevHypervisor(pod, networkNS.Endpoints)
	if err != nil {
		return NetworkNamespace{}, err
	}

	return networkNS, nil
}

// remove unbridges and deletes TAP interfaces. It also removes virtual network
// interfaces and deletes the network namespace for the CNM network.
func (n *cnm) remove(pod Pod, networkNS NetworkNamespace) error {
	err := doNetNS(networkNS.NetNsPath, func(_ ns.NetNS) error {
		for _, endpoint := range networkNS.Endpoints {
			err := unBridgeNetworkPair(endpoint.NetPair)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return err
	}

	err = deleteNetNS(networkNS.NetNsPath, true)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>cnm: Interface list has to be scanned from inside the network namespace<commit_after>//
// Copyright (c) 2016 Intel Corporation
//
// 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 virtcontainers

import (
	"net"

	"github.com/01org/ciao/ssntp/uuid"
	"github.com/containernetworking/cni/pkg/ns"
	types "github.com/containernetworking/cni/pkg/types/current"
)

// cnm is a network implementation for the CNM plugin.
type cnm struct {
	config NetworkConfig
}

func (n *cnm) createResult(iface net.Interface, addrs []net.Addr) (types.Result, error) {
	var ipConfigs []*types.IPConfig
	for _, addr := range addrs {
		ip, ipNet, err := net.ParseCIDR(addr.String())
		if err != nil {
			return types.Result{}, err
		}

		version := "6"
		if ip.To4() != nil {
			version = "4"
		}
		ipNet.IP = ip

		ipConfig := &types.IPConfig{
			Version:   version,
			Interface: iface.Index,
			Address:   *ipNet,
		}

		ipConfigs = append(ipConfigs, ipConfig)
	}

	ifaceList := []*types.Interface{
		{
			Name: iface.Name,
			Mac:  iface.HardwareAddr.String(),
		},
	}

	res := types.Result{
		Interfaces: ifaceList,
		IPs:        ipConfigs,
	}

	return res, nil
}

func (n *cnm) createEndpointsFromScan(networkNSPath string) ([]Endpoint, error) {
	var endpoints []Endpoint

	ifaces, err := getIfacesFromNetNs(networkNSPath)
	if err != nil {
		return []Endpoint{}, err
	}

	uniqueID := uuid.Generate().String()

	idx := 0
	for _, iface := range ifaces {
		var endpoint Endpoint

		addrs, err := iface.Addrs()
		if err != nil {
			return []Endpoint{}, err
		}

		if iface.Name == "lo" {
			continue
		} else {
			endpoint, err = createNetworkEndpoint(idx, uniqueID, iface.Name)
			if err != nil {
				return []Endpoint{}, err
			}
		}

		endpoint.Properties, err = n.createResult(iface, addrs)
		if err != nil {
			return []Endpoint{}, err
		}

		endpoints = append(endpoints, endpoint)

		idx++
	}

	return endpoints, nil
}

// init initializes the network, setting a new network namespace for the CNM network.
func (n *cnm) init(config *NetworkConfig) error {
	if config.NetNSPath == "" {
		path, err := createNetNS()
		if err != nil {
			return err
		}

		config.NetNSPath = path
	}

	return nil
}

// run runs a callback in the specified network namespace.
func (n *cnm) run(networkNSPath string, cb func() error) error {
	return doNetNS(networkNSPath, func(_ ns.NetNS) error {
		return cb()
	})
}

// add adds all needed interfaces inside the network namespace for the CNM network.
func (n *cnm) add(pod Pod, config NetworkConfig) (NetworkNamespace, error) {
	endpoints, err := n.createEndpointsFromScan(config.NetNSPath)
	if err != nil {
		return NetworkNamespace{}, err
	}

	networkNS := NetworkNamespace{
		NetNsPath: config.NetNSPath,
		Endpoints: endpoints,
	}

	err = doNetNS(networkNS.NetNsPath, func(_ ns.NetNS) error {
		for _, endpoint := range networkNS.Endpoints {
			err := bridgeNetworkPair(endpoint.NetPair)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return NetworkNamespace{}, err
	}

	err = addNetDevHypervisor(pod, networkNS.Endpoints)
	if err != nil {
		return NetworkNamespace{}, err
	}

	return networkNS, nil
}

// remove unbridges and deletes TAP interfaces. It also removes virtual network
// interfaces and deletes the network namespace for the CNM network.
func (n *cnm) remove(pod Pod, networkNS NetworkNamespace) error {
	err := doNetNS(networkNS.NetNsPath, func(_ ns.NetNS) error {
		for _, endpoint := range networkNS.Endpoints {
			err := unBridgeNetworkPair(endpoint.NetPair)
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return err
	}

	err = deleteNetNS(networkNS.NetNsPath, true)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Claudemiro Alves Feitosa Neto. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gochip8

import (
	"fmt"
	"math/rand"
	"time"
)

// pc is the program counter
type pc uint16

// Increments the counter
func (p *pc) Increment() {
	(*p) += 2
}

// The stack
type stack struct {
	data [16]pc
	sp   uint16 // Stack Pointer
}

// Push the addr to the stack
func (s *stack) Push(data pc) {
	s.data[s.sp] = data
	s.sp++
}

// Pop a value from stack
func (s *stack) Pop() pc {
	s.sp--
	return s.data[s.sp]
}

// cpu is the chip8 main cpu
type cpu struct {
	regs  [16]byte // Registers v0 - vF
	stack stack    // The Stack
	i     uint16   // Index
	pc    pc       // Program Counter

	gfx    gfx      // Graphics
	memory memory   // Memory - 4K
	keys   [16]bool // Key State
	dt     byte     // Delay Timer
	st     byte     // Sound Timer
}

// Chip8 Fonts
var font = [80]byte{
	0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
	0x20, 0x60, 0x20, 0x20, 0x70, // 1
	0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
	0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
	0x90, 0x90, 0xF0, 0x10, 0x10, // 4
	0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
	0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
	0xF0, 0x10, 0x20, 0x40, 0x40, // 7
	0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
	0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
	0xF0, 0x90, 0xF0, 0x90, 0x90, // A
	0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
	0xF0, 0x80, 0x80, 0x80, 0xF0, // C
	0xE0, 0x90, 0x90, 0x90, 0xE0, // D
	0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
	0xF0, 0x80, 0xF0, 0x80, 0x80, // F
}

// newCpu creates a new cpu and initialize it
func newCpu() cpu {
	rand.Seed(time.Now().UTC().UnixNano())

	c := cpu{
		pc:    0x200,
		i:     0,
		dt:    0,
		st:    0,
		stack: stack{sp: 0},
	}

	// Load font into memory
	for i, e := range font {
		c.memory.Write(uint16(i), e)
	}

	return c
}

// Step the cpu one instruction at a time
func (c *cpu) Step() {
	opcode := c.memory.ReadWord(uint16(c.pc))
	x := opcode & 0x0F00
	y := opcode & 0x00F0

	c.pc.Increment()

	switch opcode & 0xF000 {
	case 0x0000:
		switch opcode {
		case 0x00E0: // 00E0 - CLS
			c.gfx.Cls()
		case 0x00EE: // 00EE - RET
			c.pc = c.stack.Pop()
		}
	case 0x1000: // 1nnn - JP addr
		c.pc = pc(opcode & 0x0FFF)
	case 0x2000: // 2nnn - CALL addr
		c.stack.Push(c.pc)
		c.pc = pc(opcode & 0x0FFF)
	case 0x3000: // 3xkk - SE Vx, byte
		kk := opcode & 0x00FF

		if c.regs[x] == byte(kk) {
			c.pc.Increment()
		}
	case 0x4000: // 4xkk - SNE Vx, byte
		kk := opcode & 0x00FF

		if c.regs[x] != byte(kk) {
			c.pc.Increment()
		}
	case 0x5000: // 5xy0 - SE Vx, Vy
		if c.regs[x] == c.regs[y] {
			c.pc.Increment()
		}
	case 0x6000: // 6xkk - LD Vx, byte
		kk := opcode & 0x00FF

		c.regs[x] = byte(kk)
	case 0x7000: // 7xkk - ADD Vx, byte
		kk := opcode & 0x00FF

		c.regs[x] += byte(kk)
	case 0x8000:
		switch opcode & 0x000F {
		case 0x0000: // 8xy0 - LD Vx, Vy
			c.regs[x] = c.regs[y]
		case 0x0001: // 8xy1 - OR Vx, Vy
			c.regs[x] |= c.regs[y]
		case 0x0002: // 8xy2 - AND Vx, Vy
			c.regs[x] &= c.regs[y]
		case 0x0003: // 8xy3 - XOR Vx, Vy
			c.regs[x] ^= c.regs[y]
		case 0x0004: // 8xy4 - ADD Vx, Vy
			r := c.regs[x] + c.regs[y]

			if r > 0xFF {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}

			c.regs[x] = r
		case 0x0005: // 8xy5 - SUB Vx, Vy
			if c.regs[x] > c.regs[y] {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}

			c.regs[x] = c.regs[x] - c.regs[y]
		case 0x0006: // 8xy6 - SHR Vx {, Vy}
			c.regs[0xF] = c.regs[x] & 0x0001
			c.regs[x] = c.regs[x] / 2
		case 0x0007: // 8xy7 - SUBN Vx, Vy
			if c.regs[y] > c.regs[x] {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}
			c.regs[x] = c.regs[y] - c.regs[x]
		case 0x000E: // 8xyE - SHL Vx {, Vy}
			c.regs[0xF] = c.regs[x] & 0x0001
			c.regs[x] = c.regs[x] * 2
		}
	case 0x9000: // 9xy0 - SNE Vx, Vy
		if c.regs[x] != c.regs[y] {
			c.pc.Increment()
		}
	case 0xA000: // Annn - LD I, addr
		c.i = opcode & 0x0FFF
	case 0xB000: // Bnnn - JP V0, addr
		addr := opcode & 0x0FFF
		c.pc = pc(addr + uint16(c.regs[0]))
	case 0xC000: // Cxkk - RND Vx, byte
		kk := opcode & 0x00FF
		c.regs[x] = byte(rand.Intn(256)) & byte(kk)
	case 0xD000: // Dxyn - DRW Vx, Vy, nibble
		// TODO:  Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
	case 0xE000:
		switch opcode & 0x000F {
		case 0x000E: // Ex9E - SKP Vx
			if c.keys[x] {
				c.pc.Increment()
			}
		case 0x0001: // ExA1 - SKNP Vx
			if !c.keys[x] {
				c.pc.Increment()
			}
		}
	case 0xF000:
		switch opcode & 0x00FF {
		case 0x0007: // Fx07 - LD Vx, DT
			c.regs[x] = c.dt
		case 0x000A: // Fx0A - LD Vx, K
			// TODO: Wait for a key press, store the value of the key in Vx.
			// All execution stops until a key is pressed, then the value of that key is stored in Vx.
		case 0x0015: // Fx15 - LD DT, Vx
			c.dt = c.regs[x]
		case 0x0018: // Fx18 - LD ST, Vx
			c.st = c.regs[x]
		case 0x001E: // Fx1E - ADD I, Vx
			c.i += uint16(c.regs[x])
		case 0x0029: // Fx29 - LD F, Vx
			c.i = uint16(c.regs[x] * 5) // 5 is the number of rows per character.
		case 0x0033: // Fx33 - LD B, Vx
			// TODO: Store BCD representation of Vx in memory locations I, I+1, and I+2.
			// The interpreter takes the decimal value of Vx, and places the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.
		case 0x0055: // Fx55 - LD [I], Vx
			for i := uint16(0); i <= x; i++ {
				c.memory.Write(c.i+i, c.regs[i])
			}
		case 0x0065: // Fx65 - LD Vx, [I]
			for i := uint16(0); i <= x; i++ {
				c.regs[i] = c.memory.Read(c.i + i)
			}
		}
	default:
		panic(fmt.Sprintf("Unknown opcode %s", opcode))
	}
}
<commit_msg>It is not %s<commit_after>// Copyright 2015 Claudemiro Alves Feitosa Neto. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gochip8

import (
	"fmt"
	"math/rand"
	"time"
)

// pc is the program counter
type pc uint16

// Increments the counter
func (p *pc) Increment() {
	(*p) += 2
}

// The stack
type stack struct {
	data [16]pc
	sp   uint16 // Stack Pointer
}

// Push the addr to the stack
func (s *stack) Push(data pc) {
	s.data[s.sp] = data
	s.sp++
}

// Pop a value from stack
func (s *stack) Pop() pc {
	s.sp--
	return s.data[s.sp]
}

// cpu is the chip8 main cpu
type cpu struct {
	regs  [16]byte // Registers v0 - vF
	stack stack    // The Stack
	i     uint16   // Index
	pc    pc       // Program Counter

	gfx    gfx      // Graphics
	memory memory   // Memory - 4K
	keys   [16]bool // Key State
	dt     byte     // Delay Timer
	st     byte     // Sound Timer
}

// Chip8 Fonts
var font = [80]byte{
	0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
	0x20, 0x60, 0x20, 0x20, 0x70, // 1
	0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
	0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
	0x90, 0x90, 0xF0, 0x10, 0x10, // 4
	0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
	0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
	0xF0, 0x10, 0x20, 0x40, 0x40, // 7
	0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
	0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
	0xF0, 0x90, 0xF0, 0x90, 0x90, // A
	0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
	0xF0, 0x80, 0x80, 0x80, 0xF0, // C
	0xE0, 0x90, 0x90, 0x90, 0xE0, // D
	0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
	0xF0, 0x80, 0xF0, 0x80, 0x80, // F
}

// newCpu creates a new cpu and initialize it
func newCpu() cpu {
	rand.Seed(time.Now().UTC().UnixNano())

	c := cpu{
		pc:    0x200,
		i:     0,
		dt:    0,
		st:    0,
		stack: stack{sp: 0},
	}

	// Load font into memory
	for i, e := range font {
		c.memory.Write(uint16(i), e)
	}

	return c
}

// Step the cpu one instruction at a time
func (c *cpu) Step() {
	opcode := c.memory.ReadWord(uint16(c.pc))
	x := opcode & 0x0F00
	y := opcode & 0x00F0

	c.pc.Increment()

	switch opcode & 0xF000 {
	case 0x0000:
		switch opcode {
		case 0x00E0: // 00E0 - CLS
			c.gfx.Cls()
		case 0x00EE: // 00EE - RET
			c.pc = c.stack.Pop()
		}
	case 0x1000: // 1nnn - JP addr
		c.pc = pc(opcode & 0x0FFF)
	case 0x2000: // 2nnn - CALL addr
		c.stack.Push(c.pc)
		c.pc = pc(opcode & 0x0FFF)
	case 0x3000: // 3xkk - SE Vx, byte
		kk := opcode & 0x00FF

		if c.regs[x] == byte(kk) {
			c.pc.Increment()
		}
	case 0x4000: // 4xkk - SNE Vx, byte
		kk := opcode & 0x00FF

		if c.regs[x] != byte(kk) {
			c.pc.Increment()
		}
	case 0x5000: // 5xy0 - SE Vx, Vy
		if c.regs[x] == c.regs[y] {
			c.pc.Increment()
		}
	case 0x6000: // 6xkk - LD Vx, byte
		kk := opcode & 0x00FF

		c.regs[x] = byte(kk)
	case 0x7000: // 7xkk - ADD Vx, byte
		kk := opcode & 0x00FF

		c.regs[x] += byte(kk)
	case 0x8000:
		switch opcode & 0x000F {
		case 0x0000: // 8xy0 - LD Vx, Vy
			c.regs[x] = c.regs[y]
		case 0x0001: // 8xy1 - OR Vx, Vy
			c.regs[x] |= c.regs[y]
		case 0x0002: // 8xy2 - AND Vx, Vy
			c.regs[x] &= c.regs[y]
		case 0x0003: // 8xy3 - XOR Vx, Vy
			c.regs[x] ^= c.regs[y]
		case 0x0004: // 8xy4 - ADD Vx, Vy
			r := c.regs[x] + c.regs[y]

			if r > 0xFF {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}

			c.regs[x] = r
		case 0x0005: // 8xy5 - SUB Vx, Vy
			if c.regs[x] > c.regs[y] {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}

			c.regs[x] = c.regs[x] - c.regs[y]
		case 0x0006: // 8xy6 - SHR Vx {, Vy}
			c.regs[0xF] = c.regs[x] & 0x0001
			c.regs[x] = c.regs[x] / 2
		case 0x0007: // 8xy7 - SUBN Vx, Vy
			if c.regs[y] > c.regs[x] {
				c.regs[0xF] = 1
			} else {
				c.regs[0xF] = 0
			}
			c.regs[x] = c.regs[y] - c.regs[x]
		case 0x000E: // 8xyE - SHL Vx {, Vy}
			c.regs[0xF] = c.regs[x] & 0x0001
			c.regs[x] = c.regs[x] * 2
		}
	case 0x9000: // 9xy0 - SNE Vx, Vy
		if c.regs[x] != c.regs[y] {
			c.pc.Increment()
		}
	case 0xA000: // Annn - LD I, addr
		c.i = opcode & 0x0FFF
	case 0xB000: // Bnnn - JP V0, addr
		addr := opcode & 0x0FFF
		c.pc = pc(addr + uint16(c.regs[0]))
	case 0xC000: // Cxkk - RND Vx, byte
		kk := opcode & 0x00FF
		c.regs[x] = byte(rand.Intn(256)) & byte(kk)
	case 0xD000: // Dxyn - DRW Vx, Vy, nibble
		// TODO:  Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
	case 0xE000:
		switch opcode & 0x000F {
		case 0x000E: // Ex9E - SKP Vx
			if c.keys[x] {
				c.pc.Increment()
			}
		case 0x0001: // ExA1 - SKNP Vx
			if !c.keys[x] {
				c.pc.Increment()
			}
		}
	case 0xF000:
		switch opcode & 0x00FF {
		case 0x0007: // Fx07 - LD Vx, DT
			c.regs[x] = c.dt
		case 0x000A: // Fx0A - LD Vx, K
			// TODO: Wait for a key press, store the value of the key in Vx.
			// All execution stops until a key is pressed, then the value of that key is stored in Vx.
		case 0x0015: // Fx15 - LD DT, Vx
			c.dt = c.regs[x]
		case 0x0018: // Fx18 - LD ST, Vx
			c.st = c.regs[x]
		case 0x001E: // Fx1E - ADD I, Vx
			c.i += uint16(c.regs[x])
		case 0x0029: // Fx29 - LD F, Vx
			c.i = uint16(c.regs[x] * 5) // 5 is the number of rows per character.
		case 0x0033: // Fx33 - LD B, Vx
			// TODO: Store BCD representation of Vx in memory locations I, I+1, and I+2.
			// The interpreter takes the decimal value of Vx, and places the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.
		case 0x0055: // Fx55 - LD [I], Vx
			for i := uint16(0); i <= x; i++ {
				c.memory.Write(c.i+i, c.regs[i])
			}
		case 0x0065: // Fx65 - LD Vx, [I]
			for i := uint16(0); i <= x; i++ {
				c.regs[i] = c.memory.Read(c.i + i)
			}
		}
	default:
		panic(fmt.Sprintf("Unknown opcode %+v", opcode))
	}
}
<|endoftext|>


<commit_before>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju-core/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// CacheDir stores the charm cache directory path.
var CacheDir string

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// EventResponse is sent by the charm store in response to charm-event requests.
type EventResponse struct {
	Kind     string   `json:"kind"`
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
	Time     string   `json:"time,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// NotFoundError represents an error indicating that the requested data wasn't found.
type NotFoundError struct {
	msg string
}

func (e *NotFoundError) Error() string {
	return e.msg
}

// CharmStore is a Repository that provides access to the public juju charm store.
type CharmStore struct {
	baseURL string
}

var Store = &CharmStore{"https://store.juju.ubuntu.com"}

// Info returns details for a charm in the charm store.
func (s *CharmStore) Info(curl *URL) (*InfoResponse, error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return nil, err
	}
	info, found := infos[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(info.Errors) == 1 && info.Errors[0] == "entry not found" {
		return nil, &NotFoundError{fmt.Sprintf("charm not found: %s", curl)}
	}
	return info, nil
}

// Event returns details for a charm event in the charm store.
//
// If digest is empty, the latest event is returned.
func (s *CharmStore) Event(curl *URL, digest string) (*EventResponse, error) {
	key := curl.String()
	query := key
	if digest != "" {
		query += "@" + digest
	}
	resp, err := http.Get(s.baseURL + "/charm-event?charms=" + url.QueryEscape(query))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	events := make(map[string]*EventResponse)
	if err = json.Unmarshal(body, &events); err != nil {
		return nil, err
	}
	event, found := events[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(event.Errors) == 1 && event.Errors[0] == "entry not found" {
		if digest == "" {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q", curl)}
		} else {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q with digest %q", curl, digest)}
		}
	}
	return event, nil
}

// revision returns the revision and SHA256 digest of the charm referenced by curl.
func (s *CharmStore) revision(curl *URL) (revision int, digest string, err error) {
	info, err := s.Info(curl)
	if err != nil {
		return 0, "", err
	}
	for _, w := range info.Warnings {
		log.Warningf("charm: charm store reports for %q: %s", curl, w)
	}
	if info.Errors != nil {
		return 0, "", fmt.Errorf("charm info errors for %q: %s", curl, strings.Join(info.Errors, "; "))
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *CharmStore) Latest(curl *URL) (int, error) {
	rev, _, err := s.revision(curl.WithRevision(-1))
	return rev, err
}

// BranchLocation returns the location for the branch holding the charm at curl.
func (s *CharmStore) BranchLocation(curl *URL) string {
	if curl.User != "" {
		return fmt.Sprintf("lp:~%s/charms/%s/%s/trunk", curl.User, curl.Series, curl.Name)
	}
	return fmt.Sprintf("lp:charms/%s/%s/trunk", curl.Series, curl.Name)
}

var branchPrefixes = []string{
	"lp:",
	"bzr+ssh://bazaar.launchpad.net/+branch/",
	"bzr+ssh://bazaar.launchpad.net/",
	"http://launchpad.net/+branch/",
	"http://launchpad.net/",
	"https://launchpad.net/+branch/",
	"https://launchpad.net/",
	"http://code.launchpad.net/+branch/",
	"http://code.launchpad.net/",
	"https://code.launchpad.net/+branch/",
	"https://code.launchpad.net/",
}

// CharmURL returns the charm URL for the branch at location.
func (s *CharmStore) CharmURL(location string) (*URL, error) {
	var l string
	if len(location) > 0 && location[0] == '~' {
		l = location
	} else {
		for _, prefix := range branchPrefixes {
			if strings.HasPrefix(location, prefix) {
				l = location[len(prefix):]
				break
			}
		}
	}
	if l != "" {
		u := strings.Split(l, "/")
		if len(u) == 3 && u[0] == "charms" {
			return ParseURL(fmt.Sprintf("cs:%s/%s", u[1], u[2]))
		}
		if len(u) == 4 && u[0] == "charms" && u[3] == "trunk" {
			return ParseURL(fmt.Sprintf("cs:%s/%s", u[1], u[2]))
		}
		if len(u) == 5 && u[1] == "charms" && u[4] == "trunk" && len(u[0]) > 0 && u[0][0] == '~' {
			return ParseURL(fmt.Sprintf("cs:%s/%s/%s", u[0], u[2], u[3]))
		}
	}
	return nil, fmt.Errorf("unknown branch location: %q", location)
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	h := sha256.New()
	if _, err := io.Copy(h, f); err != nil {
		return err
	}
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
func (s *CharmStore) Get(curl *URL) (Charm, error) {
	// MachineAgent.Run should have already set the CacheDir.
	if CacheDir == "" {
		panic("the charm cache directory path is empty")
	}
	if err := os.MkdirAll(CacheDir, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.revision(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(CacheDir, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(CacheDir, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series. For example:
//
//   /path/to/repository/oneiric/mongodb/
//   /path/to/repository/precise/mongodb.charm
//   /path/to/repository/precise/wordpress/
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return &NotFoundError{fmt.Sprintf("no repository found at %q", path)}
}

func charmNotFound(curl *URL, repoPath string) error {
	return &NotFoundError{fmt.Sprintf("no charms found matching %q in %s", curl, repoPath)}
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl, r.Path)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Warningf("charm: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl, r.Path)
}
<commit_msg>Chenges as per review.<commit_after>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju-core/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// CacheDir stores the charm cache directory path.
var CacheDir string

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// EventResponse is sent by the charm store in response to charm-event requests.
type EventResponse struct {
	Kind     string   `json:"kind"`
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
	Time     string   `json:"time,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// NotFoundError represents an error indicating that the requested data wasn't found.
type NotFoundError struct {
	msg string
}

func (e *NotFoundError) Error() string {
	return e.msg
}

// CharmStore is a Repository that provides access to the public juju charm store.
type CharmStore struct {
	baseURL string
}

var Store = &CharmStore{"https://store.juju.ubuntu.com"}

// Info returns details for a charm in the charm store.
func (s *CharmStore) Info(curl *URL) (*InfoResponse, error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return nil, err
	}
	info, found := infos[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(info.Errors) == 1 && info.Errors[0] == "entry not found" {
		return nil, &NotFoundError{fmt.Sprintf("charm not found: %s", curl)}
	}
	return info, nil
}

// Event returns details for a charm event in the charm store.
//
// If digest is empty, the latest event is returned.
func (s *CharmStore) Event(curl *URL, digest string) (*EventResponse, error) {
	key := curl.String()
	query := key
	if digest != "" {
		query += "@" + digest
	}
	resp, err := http.Get(s.baseURL + "/charm-event?charms=" + url.QueryEscape(query))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	events := make(map[string]*EventResponse)
	if err = json.Unmarshal(body, &events); err != nil {
		return nil, err
	}
	event, found := events[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(event.Errors) == 1 && event.Errors[0] == "entry not found" {
		if digest == "" {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q", curl)}
		} else {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q with digest %q", curl, digest)}
		}
	}
	return event, nil
}

// revision returns the revision and SHA256 digest of the charm referenced by curl.
func (s *CharmStore) revision(curl *URL) (revision int, digest string, err error) {
	info, err := s.Info(curl)
	if err != nil {
		return 0, "", err
	}
	for _, w := range info.Warnings {
		log.Warningf("charm: charm store reports for %q: %s", curl, w)
	}
	if info.Errors != nil {
		return 0, "", fmt.Errorf("charm info errors for %q: %s", curl, strings.Join(info.Errors, "; "))
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *CharmStore) Latest(curl *URL) (int, error) {
	rev, _, err := s.revision(curl.WithRevision(-1))
	return rev, err
}

// BranchLocation returns the location for the branch holding the charm at curl.
func (s *CharmStore) BranchLocation(curl *URL) string {
	if curl.User != "" {
		return fmt.Sprintf("lp:~%s/charms/%s/%s/trunk", curl.User, curl.Series, curl.Name)
	}
	return fmt.Sprintf("lp:charms/%s/%s/trunk", curl.Series, curl.Name)
}

var branchPrefixes = []string{
	"lp:",
	"bzr+ssh://bazaar.launchpad.net/+branch/",
	"bzr+ssh://bazaar.launchpad.net/",
	"http://launchpad.net/+branch/",
	"http://launchpad.net/",
	"https://launchpad.net/+branch/",
	"https://launchpad.net/",
	"http://code.launchpad.net/+branch/",
	"http://code.launchpad.net/",
	"https://code.launchpad.net/+branch/",
	"https://code.launchpad.net/",
}

// CharmURL returns the charm URL for the branch at location.
func (s *CharmStore) CharmURL(location string) (*URL, error) {
	var l string
	if len(location) > 0 && location[0] == '~' {
		l = location
	} else {
		for _, prefix := range branchPrefixes {
			if strings.HasPrefix(location, prefix) {
				l = location[len(prefix):]
				break
			}
		}
	}
	if l != "" {
		u := strings.Split(l, "/")
		if len(u) == 3 && u[0] == "charms" {
			return ParseURL(fmt.Sprintf("cs:%s/%s", u[1], u[2]))
		}
		if len(u) == 4 && u[0] == "charms" && u[3] == "trunk" {
			return ParseURL(fmt.Sprintf("cs:%s/%s", u[1], u[2]))
		}
		if len(u) == 5 && u[1] == "charms" && u[4] == "trunk" && len(u[0]) > 0 && u[0][0] == '~' {
			return ParseURL(fmt.Sprintf("cs:%s/%s/%s", u[0], u[2], u[3]))
		}
	}
	return nil, fmt.Errorf("unknown branch location: %q", location)
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	h := sha256.New()
	if _, err := io.Copy(h, f); err != nil {
		return err
	}
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
// CacheDir must have been set, otherwise Get will panic.
func (s *CharmStore) Get(curl *URL) (Charm, error) {
	// The cache location must have been previously set.
	if CacheDir == "" {
		panic("charm cache directory path is empty")
	}
	if err := os.MkdirAll(CacheDir, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.revision(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(CacheDir, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(CacheDir, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series. For example:
//
//   /path/to/repository/oneiric/mongodb/
//   /path/to/repository/precise/mongodb.charm
//   /path/to/repository/precise/wordpress/
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return &NotFoundError{fmt.Sprintf("no repository found at %q", path)}
}

func charmNotFound(curl *URL, repoPath string) error {
	return &NotFoundError{fmt.Sprintf("no charms found matching %q in %s", curl, repoPath)}
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl, r.Path)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Warningf("charm: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl, r.Path)
}
<|endoftext|>


<commit_before>package openstack

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type StepRunSourceServer struct {
	Name             string
	SourceImage      string
	SourceImageName  string
	SecurityGroups   []string
	Networks         []string
	Ports            []string
	AvailabilityZone string
	UserData         string
	UserDataFile     string
	ConfigDrive      bool
	InstanceMetadata map[string]string
	server           *servers.Server
}

func (s *StepRunSourceServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(Config)
	flavor := state.Get("flavor_id").(string)
	ui := state.Get("ui").(packer.Ui)

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		err = fmt.Errorf("Error initializing compute client: %s", err)
		state.Put("error", err)
		return multistep.ActionHalt
	}

	networks := make([]servers.Network, len(s.Networks)+len(s.Ports))
	i := 0
	if len(s.Ports) > 0 {
		for i = 0; i < len(s.Ports); i++ {
			networks[i].Port = s.Ports[i]
		}
	}
	if len(s.Networks) > 0 {
		for i = len(s.Ports); i < len(networks); i++ {
			networks[i].UUID = s.Networks[i]
		}
	}

	userData := []byte(s.UserData)
	if s.UserDataFile != "" {
		userData, err = ioutil.ReadFile(s.UserDataFile)
		if err != nil {
			err = fmt.Errorf("Error reading user data file: %s", err)
			state.Put("error", err)
			return multistep.ActionHalt
		}
	}

	ui.Say("Launching server...")

	serverOpts := servers.CreateOpts{
		Name:             s.Name,
		ImageRef:         s.SourceImage,
		ImageName:        s.SourceImageName,
		FlavorRef:        flavor,
		SecurityGroups:   s.SecurityGroups,
		Networks:         networks,
		AvailabilityZone: s.AvailabilityZone,
		UserData:         userData,
		ConfigDrive:      &s.ConfigDrive,
		ServiceClient:    computeClient,
		Metadata:         s.InstanceMetadata,
	}

	var serverOptsExt servers.CreateOptsBuilder
	keyName, hasKey := state.GetOk("keyPair")
	if hasKey {
		serverOptsExt = keypairs.CreateOptsExt{
			CreateOptsBuilder: serverOpts,
			KeyName:           keyName.(string),
		}
	} else {
		serverOptsExt = serverOpts
	}

	s.server, err = servers.Create(computeClient, serverOptsExt).Extract()
	if err != nil {
		err := fmt.Errorf("Error launching source server: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID))
	log.Printf("server id: %s", s.server.ID)

	ui.Say("Waiting for server to become ready...")
	stateChange := StateChangeConf{
		Pending:   []string{"BUILD"},
		Target:    []string{"ACTIVE"},
		Refresh:   ServerStateRefreshFunc(computeClient, s.server),
		StepState: state,
	}
	latestServer, err := WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.server = latestServer.(*servers.Server)
	state.Put("server", s.server)

	return multistep.ActionContinue
}

func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
	if s.server == nil {
		return
	}

	config := state.Get("config").(Config)
	ui := state.Get("ui").(packer.Ui)

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID))
	if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	stateChange := StateChangeConf{
		Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"},
		Refresh: ServerStateRefreshFunc(computeClient, s.server),
		Target:  []string{"DELETED"},
	}

	WaitForState(&stateChange)
}
<commit_msg>Simplified loop code<commit_after>package openstack

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type StepRunSourceServer struct {
	Name             string
	SourceImage      string
	SourceImageName  string
	SecurityGroups   []string
	Networks         []string
	Ports            []string
	AvailabilityZone string
	UserData         string
	UserDataFile     string
	ConfigDrive      bool
	InstanceMetadata map[string]string
	server           *servers.Server
}

func (s *StepRunSourceServer) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(Config)
	flavor := state.Get("flavor_id").(string)
	ui := state.Get("ui").(packer.Ui)

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		err = fmt.Errorf("Error initializing compute client: %s", err)
		state.Put("error", err)
		return multistep.ActionHalt
	}

	networks := make([]servers.Network, len(s.Networks)+len(s.Ports))
	i := 0
	for ; i < len(s.Ports); i++ {
		networks[i].Port = s.Ports[i]
	}
	for ; i < len(networks); i++ {
		networks[i].UUID = s.Networks[i]
	}

	userData := []byte(s.UserData)
	if s.UserDataFile != "" {
		userData, err = ioutil.ReadFile(s.UserDataFile)
		if err != nil {
			err = fmt.Errorf("Error reading user data file: %s", err)
			state.Put("error", err)
			return multistep.ActionHalt
		}
	}

	ui.Say("Launching server...")

	serverOpts := servers.CreateOpts{
		Name:             s.Name,
		ImageRef:         s.SourceImage,
		ImageName:        s.SourceImageName,
		FlavorRef:        flavor,
		SecurityGroups:   s.SecurityGroups,
		Networks:         networks,
		AvailabilityZone: s.AvailabilityZone,
		UserData:         userData,
		ConfigDrive:      &s.ConfigDrive,
		ServiceClient:    computeClient,
		Metadata:         s.InstanceMetadata,
	}

	var serverOptsExt servers.CreateOptsBuilder
	keyName, hasKey := state.GetOk("keyPair")
	if hasKey {
		serverOptsExt = keypairs.CreateOptsExt{
			CreateOptsBuilder: serverOpts,
			KeyName:           keyName.(string),
		}
	} else {
		serverOptsExt = serverOpts
	}

	s.server, err = servers.Create(computeClient, serverOptsExt).Extract()
	if err != nil {
		err := fmt.Errorf("Error launching source server: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID))
	log.Printf("server id: %s", s.server.ID)

	ui.Say("Waiting for server to become ready...")
	stateChange := StateChangeConf{
		Pending:   []string{"BUILD"},
		Target:    []string{"ACTIVE"},
		Refresh:   ServerStateRefreshFunc(computeClient, s.server),
		StepState: state,
	}
	latestServer, err := WaitForState(&stateChange)
	if err != nil {
		err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.server = latestServer.(*servers.Server)
	state.Put("server", s.server)

	return multistep.ActionContinue
}

func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
	if s.server == nil {
		return
	}

	config := state.Get("config").(Config)
	ui := state.Get("ui").(packer.Ui)

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	ui.Say(fmt.Sprintf("Terminating the source server: %s ...", s.server.ID))
	if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	stateChange := StateChangeConf{
		Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"},
		Refresh: ServerStateRefreshFunc(computeClient, s.server),
		Target:  []string{"DELETED"},
	}

	WaitForState(&stateChange)
}
<|endoftext|>


<commit_before>// Copyright 2017 ego 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 riot

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"strings"

	"encoding/binary"
	"encoding/gob"

	"github.com/go-ego/murmur"
	"github.com/go-ego/riot/core"
	"github.com/go-ego/riot/types"
	toml "github.com/go-vgo/gt/conf"
)

// New create a new engine with mode
func New(conf ...interface{}) *Engine {
	// func (engine *Engine) New(conf com.Config) *Engine{
	if len(conf) > 0 && strings.HasSuffix(conf[0].(string), ".toml") {
		var (
			config   types.EngineOpts
			searcher = &Engine{}
		)

		fs := conf[0].(string)
		log.Println("conf path is: ", fs)
		toml.Init(fs, &config)
		go toml.Watch(fs, &config)

		searcher.Init(config)
		return searcher
	}

	return NewEngine(conf...)
}

// NewEngine create a new engine
func NewEngine(conf ...interface{}) *Engine {
	var (
		searcher = &Engine{}

		path          = DefaultPath
		storageShards = 10
		numShards     = 10

		segmentDict string
	)

	if len(conf) > 0 {
		segmentDict = conf[0].(string)
	}

	if len(conf) > 1 {
		path = conf[1].(string)
	}

	if len(conf) > 2 {
		numShards = conf[2].(int)
		storageShards = conf[2].(int)
	}

	searcher.Init(types.EngineOpts{
		// Using:         using,
		StoreShards: storageShards,
		NumShards:   numShards,
		IndexerOpts: &types.IndexerOpts{
			IndexType: types.DocIdsIndex,
		},
		UseStore:    true,
		StoreFolder: path,
		// StoreEngine: storageEngine,
		GseDict: segmentDict,
		// StopTokenFile: stopTokenFile,
	})

	// defer searcher.Close()
	os.MkdirAll(path, 0777)

	// 等待索引刷新完毕
	// searcher.Flush()
	// log.Println("recover index number: ", searcher.NumDocsIndexed())

	return searcher
}

// func (engine *Engine) IsDocExist(docId uint64) bool {
// 	return core.IsDocExist(docId)
// }

// HasDoc if the document is exist return true
func (engine *Engine) HasDoc(docId uint64) bool {
	for shard := 0; shard < engine.initOptions.NumShards; shard++ {
		engine.indexers = append(engine.indexers, core.Indexer{})

		has := engine.indexers[shard].HasDoc(docId)

		if has {
			return true
		}
	}

	return false
}

// HasDocDB if the document is exist in the database
// return true
func (engine *Engine) HasDocDB(docId uint64) bool {
	b := make([]byte, 10)
	length := binary.PutUvarint(b, docId)

	shard := murmur.Sum32(fmt.Sprintf("%d", docId)) %
		uint32(engine.initOptions.StoreShards)

	has, err := engine.dbs[shard].Has(b[0:length])
	if err != nil {
		log.Println("engine.dbs[shard].Has(b[0:length]): ", err)
	}

	return has
}

// GetDBAllIds get all the DocId from the storage database
// and return
// 从数据库遍历所有的 DocId, 并返回
func (engine *Engine) GetDBAllIds() []uint64 {
	docsId := make([]uint64, 0)
	for i := range engine.dbs {
		engine.dbs[i].ForEach(func(k, v []byte) error {
			// fmt.Println(k, v)
			docId, _ := binary.Uvarint(k)
			docsId = append(docsId, docId)
			return nil
		})
	}

	return docsId
}

// GetDBAllDocs get the db all docs
func (engine *Engine) GetDBAllDocs() (
	docsId []uint64, docsData []types.DocData) {
	for i := range engine.dbs {
		engine.dbs[i].ForEach(func(key, val []byte) error {
			// fmt.Println(k, v)
			docId, _ := binary.Uvarint(key)
			docsId = append(docsId, docId)

			buf := bytes.NewReader(val)
			dec := gob.NewDecoder(buf)

			var data types.DocData
			err := dec.Decode(&data)
			if err != nil {
				log.Println("dec.decode: ", err)
			}

			docsData = append(docsData, data)

			return nil
		})
	}

	return docsId, docsData
}

// GetAllDocIds get all the DocId from the storage database
// and return
// 从数据库遍历所有的 DocId, 并返回
func (engine *Engine) GetAllDocIds() []uint64 {
	return engine.GetDBAllIds()
}

// Try handler(err)
func Try(fun func(), handler func(interface{})) {
	defer func() {
		if err := recover(); err != nil {
			handler(err)
		}
	}()
	fun()
}
<commit_msg>update riot.go code [ci skip]<commit_after>// Copyright 2017 ego 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 riot

import (
	"bytes"
	"log"
	"os"
	"strings"

	"encoding/gob"

	"github.com/go-ego/murmur"
	"github.com/go-ego/riot/core"
	"github.com/go-ego/riot/types"
	toml "github.com/go-vgo/gt/conf"
)

// New create a new engine with mode
func New(conf ...interface{}) *Engine {
	// func (engine *Engine) New(conf com.Config) *Engine{
	if len(conf) > 0 && strings.HasSuffix(conf[0].(string), ".toml") {
		var (
			config   types.EngineOpts
			searcher = &Engine{}
		)

		fs := conf[0].(string)
		log.Println("conf path is: ", fs)
		toml.Init(fs, &config)
		go toml.Watch(fs, &config)

		searcher.Init(config)
		return searcher
	}

	return NewEngine(conf...)
}

// NewEngine create a new engine
func NewEngine(conf ...interface{}) *Engine {
	var (
		searcher = &Engine{}

		path          = DefaultPath
		storageShards = 10
		numShards     = 10

		segmentDict string
	)

	if len(conf) > 0 {
		segmentDict = conf[0].(string)
	}

	if len(conf) > 1 {
		path = conf[1].(string)
	}

	if len(conf) > 2 {
		numShards = conf[2].(int)
		storageShards = conf[2].(int)
	}

	searcher.Init(types.EngineOpts{
		// Using:         using,
		StoreShards: storageShards,
		NumShards:   numShards,
		IndexerOpts: &types.IndexerOpts{
			IndexType: types.DocIdsIndex,
		},
		UseStore:    true,
		StoreFolder: path,
		// StoreEngine: storageEngine,
		GseDict: segmentDict,
		// StopTokenFile: stopTokenFile,
	})

	// defer searcher.Close()
	os.MkdirAll(path, 0777)

	// 等待索引刷新完毕
	// searcher.Flush()
	// log.Println("recover index number: ", searcher.NumDocsIndexed())

	return searcher
}

// func (engine *Engine) IsDocExist(docId uint64) bool {
// 	return core.IsDocExist(docId)
// }

// HasDoc if the document is exist return true
func (engine *Engine) HasDoc(docId string) bool {
	for shard := 0; shard < engine.initOptions.NumShards; shard++ {
		engine.indexers = append(engine.indexers, core.Indexer{})

		has := engine.indexers[shard].HasDoc(docId)

		if has {
			return true
		}
	}

	return false
}

// HasDocDB if the document is exist in the database
// return true
func (engine *Engine) HasDocDB(docId string) bool {
	shard := murmur.Sum32(docId) % uint32(engine.initOptions.StoreShards)

	has, err := engine.dbs[shard].Has([]byte(docId))
	if err != nil {
		log.Println("engine.dbs[shard].Has(b[0:length]): ", err)
	}

	return has
}

// GetDBAllIds get all the DocId from the storage database
// and return
// 从数据库遍历所有的 DocId, 并返回
func (engine *Engine) GetDBAllIds() []string {
	docsId := make([]string, 0)

	for i := range engine.dbs {
		engine.dbs[i].ForEach(func(k, v []byte) error {
			// fmt.Println(k, v)
			docsId = append(docsId, string(k))
			return nil
		})
	}

	return docsId
}

// GetDBAllDocs get the db all docs
func (engine *Engine) GetDBAllDocs() (docsId []string, docsData []types.DocData) {
	for i := range engine.dbs {
		engine.dbs[i].ForEach(func(key, val []byte) error {
			// fmt.Println(k, v)
			docsId = append(docsId, string(key))

			buf := bytes.NewReader(val)
			dec := gob.NewDecoder(buf)

			var data types.DocData
			err := dec.Decode(&data)
			if err != nil {
				log.Println("dec.decode: ", err)
			}

			docsData = append(docsData, data)

			return nil
		})
	}

	return docsId, docsData
}

// GetAllDocIds get all the DocId from the storage database
// and return
// 从数据库遍历所有的 DocId, 并返回
func (engine *Engine) GetAllDocIds() []string {
	return engine.GetDBAllIds()
}

// Try handler(err)
func Try(fun func(), handler func(interface{})) {
	defer func() {
		if err := recover(); err != nil {
			handler(err)
		}
	}()
	fun()
}
<|endoftext|>


<commit_before>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     August 12, 2020
;       related version of root zone:     2020081201
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<commit_msg>auto-update<commit_after>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     September 14, 2020
;       related version of root zone:     2020091401
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<|endoftext|>


<commit_before>package main

import (
	//"debug/pe"
	"fmt"
	"os"
)

func main() {
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	if len(os.Args) <= 1 {
		return fmt.Errorf("USAGE: %s FILE.exe.manifest\n" +
			"Generates a.res\n")
	}
	return nil
}
<commit_msg>fixed help string<commit_after>package main

import (
	//"debug/pe"
	"fmt"
	"os"
)

func main() {
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	if len(os.Args) <= 1 {
		return fmt.Errorf("USAGE: %s FILE.exe.manifest\n"+
			"Generates FILE.res",
			os.Args[0])
	}
	return nil
}
<|endoftext|>


<commit_before>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2019 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * 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.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package lib

import (
	"encoding"
	"fmt"
	"math/big"
	"strings"
)

// ExecutionSegment represents a (start, end] partition of the total execution
// work for a specific test. For example, if we want the split the execution of a
// test in 2 different parts, we can split it in two segments (0, 0.5] and (0,5, 1].
//
// We use rational numbers so it's easier to verify the correctness and easier to
// reason about portions of indivisible things, like VUs. This way, we can easily
// split a test in thirds (i.e. (0, 1/3], (1/3, 2/3], (2/3, 1]), without fearing
// that we'll lose a VU along the way...
//
// The most important part is that if work is split between multiple k6 instances,
// each k6 instance can precisely and reproducably calculate its share of the work,
// just by knowing its own segment. There won't be a need to schedule the
// execution from a master node, or to even know how many other k6 instances are
// running!
type ExecutionSegment struct {
	// 0 <= from < to <= 1
	from *big.Rat
	to   *big.Rat

	// derived, equals to-from, but pre-calculated here for speed
	length *big.Rat
}

// Ensure we implement those interfaces
var _ encoding.TextUnmarshaler = &ExecutionSegment{}
var _ fmt.Stringer = &ExecutionSegment{}

// Helpful "constants" so we don't initialize them in every function call
var zeroRat, oneRat = big.NewRat(0, 1), big.NewRat(1, 1) //nolint:gochecknoglobals
var oneBigInt, twoBigInt = big.NewInt(1), big.NewInt(2)  //nolint:gochecknoglobals

// NewExecutionSegment validates the supplied arguments (basically, that 0 <=
// from < to <= 1) and either returns an error, or it returns a
// fully-initialized and usable execution segment.
func NewExecutionSegment(from, to *big.Rat) (*ExecutionSegment, error) {
	if from.Cmp(zeroRat) < 0 {
		return nil, fmt.Errorf("segment start value should be at least 0 but was %s", from.FloatString(2))
	}
	if from.Cmp(to) >= 0 {
		return nil, fmt.Errorf("segment start(%s) should be less than its end(%s)", from.FloatString(2), to.FloatString(2))
	}
	if to.Cmp(oneRat) > 0 {
		return nil, fmt.Errorf("segment end value shouldn't be more than 1 but was %s", to.FloatString(2))
	}
	return &ExecutionSegment{
		from:   from,
		to:     to,
		length: new(big.Rat).Sub(to, from),
	}, nil
}

// stringToRat is a helper function that tries to convert a string to a rational
// number while allowing percentage, decimal, and fraction values.
func stringToRat(s string) (*big.Rat, error) {
	if strings.HasSuffix(s, "%") {
		num, ok := new(big.Int).SetString(strings.TrimSuffix(s, "%"), 10)
		if !ok {
			return nil, fmt.Errorf("'%s' is not a valid percentage", s)
		}
		return new(big.Rat).SetFrac(num, big.NewInt(100)), nil
	}
	rat, ok := new(big.Rat).SetString(s)
	if !ok {
		return nil, fmt.Errorf("'%s' is not a valid percentage, decimal, fraction or interval value", s)
	}
	return rat, nil
}

// UnmarshalText implements the encoding.TextUnmarshaler interface, so that
// execution segments can be specified as CLI flags, environment variables, and
// JSON strings.
//
// We are able to parse both single percentage/float/fraction values, and actual
// (from; to] segments. For the single values, we just treat them as the
// beginning segment - thus the execution segment can be used as a shortcut for
// quickly running an arbitrarily scaled-down version of a test.
//
// The parsing logic is that values with a colon, i.e. ':', are full segments:
//  `1/2:3/4`, `0.5:0.75`, `50%:75%`, and even `2/4:75%` should be (1/2, 3/4]
// And values without a hyphen are the end of a first segment:
//  `20%`, `0.2`,  and `1/5` should be converted to (0, 1/5]
// empty values should probably be treated as "1", i.e. the whole execution
func (es *ExecutionSegment) UnmarshalText(text []byte) (err error) {
	from := zeroRat
	toStr := string(text)
	if strings.ContainsRune(toStr, ':') {
		fromToStr := strings.SplitN(toStr, ":", 2)
		toStr = fromToStr[1]
		if from, err = stringToRat(fromToStr[0]); err != nil {
			return err
		}
	}

	to, err := stringToRat(toStr)
	if err != nil {
		return err
	}

	segment, err := NewExecutionSegment(from, to)
	if err != nil {
		return err
	}
	*es = *segment
	return nil
}

func (es *ExecutionSegment) String() string {
	if es == nil {
		return "0:1"
	}
	return es.from.RatString() + ":" + es.to.RatString()
}

// FloatLength is a helper method for getting some more human-readable
// information about the execution segment.
func (es *ExecutionSegment) FloatLength() float64 {
	if es == nil {
		return 1.0
	}
	res, _ := es.length.Float64()
	return res
}

//TODO: add a NewFromString() and Split() methods

// helper function for rounding (up) of rational numbers to big.Int values
func roundUp(rat *big.Rat) *big.Int {
	quo, rem := new(big.Int).QuoRem(rat.Num(), rat.Denom(), new(big.Int))

	if rem.Mul(rem, twoBigInt).Cmp(rat.Denom()) >= 0 {
		return quo.Add(quo, oneBigInt)
	}
	return quo
}

// Scale proportionally scales the supplied value, according to the execution
// segment's position and size of the work.
func (es *ExecutionSegment) Scale(value int64) int64 {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	// Instead of the first proposal that used remainders and floor:
	//    floor( (value * from) % 1 + value * length )
	// We're using an alternative approach with rounding that (hopefully) has
	// the same properties, but it's simpler and has better precision:
	//    round( (value * from) - round(value * from) + (value * (to - from)) )?
	// which reduces to:
	//    round( (value * to) - round(value * from) )?

	toValue := big.NewRat(value, 1)
	toValue.Mul(toValue, es.to)

	fromValue := big.NewRat(value, 1)
	fromValue.Mul(fromValue, es.from)

	toValue.Sub(toValue, new(big.Rat).SetFrac(roundUp(fromValue), oneBigInt))

	return roundUp(toValue).Int64()
}

// InPlaceScaleRat scales rational numbers in-place - it changes the passed
// argument (and also returns it, to allow for chaining, like many other big.Rat
// methods).
func (es *ExecutionSegment) InPlaceScaleRat(value *big.Rat) *big.Rat {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	return value.Mul(value, es.length)
}

// CopyScaleRat scales rational numbers without changing them - creates a new
// bit.Rat object and uses it for the calculation.
func (es *ExecutionSegment) CopyScaleRat(value *big.Rat) *big.Rat {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	return new(big.Rat).Mul(value, es.length)
}
<commit_msg>Add a helper Split() method to execution segments<commit_after>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2019 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * 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.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package lib

import (
	"encoding"
	"fmt"
	"math/big"
	"strings"
)

// ExecutionSegment represents a (start, end] partition of the total execution
// work for a specific test. For example, if we want the split the execution of a
// test in 2 different parts, we can split it in two segments (0, 0.5] and (0,5, 1].
//
// We use rational numbers so it's easier to verify the correctness and easier to
// reason about portions of indivisible things, like VUs. This way, we can easily
// split a test in thirds (i.e. (0, 1/3], (1/3, 2/3], (2/3, 1]), without fearing
// that we'll lose a VU along the way...
//
// The most important part is that if work is split between multiple k6 instances,
// each k6 instance can precisely and reproducably calculate its share of the work,
// just by knowing its own segment. There won't be a need to schedule the
// execution from a master node, or to even know how many other k6 instances are
// running!
type ExecutionSegment struct {
	// 0 <= from < to <= 1
	from *big.Rat
	to   *big.Rat

	// derived, equals to-from, but pre-calculated here for speed
	length *big.Rat
}

// Ensure we implement those interfaces
var _ encoding.TextUnmarshaler = &ExecutionSegment{}
var _ fmt.Stringer = &ExecutionSegment{}

// Helpful "constants" so we don't initialize them in every function call
var zeroRat, oneRat = big.NewRat(0, 1), big.NewRat(1, 1) //nolint:gochecknoglobals
var oneBigInt, twoBigInt = big.NewInt(1), big.NewInt(2)  //nolint:gochecknoglobals

// NewExecutionSegment validates the supplied arguments (basically, that 0 <=
// from < to <= 1) and either returns an error, or it returns a
// fully-initialized and usable execution segment.
func NewExecutionSegment(from, to *big.Rat) (*ExecutionSegment, error) {
	if from.Cmp(zeroRat) < 0 {
		return nil, fmt.Errorf("segment start value should be at least 0 but was %s", from.FloatString(2))
	}
	if from.Cmp(to) >= 0 {
		return nil, fmt.Errorf("segment start(%s) should be less than its end(%s)", from.FloatString(2), to.FloatString(2))
	}
	if to.Cmp(oneRat) > 0 {
		return nil, fmt.Errorf("segment end value shouldn't be more than 1 but was %s", to.FloatString(2))
	}
	return &ExecutionSegment{
		from:   from,
		to:     to,
		length: new(big.Rat).Sub(to, from),
	}, nil
}

// stringToRat is a helper function that tries to convert a string to a rational
// number while allowing percentage, decimal, and fraction values.
func stringToRat(s string) (*big.Rat, error) {
	if strings.HasSuffix(s, "%") {
		num, ok := new(big.Int).SetString(strings.TrimSuffix(s, "%"), 10)
		if !ok {
			return nil, fmt.Errorf("'%s' is not a valid percentage", s)
		}
		return new(big.Rat).SetFrac(num, big.NewInt(100)), nil
	}
	rat, ok := new(big.Rat).SetString(s)
	if !ok {
		return nil, fmt.Errorf("'%s' is not a valid percentage, decimal, fraction or interval value", s)
	}
	return rat, nil
}

// UnmarshalText implements the encoding.TextUnmarshaler interface, so that
// execution segments can be specified as CLI flags, environment variables, and
// JSON strings.
//
// We are able to parse both single percentage/float/fraction values, and actual
// (from; to] segments. For the single values, we just treat them as the
// beginning segment - thus the execution segment can be used as a shortcut for
// quickly running an arbitrarily scaled-down version of a test.
//
// The parsing logic is that values with a colon, i.e. ':', are full segments:
//  `1/2:3/4`, `0.5:0.75`, `50%:75%`, and even `2/4:75%` should be (1/2, 3/4]
// And values without a hyphen are the end of a first segment:
//  `20%`, `0.2`,  and `1/5` should be converted to (0, 1/5]
// empty values should probably be treated as "1", i.e. the whole execution
func (es *ExecutionSegment) UnmarshalText(text []byte) (err error) {
	from := zeroRat
	toStr := string(text)
	if strings.ContainsRune(toStr, ':') {
		fromToStr := strings.SplitN(toStr, ":", 2)
		toStr = fromToStr[1]
		if from, err = stringToRat(fromToStr[0]); err != nil {
			return err
		}
	}

	to, err := stringToRat(toStr)
	if err != nil {
		return err
	}

	segment, err := NewExecutionSegment(from, to)
	if err != nil {
		return err
	}
	*es = *segment
	return nil
}

func (es *ExecutionSegment) String() string {
	if es == nil {
		return "0:1"
	}
	return es.from.RatString() + ":" + es.to.RatString()
}

// FloatLength is a helper method for getting some more human-readable
// information about the execution segment.
func (es *ExecutionSegment) FloatLength() float64 {
	if es == nil {
		return 1.0
	}
	res, _ := es.length.Float64()
	return res
}

// Split evenly dividies the execution segment into the specified number of
// equal consecutive execution sub-segments.
func (es *ExecutionSegment) Split(numParts int64) ([]*ExecutionSegment, error) {
	if numParts < 1 {
		return nil, fmt.Errorf("the number of parts should be at least 1, %d received", numParts)
	}

	from, to := zeroRat, oneRat
	if es != nil {
		from, to = es.from, es.to
	}

	increment := new(big.Rat).Sub(to, from)
	increment.Denom().Mul(increment.Denom(), big.NewInt(numParts))

	results := make([]*ExecutionSegment, numParts)
	for i := int64(0); i < numParts; i++ {
		segmentTo := new(big.Rat).Add(from, increment)
		segment, err := NewExecutionSegment(from, segmentTo)
		if err != nil {
			return nil, err
		}
		results[i] = segment
		from = segmentTo
	}

	if from.Cmp(to) != 0 {
		return nil, fmt.Errorf("Expected %s and %s to be equal", from, to)
	}

	return results, nil
}

//TODO: add a NewFromString() method

// helper function for rounding (up) of rational numbers to big.Int values
func roundUp(rat *big.Rat) *big.Int {
	quo, rem := new(big.Int).QuoRem(rat.Num(), rat.Denom(), new(big.Int))

	if rem.Mul(rem, twoBigInt).Cmp(rat.Denom()) >= 0 {
		return quo.Add(quo, oneBigInt)
	}
	return quo
}

// Scale proportionally scales the supplied value, according to the execution
// segment's position and size of the work.
func (es *ExecutionSegment) Scale(value int64) int64 {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	// Instead of the first proposal that used remainders and floor:
	//    floor( (value * from) % 1 + value * length )
	// We're using an alternative approach with rounding that (hopefully) has
	// the same properties, but it's simpler and has better precision:
	//    round( (value * from) - round(value * from) + (value * (to - from)) )?
	// which reduces to:
	//    round( (value * to) - round(value * from) )?

	toValue := big.NewRat(value, 1)
	toValue.Mul(toValue, es.to)

	fromValue := big.NewRat(value, 1)
	fromValue.Mul(fromValue, es.from)

	toValue.Sub(toValue, new(big.Rat).SetFrac(roundUp(fromValue), oneBigInt))

	return roundUp(toValue).Int64()
}

// InPlaceScaleRat scales rational numbers in-place - it changes the passed
// argument (and also returns it, to allow for chaining, like many other big.Rat
// methods).
func (es *ExecutionSegment) InPlaceScaleRat(value *big.Rat) *big.Rat {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	return value.Mul(value, es.length)
}

// CopyScaleRat scales rational numbers without changing them - creates a new
// bit.Rat object and uses it for the calculation.
func (es *ExecutionSegment) CopyScaleRat(value *big.Rat) *big.Rat {
	if es == nil { // no execution segment, i.e. 100%
		return value
	}
	return new(big.Rat).Mul(value, es.length)
}
<|endoftext|>