<commit_before>/*
** Copyright [2012-2014] [Megam Systems]
**
** 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 action

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"sync"
)

// Result is the value returned by Forward. It is used in the call of the next
// action, and also when rolling back the actions.
type Result interface{}

// Forward is the function called by the pipeline executor in the forward
// phase.  It receives a FWContext instance, that contains the list of
// parameters given to the pipeline executor and the result of the previous
// action in the pipeline (which will be nil for the first action in the
// pipeline).
type Forward func(context FWContext) (Result, error)

// Backward is the function called by the pipeline executor when in the
// backward phase. It receives the context instance, that contains the list of
// parameters given to the pipeline executor and the result of the forward
// phase.
type Backward func(context BWContext)

type OnErrorFunc func(FWContext, error)

// FWContext is the context used in calls to Forward functions (forward phase).
type FWContext struct {
	// Result of the previous action.
	Previous Result

	// List of parameters given to the executor.
	Params []interface{}
}

// BWContext is the context used in calls to Backward functions (backward
// phase).
type BWContext struct {
	// Result of the forward phase (for the current action).
	FWResult Result

	// List of parameters given to the executor.
	Params []interface{}
}

// Action defines actions that should be . It is composed of two functions:
// Forward and Backward.
//
// Each action should do only one thing, and do it well. All information that
// is needed to undo the action should be returned by the Forward function.
type Action struct {
	// Name is the action name. Used by the log.
	Name string

	// Function that will be invoked in the forward phase. This value
	// cannot be nil.
	Forward Forward

	// Function that will be invoked in the backward phase. For actions
	// that are not undoable, this attribute should be nil.
	Backward Backward

	// Minimum number of parameters that this action requires to run.
	MinParams int

	// Function taht will be invoked after some failure occurured in the
	// Forward phase of this same action.
	OnError OnErrorFunc

	// Result of the action. Stored for use in the backward phase.
	result Result

	// mutex for the result
	rMutex sync.Mutex
}

// Pipeline is a list of actions. Each pipeline is atomic: either all actions
// are successfully executed, or none of them are. For that, it's fundamental
// that all actions are really small and atomic.
type Pipeline struct {
	actions []*Action
}

// NewPipeline creates a new pipeline instance with the given list of actions.
func NewPipeline(actions ...*Action) *Pipeline {
	return &Pipeline{actions: actions}
}

func (p *Pipeline) Result() Result {
	action := p.actions[len(p.actions)-1]
	action.rMutex.Lock()
	defer action.rMutex.Unlock()
	return action.result
}

// Execute executes the pipeline.
//
// The execution starts in the forward phase, calling the Forward function of
// all actions. If none of the Forward calls return error, the pipeline
// execution ends in the forward phase and is "committed".
//
// If any of the Forward calls fails, the executor switches to the backward phase
// (roll back) and call the Backward function for each action completed. It
// does not call the Backward function of the action that has failed.
//
// After rolling back all completed actions, it returns the original error
// returned by the action that failed.
func (p *Pipeline) Execute(params ...interface{}) error {
	var (
		r   Result
		err error
	)
	if len(p.actions) == 0 {
		return errors.New("No actions to execute.")
	}
	log.Debugf("   ----> <pipe> [%d]", len(p.actions))

	fwCtx := FWContext{Params: params}
	for i, a := range p.actions {
		log.Debugf("  ====> step %d: %s action +>>", i, a.Name)
		if a.Forward == nil {
			err = errors.New("All actions must define the forward function.")
		} else if len(fwCtx.Params) < a.MinParams {
			err = errors.New("Not enough parameters to call Action.Forward.")
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Debugf("  ====> step %d: %s action +>> error - %s", i, a.Name, err)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	log.Debugf("   !----> <pipe> [%d] !.", len(p.actions))
	return nil
}

func (p *Pipeline) rollback(index int, params []interface{}) {
	bwCtx := BWContext{Params: params}
	for i := index; i >= 0; i-- {
		log.Debugf("  <==== step %d: %s action <<+", i, p.actions[i].Name)
		if p.actions[i].Backward != nil {
			bwCtx.FWResult = p.actions[i].result
			p.actions[i].Backward(bwCtx)
		}
	}
}
<commit_msg>minor cleanup of log msgs<commit_after>/*
** Copyright [2012-2014] [Megam Systems]
**
** 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 action

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"sync"
)

// Result is the value returned by Forward. It is used in the call of the next
// action, and also when rolling back the actions.
type Result interface{}

// Forward is the function called by the pipeline executor in the forward
// phase.  It receives a FWContext instance, that contains the list of
// parameters given to the pipeline executor and the result of the previous
// action in the pipeline (which will be nil for the first action in the
// pipeline).
type Forward func(context FWContext) (Result, error)

// Backward is the function called by the pipeline executor when in the
// backward phase. It receives the context instance, that contains the list of
// parameters given to the pipeline executor and the result of the forward
// phase.
type Backward func(context BWContext)

type OnErrorFunc func(FWContext, error)

// FWContext is the context used in calls to Forward functions (forward phase).
type FWContext struct {
	// Result of the previous action.
	Previous Result

	// List of parameters given to the executor.
	Params []interface{}
}

// BWContext is the context used in calls to Backward functions (backward
// phase).
type BWContext struct {
	// Result of the forward phase (for the current action).
	FWResult Result

	// List of parameters given to the executor.
	Params []interface{}
}

// Action defines actions that should be . It is composed of two functions:
// Forward and Backward.
//
// Each action should do only one thing, and do it well. All information that
// is needed to undo the action should be returned by the Forward function.
type Action struct {
	// Name is the action name. Used by the log.
	Name string

	// Function that will be invoked in the forward phase. This value
	// cannot be nil.
	Forward Forward

	// Function that will be invoked in the backward phase. For actions
	// that are not undoable, this attribute should be nil.
	Backward Backward

	// Minimum number of parameters that this action requires to run.
	MinParams int

	// Function taht will be invoked after some failure occurured in the
	// Forward phase of this same action.
	OnError OnErrorFunc

	// Result of the action. Stored for use in the backward phase.
	result Result

	// mutex for the result
	rMutex sync.Mutex
}

// Pipeline is a list of actions. Each pipeline is atomic: either all actions
// are successfully executed, or none of them are. For that, it's fundamental
// that all actions are really small and atomic.
type Pipeline struct {
	actions []*Action
}

// NewPipeline creates a new pipeline instance with the given list of actions.
func NewPipeline(actions ...*Action) *Pipeline {
	return &Pipeline{actions: actions}
}

func (p *Pipeline) Result() Result {
	action := p.actions[len(p.actions)-1]
	action.rMutex.Lock()
	defer action.rMutex.Unlock()
	return action.result
}

// Execute executes the pipeline.
//
// The execution starts in the forward phase, calling the Forward function of
// all actions. If none of the Forward calls return error, the pipeline
// execution ends in the forward phase and is "committed".
//
// If any of the Forward calls fails, the executor switches to the backward phase
// (roll back) and call the Backward function for each action completed. It
// does not call the Backward function of the action that has failed.
//
// After rolling back all completed actions, it returns the original error
// returned by the action that failed.
func (p *Pipeline) Execute(params ...interface{}) error {
	var (
		r   Result
		err error
	)
	if len(p.actions) == 0 {
		return errors.New("No actions to execute.")
	}
	log.Debugf("   =====> pipe [%d]", len(p.actions))

	fwCtx := FWContext{Params: params}
	for i, a := range p.actions {
		log.Debugf("  ====> step> %d: %s action", i, a.Name)
		if a.Forward == nil {
			err = errors.New("All actions must define the forward function.")
		} else if len(fwCtx.Params) < a.MinParams {
			err = errors.New("Not enough parameters to call Action.Forward.")
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Debugf("  ====> step> %d: %s action error - %s", i, a.Name, err)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	log.Debugf("   !====> pipe [%d] !.", len(p.actions))
	return nil
}

func (p *Pipeline) rollback(index int, params []interface{}) {
	bwCtx := BWContext{Params: params}
	for i := index; i >= 0; i-- {
		log.Debugf("  ====> <step %d: %s action", i, p.actions[i].Name)
		if p.actions[i].Backward != nil {
			bwCtx.FWResult = p.actions[i].result
			p.actions[i].Backward(bwCtx)
		}
	}
}
<|endoftext|>


<commit_before>package action

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"github.com/miclle/lisa/msg"
	"github.com/skratchdot/open-golang/open"
)

type server struct {
	port                int
	bind, dir, absolute string
}

// Server : Serving Static Files with HTTP
func Server(port int, bind, dir string) {
	s := &server{
		bind: bind,
		port: port,
		dir:  dir,
	}

	if s.port == 0 {
		s.port = 8080
	}

	var err error
	s.absolute, err = filepath.Abs(dir)

	if err != nil {
		msg.Err(err.Error())
		return
	}

	http.HandleFunc("/", s.handleFunc)

	msg.Info(fmt.Sprintf("Serving HTTP on %s port %d ...", s.bind, s.port))

	// open URI using the OS's default browser
	if err := open.Run(fmt.Sprintf("http://%s:%d", s.bind, s.port)); err != nil {
		msg.Err(err.Error())
	}

	addr := fmt.Sprintf("%s:%d", s.bind, s.port)
	if err := http.ListenAndServe(addr, nil); err != nil {
		msg.Err(err.Error())
		return
	}
}

func (s *server) handleFunc(w http.ResponseWriter, r *http.Request) {
	dir := s.absolute + r.URL.Path

	if _, err := os.Stat(dir); err != nil {

		if os.IsNotExist(err) {
			msg.Err(s.requestInfo(r, 404))
			http.NotFound(w, r)
			return
		}

		msg.Err(s.requestInfo(r, 500))
		http.Error(w, err.Error(), 500)
		return
	}

	msg.Info(s.requestInfo(r, 200))
	http.ServeFile(w, r, dir)
}

func (s *server) requestInfo(r *http.Request, code int) string {
	return fmt.Sprintf("%s\t%s\t%d\t%s\t%s", r.RemoteAddr, r.Method, code, r.URL.Path, r.URL.RawQuery)
}
<commit_msg>Update log info.<commit_after>package action

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"github.com/miclle/lisa/msg"
	"github.com/skratchdot/open-golang/open"
)

type server struct {
	port                int
	bind, dir, absolute string
}

// Server : Serving Static Files with HTTP
func Server(port int, bind, dir string) {
	s := &server{
		bind: bind,
		port: port,
		dir:  dir,
	}

	if s.port == 0 {
		s.port = 8080
	}

	var err error
	s.absolute, err = filepath.Abs(dir)

	if err != nil {
		msg.Err(err.Error())
		return
	}

	http.HandleFunc("/", s.handleFunc)

	msg.Info("Serving HTTP on %s port %d ...", s.bind, s.port)

	// open URI using the OS's default browser
	if err := open.Run(fmt.Sprintf("http://%s:%d", s.bind, s.port)); err != nil {
		msg.Err(err.Error())
	}

	addr := fmt.Sprintf("%s:%d", s.bind, s.port)
	if err := http.ListenAndServe(addr, nil); err != nil {
		msg.Err(err.Error())
		return
	}
}

func (s *server) handleFunc(w http.ResponseWriter, r *http.Request) {
	dir := s.absolute + r.URL.Path

	if _, err := os.Stat(dir); err != nil {

		if os.IsNotExist(err) {
			msg.Err(s.requestInfo(r, 404))
			http.NotFound(w, r)
			return
		}

		msg.Err(s.requestInfo(r, 500))
		http.Error(w, err.Error(), 500)
		return
	}

	msg.Info(s.requestInfo(r, 200))
	http.ServeFile(w, r, dir)
}

func (s *server) requestInfo(r *http.Request, code int) string {
	return fmt.Sprintf("%s\t%s\t%d\t%s\t%s", r.RemoteAddr, r.Method, code, r.URL.Path, r.URL.RawQuery)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"github.com/timakin/ts/loader"
	"github.com/codegangsta/cli"
)

var Commands = []cli.Command{
	commandAll,
	commandBiz,
	commandHack,
}

var commandAll = cli.Command{
	Name:  "all",
	Usage: "",
	Description: `
`,
	Action: doAll,
}

var commandBiz = cli.Command{
	Name:  "biz",
	Usage: "",
	Description: `
`,
	Action: doBiz,
}

var commandHack = cli.Command{
	Name:  "hack",
	Usage: "",
	Description: `
`,
	Action: doHack,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doAll(c *cli.Context) {
	hn := make(chan loader.ResultData)
	go loader.GetHNFeed(hn)
	phres := <- hn
	var HNData loader.Feed = &phres
	HNData.Display()
	loader.GetPHFeed()
}

func doBiz(c *cli.Context) {
}

func doHack(c *cli.Context) {
}
<commit_msg>Add ProductHunt feed<commit_after>package main

import (
	"log"
	"os"
	"github.com/timakin/ts/loader"
	"github.com/codegangsta/cli"
)

var Commands = []cli.Command{
	commandAll,
	commandBiz,
	commandHack,
}

var commandAll = cli.Command{
	Name:  "all",
	Usage: "",
	Description: `
`,
	Action: doAll,
}

var commandBiz = cli.Command{
	Name:  "biz",
	Usage: "",
	Description: `
`,
	Action: doBiz,
}

var commandHack = cli.Command{
	Name:  "hack",
	Usage: "",
	Description: `
`,
	Action: doHack,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doAll(c *cli.Context) {
	hn := make(chan loader.ResultData)
	ph := make(chan loader.ResultData)
	go loader.GetHNFeed(hn)
	go loader.GetPHFeed(ph)
	hnres := <- hn
	phres := <- ph
	var HNData loader.Feed = &hnres
	var PHData loader.Feed = &phres
	HNData.Display()
	PHData.Display()
}

func doBiz(c *cli.Context) {
}

func doHack(c *cli.Context) {
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/hashicorp/consul/command"
	"github.com/hashicorp/consul/command/agent"
	"github.com/hashicorp/consul/version"
	"github.com/mitchellh/cli"
)

// Commands is the mapping of all the available Consul commands.
var Commands map[string]cli.CommandFactory

func init() {
	ui := &cli.BasicUi{Writer: os.Stdout}

	Commands = map[string]cli.CommandFactory{
		"agent": func() (cli.Command, error) {
			return &agent.Command{
				Revision:          version.GitCommit,
				Version:           version.Version,
				VersionPrerelease: version.VersionPrerelease,
				HumanVersion:      version.GetHumanVersion(),
				Ui:                ui,
				ShutdownCh:        make(chan struct{}),
			}, nil
		},

		"configtest": func() (cli.Command, error) {
			return &command.ConfigTestCommand{
				Ui: ui,
			}, nil
		},

		"event": func() (cli.Command, error) {
			return &command.EventCommand{
				Ui: ui,
			}, nil
		},

		"exec": func() (cli.Command, error) {
			return &command.ExecCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"force-leave": func() (cli.Command, error) {
			return &command.ForceLeaveCommand{
				Ui: ui,
			}, nil
		},

		"kv": func() (cli.Command, error) {
			return &command.KVCommand{
				Ui: ui,
			}, nil
		},

		"kv delete": func() (cli.Command, error) {
			return &command.KVDeleteCommand{
				Ui: ui,
			}, nil
		},

		"kv get": func() (cli.Command, error) {
			return &command.KVGetCommand{
				Ui: ui,
			}, nil
		},

		"kv put": func() (cli.Command, error) {
			return &command.KVPutCommand{
				Ui: ui,
			}, nil
		},

		"join": func() (cli.Command, error) {
			return &command.JoinCommand{
				Ui: ui,
			}, nil
		},

		"keygen": func() (cli.Command, error) {
			return &command.KeygenCommand{
				Ui: ui,
			}, nil
		},

		"keyring": func() (cli.Command, error) {
			return &command.KeyringCommand{
				Ui: ui,
			}, nil
		},

		"leave": func() (cli.Command, error) {
			return &command.LeaveCommand{
				Ui: ui,
			}, nil
		},

		"lock": func() (cli.Command, error) {
			return &command.LockCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"maint": func() (cli.Command, error) {
			return &command.MaintCommand{
				Ui: ui,
			}, nil
		},

		"members": func() (cli.Command, error) {
			return &command.MembersCommand{
				Ui: ui,
			}, nil
		},

		"monitor": func() (cli.Command, error) {
			return &command.MonitorCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"operator": func() (cli.Command, error) {
			return &command.OperatorCommand{
				Ui: ui,
			}, nil
		},

		"info": func() (cli.Command, error) {
			return &command.InfoCommand{
				Ui: ui,
			}, nil
		},

		"reload": func() (cli.Command, error) {
			return &command.ReloadCommand{
				Ui: ui,
			}, nil
		},

		"rtt": func() (cli.Command, error) {
			return &command.RTTCommand{
				Ui: ui,
			}, nil
		},

		"snapshot": func() (cli.Command, error) {
			return &command.SnapshotCommand{
				Ui: ui,
			}, nil
		},

		"snapshot restore": func() (cli.Command, error) {
			return &command.SnapshotRestoreCommand{
				Ui: ui,
			}, nil
		},

		"snapshot save": func() (cli.Command, error) {
			return &command.SnapshotSaveCommand{
				Ui: ui,
			}, nil
		},

		"snapshot inspect": func() (cli.Command, error) {
			return &command.SnapshotInspectCommand{
				Ui: ui,
			}, nil
		},

		"version": func() (cli.Command, error) {
			return &command.VersionCommand{
				HumanVersion: version.GetHumanVersion(),
				Ui:           ui,
			}, nil
		},

		"watch": func() (cli.Command, error) {
			return &command.WatchCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},
	}
}

// makeShutdownCh returns a channel that can be used for shutdown
// notifications for commands. This channel will send a message for every
// interrupt or SIGTERM received.
func makeShutdownCh() <-chan struct{} {
	resultCh := make(chan struct{})

	signalCh := make(chan os.Signal, 4)
	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
	go func() {
		for {
			<-signalCh
			resultCh <- struct{}{}
		}
	}()

	return resultCh
}
<commit_msg>Use ErrorWriter in cli so that errors get written to stderr<commit_after>package main

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/hashicorp/consul/command"
	"github.com/hashicorp/consul/command/agent"
	"github.com/hashicorp/consul/version"
	"github.com/mitchellh/cli"
)

// Commands is the mapping of all the available Consul commands.
var Commands map[string]cli.CommandFactory

func init() {
	ui := &cli.BasicUi{Writer: os.Stdout, ErrorWriter: os.Stderr}

	Commands = map[string]cli.CommandFactory{
		"agent": func() (cli.Command, error) {
			return &agent.Command{
				Revision:          version.GitCommit,
				Version:           version.Version,
				VersionPrerelease: version.VersionPrerelease,
				HumanVersion:      version.GetHumanVersion(),
				Ui:                ui,
				ShutdownCh:        make(chan struct{}),
			}, nil
		},

		"configtest": func() (cli.Command, error) {
			return &command.ConfigTestCommand{
				Ui: ui,
			}, nil
		},

		"event": func() (cli.Command, error) {
			return &command.EventCommand{
				Ui: ui,
			}, nil
		},

		"exec": func() (cli.Command, error) {
			return &command.ExecCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"force-leave": func() (cli.Command, error) {
			return &command.ForceLeaveCommand{
				Ui: ui,
			}, nil
		},

		"kv": func() (cli.Command, error) {
			return &command.KVCommand{
				Ui: ui,
			}, nil
		},

		"kv delete": func() (cli.Command, error) {
			return &command.KVDeleteCommand{
				Ui: ui,
			}, nil
		},

		"kv get": func() (cli.Command, error) {
			return &command.KVGetCommand{
				Ui: ui,
			}, nil
		},

		"kv put": func() (cli.Command, error) {
			return &command.KVPutCommand{
				Ui: ui,
			}, nil
		},

		"join": func() (cli.Command, error) {
			return &command.JoinCommand{
				Ui: ui,
			}, nil
		},

		"keygen": func() (cli.Command, error) {
			return &command.KeygenCommand{
				Ui: ui,
			}, nil
		},

		"keyring": func() (cli.Command, error) {
			return &command.KeyringCommand{
				Ui: ui,
			}, nil
		},

		"leave": func() (cli.Command, error) {
			return &command.LeaveCommand{
				Ui: ui,
			}, nil
		},

		"lock": func() (cli.Command, error) {
			return &command.LockCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"maint": func() (cli.Command, error) {
			return &command.MaintCommand{
				Ui: ui,
			}, nil
		},

		"members": func() (cli.Command, error) {
			return &command.MembersCommand{
				Ui: ui,
			}, nil
		},

		"monitor": func() (cli.Command, error) {
			return &command.MonitorCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},

		"operator": func() (cli.Command, error) {
			return &command.OperatorCommand{
				Ui: ui,
			}, nil
		},

		"info": func() (cli.Command, error) {
			return &command.InfoCommand{
				Ui: ui,
			}, nil
		},

		"reload": func() (cli.Command, error) {
			return &command.ReloadCommand{
				Ui: ui,
			}, nil
		},

		"rtt": func() (cli.Command, error) {
			return &command.RTTCommand{
				Ui: ui,
			}, nil
		},

		"snapshot": func() (cli.Command, error) {
			return &command.SnapshotCommand{
				Ui: ui,
			}, nil
		},

		"snapshot restore": func() (cli.Command, error) {
			return &command.SnapshotRestoreCommand{
				Ui: ui,
			}, nil
		},

		"snapshot save": func() (cli.Command, error) {
			return &command.SnapshotSaveCommand{
				Ui: ui,
			}, nil
		},

		"snapshot inspect": func() (cli.Command, error) {
			return &command.SnapshotInspectCommand{
				Ui: ui,
			}, nil
		},

		"version": func() (cli.Command, error) {
			return &command.VersionCommand{
				HumanVersion: version.GetHumanVersion(),
				Ui:           ui,
			}, nil
		},

		"watch": func() (cli.Command, error) {
			return &command.WatchCommand{
				ShutdownCh: makeShutdownCh(),
				Ui:         ui,
			}, nil
		},
	}
}

// makeShutdownCh returns a channel that can be used for shutdown
// notifications for commands. This channel will send a message for every
// interrupt or SIGTERM received.
func makeShutdownCh() <-chan struct{} {
	resultCh := make(chan struct{})

	signalCh := make(chan os.Signal, 4)
	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
	go func() {
		for {
			<-signalCh
			resultCh <- struct{}{}
		}
	}()

	return resultCh
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/bwmarrin/discordgo"
)

const commandPrefix = `$`

func messageCreateHandler(s *discordgo.Session, m *discordgo.MessageCreate) {

	user, _ := s.User("@me")
	if m.Author.ID != user.ID {
		s.ChannelMessageSend(botTestChannel, fmt.Sprintf("%s schrieb: %s", m.Author.Username, m.Content))

		if !strings.HasPrefix(m.Content, commandPrefix) {
			return
		}

	}
}
<commit_msg>Add help command<commit_after>package main

import (
	"fmt"
	"strings"

	"github.com/bwmarrin/discordgo"
)

const commandPrefix = `$`

func messageCreateHandler(s *discordgo.Session, m *discordgo.MessageCreate) {

	user, _ := s.User("@me")
	if m.Author.ID != user.ID {
		s.ChannelMessageSend(botTestChannel, fmt.Sprintf("%s schrieb: %s", m.Author.Username, m.Content))

		if !strings.HasPrefix(m.Content, commandPrefix) {
			return
		}

		strAr := strings.Split(m.Content, " ")
		str := strings.Replace(strAr[0], commandPrefix, "", 1)

		switch str {
		case "help":
			s.ChannelMessageSend(m.ChannelID, "Hallo")
		}

	}
}
<|endoftext|>


<commit_before>// Copyright 2012 The Go-Commander Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// Based on the original work by The Go Authors:
// Copyright 2011 The Go Authors.  All rights reserved.

// commander helps creating command line programs whose arguments are flags,
// commands and subcommands.
package commander

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"sort"
	"strings"
	"text/template"

	"github.com/gonuts/flag"
)

// UsageSection differentiates between sections in the usage text.
type Listing int

const (
	CommandsList = iota
	HelpTopicsList
	Unlisted
)

// A Command is an implementation of a subcommand.
type Command struct {

	// UsageLine is the short usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description line shown in command lists.
	Short string

	// Long is the long description shown in the 'help <this-command>' output.
	Long string

	// List reports which list to show this command in Usage and Help.
	// Choose between {CommandsList (default), HelpTopicsList, Unlisted}
	List Listing

	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string) error

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool

	// Subcommands are dispatched from this command
	Subcommands []*Command

	// Parent command, nil for root.
	Parent *Command

	// UsageTemplate formats the usage (short) information displayed to the user
	// (leave empty for default)
	UsageTemplate string

	// HelpTemplate formats the help (long) information displayed to the user
	// (leave empty for default)
	HelpTemplate string

	// Stdout and Stderr by default are os.Stdout and os.Stderr, but you can
	// point them at any io.Writer
	Stdout io.Writer
	Stderr io.Writer
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// Usage prints the usage details to the standard error output.
func (c *Command) Usage() {
	c.usage()
}

// FlagOptions returns the flag's options as a string
func (c *Command) FlagOptions() string {
	var buf bytes.Buffer
	c.Flag.SetOutput(&buf)
	c.Flag.PrintDefaults()

	str := string(buf.Bytes())
	if len(str) > 0 {
		return fmt.Sprintf("\nOptions:\n%s", str)
	}
	return ""
}

// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Type to allow us to use sort.Sort on a slice of Commands
type CommandSlice []*Command

func (c CommandSlice) Len() int {
	return len(c)
}

func (c CommandSlice) Less(i, j int) bool {
	return c[i].Name() < c[j].Name()
}

func (c CommandSlice) Swap(i, j int) {
	c[i], c[j] = c[j], c[i]
}

// Sort the commands
func (c *Command) SortCommands() {
	sort.Sort(CommandSlice(c.Subcommands))
}

// Init the command
func (c *Command) init() {
	if c.Parent != nil {
		return // already initialized.
	}

	// setup strings
	if len(c.UsageLine) < 1 {
		c.UsageLine = Defaults.UsageLine
	}
	if len(c.UsageTemplate) < 1 {
		c.UsageTemplate = Defaults.UsageTemplate
	}
	if len(c.HelpTemplate) < 1 {
		c.HelpTemplate = Defaults.HelpTemplate
	}

	if c.Stderr == nil {
		c.Stderr = os.Stderr
	}
	if c.Stdout == nil {
		c.Stdout = os.Stdout
	}

	// init subcommands
	for _, cmd := range c.Subcommands {
		cmd.init()
	}

	// init hierarchy...
	for _, cmd := range c.Subcommands {
		cmd.Parent = c
	}
}

// Dispatch executes the command using the provided arguments.
// If a subcommand exists matching the first argument, it is dispatched.
// Otherwise, the command's Run function is called.
func (c *Command) Dispatch(args []string) error {
	if c == nil {
		return fmt.Errorf("Called Run() on a nil Command")
	}

	// Ensure command is initialized.
	c.init()

	// First, try a sub-command
	if len(args) > 0 {
		for _, cmd := range c.Subcommands {
			n := cmd.Name()
			if n == args[0] {
				return cmd.Dispatch(args[1:])
			}
		}

		// help is builtin (but after, to allow overriding)
		if args[0] == "help" {
			return c.help(args[1:])
		}

		// then, try out an external binary (git-style)
		bin, err := exec.LookPath(c.FullName() + "-" + args[0])
		if err == nil {
			cmd := exec.Command(bin, args[1:]...)
			cmd.Stdin = os.Stdin
			cmd.Stdout = c.Stdout
			cmd.Stderr = c.Stderr
			return cmd.Run()
		}
	}

	// then, try running this command
	if c.Runnable() {
		if !c.CustomFlags {
			var err = error(nil)
			c.Flag.Usage = func() {
				c.Usage()
				err = fmt.Errorf("Failed to parse flags.")
			}
			c.Flag.Parse(args)
			if err != nil {
				return err
			}
			args = c.Flag.Args()
		}
		return c.Run(c, args)
	}

	// TODO: try an alias
	//...

	// Last, print usage
	if err := c.usage(); err != nil {
		return err
	}
	return nil
}

func (c *Command) usage() error {
	c.SortCommands()
	err := tmpl(c.Stderr, c.UsageTemplate, c)
	if err != nil {
		fmt.Println(err)
	}
	return err
}

// help implements the 'help' command.
func (c *Command) help(args []string) error {

	// help exactly for this command?
	if len(args) == 0 {
		if len(c.Long) > 0 {
			return tmpl(c.Stdout, c.HelpTemplate, c)
		} else {
			return c.usage()
		}
	}

	arg := args[0]

	// is this help for a subcommand?
	for _, cmd := range c.Subcommands {
		n := cmd.Name()
		// strip out "<parent>-"" name
		if strings.HasPrefix(n, c.Name()+"-") {
			n = n[len(c.Name()+"-"):]
		}
		if n == arg {
			return cmd.help(args[1:])
		}
	}

	return fmt.Errorf("Unknown help topic %#q.  Run '%v help'.\n", arg, c.Name())
}

func (c *Command) MaxLen() (res int) {
	res = 0
	for _, cmd := range c.Subcommands {
		i := len(cmd.Name())
		if i > res {
			res = i
		}
	}
	return
}

// ColFormat returns the column header size format for printing in the template
func (c *Command) ColFormat() string {
	sz := c.MaxLen()
	if sz < 11 {
		sz = 11
	}
	return fmt.Sprintf("%%-%ds", sz)
}

// FullName returns the full name of the command, prefixed with parent commands
func (c *Command) FullName() string {
	n := c.Name()
	if c.Parent != nil {
		n = c.Parent.FullName() + "-" + n
	}
	return n
}

// FullSpacedName returns the full name of the command, with ' ' instead of '-'
func (c *Command) FullSpacedName() string {
	n := c.Name()
	if c.Parent != nil {
		n = c.Parent.FullSpacedName() + " " + n
	}
	return n
}

func (c *Command) SubcommandList(list Listing) []*Command {
	var cmds []*Command
	for _, cmd := range c.Subcommands {
		if cmd.List == list {
			cmds = append(cmds, cmd)
		}
	}
	return cmds
}

var Defaults = Command{
	UsageTemplate: `{{if .Runnable}}Usage: {{.Parent.FullSpacedName}} {{.UsageLine}}

{{end}}{{.FullSpacedName}} - {{.Short}}

{{if commandList}}Commands:
{{range commandList}}
    {{.Name | printf (colfmt)}} {{.Short}}{{end}}

Use "{{.Name}} help <command>" for more information about a command.

{{end}}{{.FlagOptions}}{{if helpList}}
Additional help topics:
{{range helpList}}
    {{.Name | printf (colfmt)}} {{.Short}}{{end}}

Use "{{.Name}} help <topic>" for more information about that topic.

{{end}}`,

	HelpTemplate: `{{if .Runnable}}Usage: {{.Parent.FullSpacedName}} {{.UsageLine}}

{{end}}{{.Long | trim}}
{{.FlagOptions}}
`,
}

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) error {
	t := template.New("top")
	t.Funcs(template.FuncMap{
		"trim":        strings.TrimSpace,
		"colfmt":      func() string { return data.(*Command).ColFormat() },
		"commandList": func() []*Command { return data.(*Command).SubcommandList(CommandsList) },
		"helpList":    func() []*Command { return data.(*Command).SubcommandList(HelpTopicsList) },
	})
	template.Must(t.Parse(text))
	return t.Execute(w, data)
}
<commit_msg>bugfix: nil .Parent in template<commit_after>// Copyright 2012 The Go-Commander Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// Based on the original work by The Go Authors:
// Copyright 2011 The Go Authors.  All rights reserved.

// commander helps creating command line programs whose arguments are flags,
// commands and subcommands.
package commander

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"sort"
	"strings"
	"text/template"

	"github.com/gonuts/flag"
)

// UsageSection differentiates between sections in the usage text.
type Listing int

const (
	CommandsList = iota
	HelpTopicsList
	Unlisted
)

// A Command is an implementation of a subcommand.
type Command struct {

	// UsageLine is the short usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description line shown in command lists.
	Short string

	// Long is the long description shown in the 'help <this-command>' output.
	Long string

	// List reports which list to show this command in Usage and Help.
	// Choose between {CommandsList (default), HelpTopicsList, Unlisted}
	List Listing

	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string) error

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool

	// Subcommands are dispatched from this command
	Subcommands []*Command

	// Parent command, nil for root.
	Parent *Command

	// UsageTemplate formats the usage (short) information displayed to the user
	// (leave empty for default)
	UsageTemplate string

	// HelpTemplate formats the help (long) information displayed to the user
	// (leave empty for default)
	HelpTemplate string

	// Stdout and Stderr by default are os.Stdout and os.Stderr, but you can
	// point them at any io.Writer
	Stdout io.Writer
	Stderr io.Writer
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// Usage prints the usage details to the standard error output.
func (c *Command) Usage() {
	c.usage()
}

// FlagOptions returns the flag's options as a string
func (c *Command) FlagOptions() string {
	var buf bytes.Buffer
	c.Flag.SetOutput(&buf)
	c.Flag.PrintDefaults()

	str := string(buf.Bytes())
	if len(str) > 0 {
		return fmt.Sprintf("\nOptions:\n%s", str)
	}
	return ""
}

// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Type to allow us to use sort.Sort on a slice of Commands
type CommandSlice []*Command

func (c CommandSlice) Len() int {
	return len(c)
}

func (c CommandSlice) Less(i, j int) bool {
	return c[i].Name() < c[j].Name()
}

func (c CommandSlice) Swap(i, j int) {
	c[i], c[j] = c[j], c[i]
}

// Sort the commands
func (c *Command) SortCommands() {
	sort.Sort(CommandSlice(c.Subcommands))
}

// Init the command
func (c *Command) init() {
	if c.Parent != nil {
		return // already initialized.
	}

	// setup strings
	if len(c.UsageLine) < 1 {
		c.UsageLine = Defaults.UsageLine
	}
	if len(c.UsageTemplate) < 1 {
		c.UsageTemplate = Defaults.UsageTemplate
	}
	if len(c.HelpTemplate) < 1 {
		c.HelpTemplate = Defaults.HelpTemplate
	}

	if c.Stderr == nil {
		c.Stderr = os.Stderr
	}
	if c.Stdout == nil {
		c.Stdout = os.Stdout
	}

	// init subcommands
	for _, cmd := range c.Subcommands {
		cmd.init()
	}

	// init hierarchy...
	for _, cmd := range c.Subcommands {
		cmd.Parent = c
	}
}

// Dispatch executes the command using the provided arguments.
// If a subcommand exists matching the first argument, it is dispatched.
// Otherwise, the command's Run function is called.
func (c *Command) Dispatch(args []string) error {
	if c == nil {
		return fmt.Errorf("Called Run() on a nil Command")
	}

	// Ensure command is initialized.
	c.init()

	// First, try a sub-command
	if len(args) > 0 {
		for _, cmd := range c.Subcommands {
			n := cmd.Name()
			if n == args[0] {
				return cmd.Dispatch(args[1:])
			}
		}

		// help is builtin (but after, to allow overriding)
		if args[0] == "help" {
			return c.help(args[1:])
		}

		// then, try out an external binary (git-style)
		bin, err := exec.LookPath(c.FullName() + "-" + args[0])
		if err == nil {
			cmd := exec.Command(bin, args[1:]...)
			cmd.Stdin = os.Stdin
			cmd.Stdout = c.Stdout
			cmd.Stderr = c.Stderr
			return cmd.Run()
		}
	}

	// then, try running this command
	if c.Runnable() {
		if !c.CustomFlags {
			var err = error(nil)
			c.Flag.Usage = func() {
				c.Usage()
				err = fmt.Errorf("Failed to parse flags.")
			}
			c.Flag.Parse(args)
			if err != nil {
				return err
			}
			args = c.Flag.Args()
		}
		return c.Run(c, args)
	}

	// TODO: try an alias
	//...

	// Last, print usage
	if err := c.usage(); err != nil {
		return err
	}
	return nil
}

func (c *Command) usage() error {
	c.SortCommands()
	err := tmpl(c.Stderr, c.UsageTemplate, c)
	if err != nil {
		fmt.Println(err)
	}
	return err
}

// help implements the 'help' command.
func (c *Command) help(args []string) error {

	// help exactly for this command?
	if len(args) == 0 {
		if len(c.Long) > 0 {
			return tmpl(c.Stdout, c.HelpTemplate, c)
		} else {
			return c.usage()
		}
	}

	arg := args[0]

	// is this help for a subcommand?
	for _, cmd := range c.Subcommands {
		n := cmd.Name()
		// strip out "<parent>-"" name
		if strings.HasPrefix(n, c.Name()+"-") {
			n = n[len(c.Name()+"-"):]
		}
		if n == arg {
			return cmd.help(args[1:])
		}
	}

	return fmt.Errorf("Unknown help topic %#q.  Run '%v help'.\n", arg, c.Name())
}

func (c *Command) MaxLen() (res int) {
	res = 0
	for _, cmd := range c.Subcommands {
		i := len(cmd.Name())
		if i > res {
			res = i
		}
	}
	return
}

// ColFormat returns the column header size format for printing in the template
func (c *Command) ColFormat() string {
	sz := c.MaxLen()
	if sz < 11 {
		sz = 11
	}
	return fmt.Sprintf("%%-%ds", sz)
}

// FullName returns the full name of the command, prefixed with parent commands
func (c *Command) FullName() string {
	n := c.Name()
	if c.Parent != nil {
		n = c.Parent.FullName() + "-" + n
	}
	return n
}

// FullSpacedName returns the full name of the command, with ' ' instead of '-'
func (c *Command) FullSpacedName() string {
	n := c.Name()
	if c.Parent != nil {
		n = c.Parent.FullSpacedName() + " " + n
	}
	return n
}

func (c *Command) SubcommandList(list Listing) []*Command {
	var cmds []*Command
	for _, cmd := range c.Subcommands {
		if cmd.List == list {
			cmds = append(cmds, cmd)
		}
	}
	return cmds
}

var Defaults = Command{
	UsageTemplate: `{{if .Runnable}}Usage: {{if .Parent}}{{.Parent.FullSpacedName}}{{end}} {{.UsageLine}}

{{end}}{{.FullSpacedName}} - {{.Short}}

{{if commandList}}Commands:
{{range commandList}}
    {{.Name | printf (colfmt)}} {{.Short}}{{end}}

Use "{{.Name}} help <command>" for more information about a command.

{{end}}{{.FlagOptions}}{{if helpList}}
Additional help topics:
{{range helpList}}
    {{.Name | printf (colfmt)}} {{.Short}}{{end}}

Use "{{.Name}} help <topic>" for more information about that topic.

{{end}}`,

	HelpTemplate: `{{if .Runnable}}Usage: {{if .Parent}}{{.Parent.FullSpacedName}}{{end}} {{.UsageLine}}

{{end}}{{.Long | trim}}
{{.FlagOptions}}
`,
}

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) error {
	t := template.New("top")
	t.Funcs(template.FuncMap{
		"trim":        strings.TrimSpace,
		"colfmt":      func() string { return data.(*Command).ColFormat() },
		"commandList": func() []*Command { return data.(*Command).SubcommandList(CommandsList) },
		"helpList":    func() []*Command { return data.(*Command).SubcommandList(HelpTopicsList) },
	})
	template.Must(t.Parse(text))
	return t.Execute(w, data)
}
<|endoftext|>


<commit_before>package handler

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/Unknwon/macaron"

	"github.com/containerops/dockyard/models"
	"github.com/containerops/wrench/setting"
)

func manifestsConvertV1(data []byte) error {

	var manifest map[string]interface{}
	if err := json.Unmarshal(data, &manifest); err != nil {
		return err
	}

	tag := manifest["tag"]
	namespace, repository := strings.Split(manifest["name"].(string), "/")[0], strings.Split(manifest["name"].(string), "/")[1]

	for k := len(manifest["history"].([]interface{})) - 1; k >= 0; k-- {
		v := manifest["history"].([]interface{})[k]
		compatibility := v.(map[string]interface{})["v1Compatibility"].(string)

		var image map[string]interface{}
		if err := json.Unmarshal([]byte(compatibility), &image); err != nil {
			return err
		}

		i := map[string]string{}
		r := new(models.Repository)

		if k == 0 {
			i["Tag"] = tag.(string)
		}
		i["id"] = image["id"].(string)

		//Put V1 JSON
		if err := r.PutJSONFromManifests(i, namespace, repository); err != nil {
			return err
		}

		if k == 0 {
			//Put V1 Tag
			if err := r.PutTagFromManifests(image["id"].(string), namespace, repository, tag.(string), string(data)); err != nil {
				return err
			}
		}

		img := new(models.Image)

		blobSum := manifest["fsLayers"].([]interface{})[k].(map[string]interface{})["blobSum"].(string)
		tarsum := strings.Split(blobSum, ":")[1]

		fmt.Println("[Registry API V2] Image %s sha256: %s", image["id"].(string), v.(map[string]interface{})["v1Compatibility"].(string))

		//Put Image Json
		if err := img.PutJSON(image["id"].(string), v.(map[string]interface{})["v1Compatibility"].(string), setting.APIVERSION_V2); err != nil {
			return err
		}

		//Put Image Layer
		basePath := setting.ImagePath
		layerfile := fmt.Sprintf("%v/uuid/%v/layer", basePath, tarsum)

		if err := img.PutLayer(image["id"].(string), layerfile, true, int64(image["Size"].(float64))); err != nil {
			return err
		}

		//Put Checksum
		if err := img.PutChecksum(image["id"].(string), tarsum, true, ""); err != nil {
			return err
		}

		//Put Ancestry
		if err := img.PutAncestry(image["id"].(string)); err != nil {
			return err
		}
	}

	return nil
}

func PutManifestsV2Handler(ctx *macaron.Context) (int, []byte) {

	namespace := ctx.Params(":namespace")
	repository := ctx.Params(":repository")
	agent := ctx.Req.Header.Get("User-Agent")

	repo := new(models.Repository)
	if err := repo.Put(namespace, repository, "", agent, setting.APIVERSION_V2); err != nil {
		result, _ := json.Marshal(map[string]string{"message": err.Error()})
		return http.StatusBadRequest, result
	}

	manifest, _ := ioutil.ReadAll(ctx.Req.Request.Body)
	if err := manifestsConvertV1(manifest); err != nil {
		fmt.Errorf("[REGISTRY API V2] Decode Manifest Error: ", err.Error())
	}

	digest, err := DigestManifest(manifest)
	if err != nil {
		result, _ := json.Marshal(map[string]string{"message": "Get manifest digest failure"})
		return http.StatusBadRequest, result
	}

	random := fmt.Sprintf("http://%v/v2/%v/%v/manifests/%v",
		"containerops.me",
		namespace,
		repository,
		digest)
	ctx.Resp.Header().Set("Docker-Content-Digest", digest)
	ctx.Resp.Header().Set("Location", random)

	return http.StatusAccepted, []byte("")
}

func GetTagsListV2Handler(ctx *macaron.Context) (int, []byte) {
	result, _ := json.Marshal(map[string]string{"message": ""})

	return http.StatusOK, result
}

func GetManifestsV2Handler(ctx *macaron.Context) (int, []byte) {

	t := new(models.Tag)
	if err := t.Get(ctx.Params(":namespace"), ctx.Params(":repository"), ctx.Params(":tag")); err != nil {

		result, _ := json.Marshal(map[string]string{"message": "Manifest not found"})
		return http.StatusBadRequest, result
	}

	ctx.Resp.Header().Set("Content-Type", "application/json; charset=utf-8")

	digest, err := DigestManifest([]byte(t.Manifest))
	if err != nil {
		result, _ := json.Marshal(map[string]string{"message": "Get manifest digest failure"})
		return http.StatusBadRequest, result
	}

	ctx.Resp.Header().Set("Docker-Content-Digest", digest)
	ctx.Resp.Header().Set("Content-Length", fmt.Sprint(len(t.Manifest)))

	return http.StatusOK, []byte(t.Manifest)
}
<commit_msg>Force location to https<commit_after>package handler

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/Unknwon/macaron"

	"github.com/containerops/dockyard/models"
	"github.com/containerops/wrench/setting"
)

func manifestsConvertV1(data []byte) error {

	var manifest map[string]interface{}
	if err := json.Unmarshal(data, &manifest); err != nil {
		return err
	}

	tag := manifest["tag"]
	namespace, repository := strings.Split(manifest["name"].(string), "/")[0], strings.Split(manifest["name"].(string), "/")[1]

	for k := len(manifest["history"].([]interface{})) - 1; k >= 0; k-- {
		v := manifest["history"].([]interface{})[k]
		compatibility := v.(map[string]interface{})["v1Compatibility"].(string)

		var image map[string]interface{}
		if err := json.Unmarshal([]byte(compatibility), &image); err != nil {
			return err
		}

		i := map[string]string{}
		r := new(models.Repository)

		if k == 0 {
			i["Tag"] = tag.(string)
		}
		i["id"] = image["id"].(string)

		//Put V1 JSON
		if err := r.PutJSONFromManifests(i, namespace, repository); err != nil {
			return err
		}

		if k == 0 {
			//Put V1 Tag
			if err := r.PutTagFromManifests(image["id"].(string), namespace, repository, tag.(string), string(data)); err != nil {
				return err
			}
		}

		img := new(models.Image)

		blobSum := manifest["fsLayers"].([]interface{})[k].(map[string]interface{})["blobSum"].(string)
		tarsum := strings.Split(blobSum, ":")[1]

		fmt.Println("[Registry API V2] Image %s sha256: %s", image["id"].(string), v.(map[string]interface{})["v1Compatibility"].(string))

		//Put Image Json
		if err := img.PutJSON(image["id"].(string), v.(map[string]interface{})["v1Compatibility"].(string), setting.APIVERSION_V2); err != nil {
			return err
		}

		//Put Image Layer
		basePath := setting.ImagePath
		layerfile := fmt.Sprintf("%v/uuid/%v/layer", basePath, tarsum)

		if err := img.PutLayer(image["id"].(string), layerfile, true, int64(image["Size"].(float64))); err != nil {
			return err
		}

		//Put Checksum
		if err := img.PutChecksum(image["id"].(string), tarsum, true, ""); err != nil {
			return err
		}

		//Put Ancestry
		if err := img.PutAncestry(image["id"].(string)); err != nil {
			return err
		}
	}

	return nil
}

func PutManifestsV2Handler(ctx *macaron.Context) (int, []byte) {

	namespace := ctx.Params(":namespace")
	repository := ctx.Params(":repository")
	agent := ctx.Req.Header.Get("User-Agent")

	repo := new(models.Repository)
	if err := repo.Put(namespace, repository, "", agent, setting.APIVERSION_V2); err != nil {
		result, _ := json.Marshal(map[string]string{"message": err.Error()})
		return http.StatusBadRequest, result
	}

	manifest, _ := ioutil.ReadAll(ctx.Req.Request.Body)
	if err := manifestsConvertV1(manifest); err != nil {
		fmt.Errorf("[REGISTRY API V2] Decode Manifest Error: ", err.Error())
	}

	digest, err := DigestManifest(manifest)
	if err != nil {
		result, _ := json.Marshal(map[string]string{"message": "Get manifest digest failure"})
		return http.StatusBadRequest, result
	}

	random := fmt.Sprintf("https://%v/v2/%v/%v/manifests/%v",
		"containerops.me",
		namespace,
		repository,
		digest)
	ctx.Resp.Header().Set("Docker-Content-Digest", digest)
	ctx.Resp.Header().Set("Location", random)

	return http.StatusAccepted, []byte("")
}

func GetTagsListV2Handler(ctx *macaron.Context) (int, []byte) {
	result, _ := json.Marshal(map[string]string{"message": ""})

	return http.StatusOK, result
}

func GetManifestsV2Handler(ctx *macaron.Context) (int, []byte) {

	t := new(models.Tag)
	if err := t.Get(ctx.Params(":namespace"), ctx.Params(":repository"), ctx.Params(":tag")); err != nil {

		result, _ := json.Marshal(map[string]string{"message": "Manifest not found"})
		return http.StatusBadRequest, result
	}

	ctx.Resp.Header().Set("Content-Type", "application/json; charset=utf-8")

	digest, err := DigestManifest([]byte(t.Manifest))
	if err != nil {
		result, _ := json.Marshal(map[string]string{"message": "Get manifest digest failure"})
		return http.StatusBadRequest, result
	}

	ctx.Resp.Header().Set("Docker-Content-Digest", digest)
	ctx.Resp.Header().Set("Content-Length", fmt.Sprint(len(t.Manifest)))

	return http.StatusOK, []byte(t.Manifest)
}
<|endoftext|>


<commit_before>package agent

// You can overridden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/agent.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "3.0-beta.22"
var buildVersion string = ""

func Version() string {
	return baseVersion
}

func BuildVersion() string {
	if buildVersion != "" {
		return buildVersion
	} else {
		return "x"
	}
}
<commit_msg>Bumped to 3.0-beta.23<commit_after>package agent

// You can overridden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/agent.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "3.0-beta.23"
var buildVersion string = ""

func Version() string {
	return baseVersion
}

func BuildVersion() string {
	if buildVersion != "" {
		return buildVersion
	} else {
		return "x"
	}
}
<|endoftext|>


<commit_before>package ole

import (
	"syscall"
	"unsafe"
)

type IDispatch struct {
	lpVtbl *pIDispatchVtbl
}

type pIDispatchVtbl struct {
	pQueryInterface   uintptr
	pAddRef           uintptr
	pRelease          uintptr
	pGetTypeInfoCount uintptr
	pGetTypeInfo      uintptr
	pGetIDsOfNames    uintptr
	pInvoke           uintptr
}

func (v *IDispatch) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) MustQueryInterface(iid *GUID) (disp *IDispatch) {
	disp, _ = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) {
	dispid, err = getIDsOfName(v, names)
	return
}

func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	result, err = invoke(v, dispid, dispatch, params...)
	return
}

func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) {
	c, err = getTypeInfoCount(v)
	return
}

func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) {
	tinfo, err = getTypeInfo(v)
	return
}

func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
	wnames := make([]*uint16, len(names))
	for i := 0; i < len(names); i++ {
		wnames[i] = syscall.StringToUTF16Ptr(names[i])
	}
	dispid = make([]int32, len(names))
	hr, _, _ := syscall.Syscall6(
		disp.lpVtbl.pGetIDsOfNames,
		6,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(unsafe.Pointer(&wnames[0])),
		uintptr(len(names)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&dispid[0])))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfoCount,
		2,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(&c)),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfo,
		3,
		uintptr(unsafe.Pointer(disp)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&tinfo)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	var dispparams DISPPARAMS

	if dispatch&DISPATCH_PROPERTYPUT != 0 {
		dispnames := [1]int32{DISPID_PROPERTYPUT}
		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
		dispparams.cNamedArgs = 1
	}
	var vargs []VARIANT
	if len(params) > 0 {
		vargs = make([]VARIANT, len(params))
		for i, v := range params {
			//n := len(params)-i-1
			n := len(params) - i - 1
			VariantInit(&vargs[n])
			switch v.(type) {
			case bool:
				if v.(bool) {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
				} else {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
				}
			case *bool:
				vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
			case byte:
				vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
			case *byte:
				vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
			case int16:
				vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
			case *int16:
				vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
			case uint16:
				vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
			case *uint16:
				vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
			case int, int32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
			case *int, *int32:
				vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
			case uint, uint32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
			case *uint, *uint32:
				vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
			case int64:
				vargs[n] = VARIANT{VT_I8, 0, 0, 0, int64(v.(int64))}
			case *int64:
				vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
			case uint64:
				vargs[n] = VARIANT{VT_UI8, 0, 0, 0, v.(int64)}
			case *uint64:
				vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
			case float32:
				vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
			case *float32:
				vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
			case float64:
				vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
			case *float64:
				vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
			case string:
				vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
			case *string:
				vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
			case *IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
			case **IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
			case nil:
				vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
			case *VARIANT:
				vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
			default:
				panic("unknown type")
			}
		}
		dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
		dispparams.cArgs = uint32(len(params))
	}

	result = new(VARIANT)
	var excepInfo EXCEPINFO
	VariantInit(result)
	hr, _, _ := syscall.Syscall9(
		disp.lpVtbl.pInvoke,
		9,
		uintptr(unsafe.Pointer(disp)),
		uintptr(dispid),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(GetUserDefaultLCID()),
		uintptr(dispatch),
		uintptr(unsafe.Pointer(&dispparams)),
		uintptr(unsafe.Pointer(result)),
		uintptr(unsafe.Pointer(&excepInfo)),
		0)
	if hr != 0 {
		if excepInfo.bstrDescription == nil {
			err = NewError(hr)
		} else {
			bs := UTF16PtrToString(excepInfo.bstrDescription)
			err = NewErrorWithDescription(hr, bs)
		}
	}
	for _, varg := range vargs {
		if varg.VT == VT_BSTR && varg.Val != 0 {
			SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
		}
		/*
			if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
				*(params[n].(*string)) = UTF16PtrToString((*uint16)(unsafe.Pointer(uintptr(varg.Val))))
				println(*(params[n].(*string)))
				fmt.Fprintln(os.Stderr, *(params[n].(*string)))
			}
		*/
	}
	return
}
<commit_msg>Use typed variable<commit_after>package ole

import (
	"syscall"
	"unsafe"
)

type IDispatch struct {
	lpVtbl *pIDispatchVtbl
}

type pIDispatchVtbl struct {
	pQueryInterface   uintptr
	pAddRef           uintptr
	pRelease          uintptr
	pGetTypeInfoCount uintptr
	pGetTypeInfo      uintptr
	pGetIDsOfNames    uintptr
	pInvoke           uintptr
}

func (v *IDispatch) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) MustQueryInterface(iid *GUID) (disp *IDispatch) {
	disp, _ = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) {
	dispid, err = getIDsOfName(v, names)
	return
}

func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	result, err = invoke(v, dispid, dispatch, params...)
	return
}

func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) {
	c, err = getTypeInfoCount(v)
	return
}

func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) {
	tinfo, err = getTypeInfo(v)
	return
}

func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
	wnames := make([]*uint16, len(names))
	for i := 0; i < len(names); i++ {
		wnames[i] = syscall.StringToUTF16Ptr(names[i])
	}
	dispid = make([]int32, len(names))
	var namelen uint32 = len(names)
	hr, _, _ := syscall.Syscall6(
		disp.lpVtbl.pGetIDsOfNames,
		6,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(unsafe.Pointer(&wnames[0])),
		uintptr(namelen),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&dispid[0])))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfoCount,
		2,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(&c)),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfo,
		3,
		uintptr(unsafe.Pointer(disp)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&tinfo)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	var dispparams DISPPARAMS

	if dispatch&DISPATCH_PROPERTYPUT != 0 {
		dispnames := [1]int32{DISPID_PROPERTYPUT}
		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
		dispparams.cNamedArgs = 1
	}
	var vargs []VARIANT
	if len(params) > 0 {
		vargs = make([]VARIANT, len(params))
		for i, v := range params {
			//n := len(params)-i-1
			n := len(params) - i - 1
			VariantInit(&vargs[n])
			switch v.(type) {
			case bool:
				if v.(bool) {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
				} else {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
				}
			case *bool:
				vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
			case byte:
				vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
			case *byte:
				vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
			case int16:
				vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
			case *int16:
				vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
			case uint16:
				vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
			case *uint16:
				vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
			case int, int32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
			case *int, *int32:
				vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
			case uint, uint32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
			case *uint, *uint32:
				vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
			case int64:
				vargs[n] = VARIANT{VT_I8, 0, 0, 0, int64(v.(int64))}
			case *int64:
				vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
			case uint64:
				vargs[n] = VARIANT{VT_UI8, 0, 0, 0, v.(int64)}
			case *uint64:
				vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
			case float32:
				vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
			case *float32:
				vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
			case float64:
				vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
			case *float64:
				vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
			case string:
				vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
			case *string:
				vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
			case *IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
			case **IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
			case nil:
				vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
			case *VARIANT:
				vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
			default:
				panic("unknown type")
			}
		}
		dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
		dispparams.cArgs = uint32(len(params))
	}

	result = new(VARIANT)
	var excepInfo EXCEPINFO
	VariantInit(result)
	hr, _, _ := syscall.Syscall9(
		disp.lpVtbl.pInvoke,
		9,
		uintptr(unsafe.Pointer(disp)),
		uintptr(dispid),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(GetUserDefaultLCID()),
		uintptr(dispatch),
		uintptr(unsafe.Pointer(&dispparams)),
		uintptr(unsafe.Pointer(result)),
		uintptr(unsafe.Pointer(&excepInfo)),
		0)
	if hr != 0 {
		if excepInfo.bstrDescription == nil {
			err = NewError(hr)
		} else {
			bs := UTF16PtrToString(excepInfo.bstrDescription)
			err = NewErrorWithDescription(hr, bs)
		}
	}
	for _, varg := range vargs {
		if varg.VT == VT_BSTR && varg.Val != 0 {
			SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
		}
		/*
			if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
				*(params[n].(*string)) = UTF16PtrToString((*uint16)(unsafe.Pointer(uintptr(varg.Val))))
				println(*(params[n].(*string)))
				fmt.Fprintln(os.Stderr, *(params[n].(*string)))
			}
		*/
	}
	return
}
<|endoftext|>


<commit_before>package mackerel

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
)

var logger = logging.GetLogger("api")

// CreatingMetricsValue XXX
type CreatingMetricsValue struct {
	HostID string      `json:"hostId"`
	Name   string      `json:"name"`
	Time   float64     `json:"time"`
	Value  interface{} `json:"value"`
}

// API is the main interface of Mackerel API.
type API struct {
	BaseURL *url.URL
	APIKey  string
	Verbose bool
}

// NewAPI creates a new instance of API.
func NewAPI(rawurl string, apiKey string, verbose bool) (*API, error) {
	u, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}
	return &API{u, apiKey, verbose}, nil
}

func (api *API) urlFor(path string) *url.URL {
	newURL, err := url.Parse(api.BaseURL.String())
	if err != nil {
		panic("invalid url passed")
	}

	newURL.Path = path
	return newURL
}

var apiRequestTimeout = 30 * time.Second

func (api *API) do(req *http.Request) (resp *http.Response, err error) {
	req.Header.Add("X-Api-Key", api.APIKey)
	req.Header.Add("X-Agent-Version", version.VERSION)
	req.Header.Add("X-Revision", version.GITCOMMIT)
	req.Header.Set("User-Agent", version.UserAgent())

	if api.Verbose {
		dump, err := httputil.DumpRequest(req, true)
		if err == nil {
			logger.Tracef("%s", dump)
		}
	}

	client := &http.Client{} // same as http.DefaultClient
	client.Timeout = apiRequestTimeout
	resp, err = client.Do(req)
	if err != nil {
		return nil, err
	}
	if api.Verbose {
		dump, err := httputil.DumpResponse(resp, true)
		if err == nil {
			logger.Tracef("%s", dump)
		}
	}
	return resp, nil
}

func closeResp(resp *http.Response) {
	if resp != nil {
		resp.Body.Close()
	}
}

// FindHost XXX
func (api *API) FindHost(id string) (*Host, error) {
	req, err := http.NewRequest("GET", api.urlFor(fmt.Sprintf("/api/v0/hosts/%s", id)).String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != 200 {
		return nil, errors.New("status code is not 200")
	}

	var data struct {
		Host *Host `json:"host"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return nil, err
	}
	return data.Host, err
}

// CreateHost XXX
func (api *API) CreateHost(name string, meta map[string]interface{}, interfaces []map[string]interface{}, roleFullnames []string, displayName string) (string, error) {
	requestJSON, err := json.Marshal(map[string]interface{}{
		"name":          name,
		"type":          "unknown",
		"status":        "working",
		"meta":          meta,
		"interfaces":    interfaces,
		"roleFullnames": roleFullnames,
		"displayName":   displayName,
	})
	if err != nil {
		return "", err
	}

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/hosts").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return "", err
	}
	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return "", err
	}

	if resp.StatusCode != 200 {
		return "", fmt.Errorf("API result failed: %s", resp.Status)
	}

	var data struct {
		ID string `json:"id"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return "", err
	}

	return data.ID, nil
}

// UpdateHost updates the host information on Mackerel.
func (api *API) UpdateHost(hostID string, hostSpec HostSpec) error {
	url := api.urlFor("/api/v0/hosts/" + hostID)

	requestJSON, err := json.Marshal(hostSpec)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("PUT", url.String(), bytes.NewReader(requestJSON))
	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}

	return nil
}

// PostMetricsValues XXX
func (api *API) PostMetricsValues(metricsValues [](*CreatingMetricsValue)) error {
	requestJSON, err := json.Marshal(metricsValues)
	if err != nil {
		return err
	}
	logger.Debugf("Metrics Post Request: %s", string(requestJSON))

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/tsdb").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return err
	}
	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}
	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		return fmt.Errorf("API result failed: %s", resp.Status)
	}

	return nil
}

// CreateGraphDefsPayload XXX
type CreateGraphDefsPayload struct {
	Name        string                         `json:"name"`
	DisplayName string                         `json:"displayName"`
	Unit        string                         `json:"unit"`
	Metrics     []CreateGraphDefsPayloadMetric `json:"metrics"`
}

// CreateGraphDefsPayloadMetric XXX
type CreateGraphDefsPayloadMetric struct {
	Name        string `json:"name"`
	DisplayName string `json:"displayName"`
	IsStacked   bool   `json:"isStacked"`
}

// CreateGraphDefs XXX
func (api *API) CreateGraphDefs(payloads []CreateGraphDefsPayload) error {
	requestJSON, err := json.Marshal(payloads)
	if err != nil {
		return err
	}

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/graph-defs/create").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return err
	}

	logger.Debugf("Create grpah defs request: %s", string(requestJSON))

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}
	return nil
}

func (api *API) requestJSON(method, path string, payload interface{}) (*http.Response, error) {
	var body bytes.Buffer

	err := json.NewEncoder(&body).Encode(payload)
	if err != nil {
		return nil, err
	}
	logger.Debugf("%s %s %s", method, path, body.String())

	req, err := http.NewRequest(method, api.urlFor(path).String(), &body)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	if err != nil {
		return resp, err
	}

	logger.Debugf("%s %s status=%q", method, path, resp.Status)
	if resp.StatusCode >= 400 {
		return resp, fmt.Errorf("request failed: [%s]", resp.Status)
	}
	return resp, nil
}

func (api *API) postJSON(path string, payload interface{}) (*http.Response, error) {
	return api.requestJSON("POST", path, payload)
}

func (api *API) putJSON(path string, payload interface{}) (*http.Response, error) {
	return api.requestJSON("PUT", path, payload)
}

// Time is a type for sending time information to Mackerel API server.
// It is encoded as an epoch seconds integer in JSON.
type Time time.Time

// MarshalJSON implements json.Marshaler.
func (t Time) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Time(t).Unix())
}
<commit_msg>define API#get()<commit_after>package mackerel

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
)

var logger = logging.GetLogger("api")

// CreatingMetricsValue XXX
type CreatingMetricsValue struct {
	HostID string      `json:"hostId"`
	Name   string      `json:"name"`
	Time   float64     `json:"time"`
	Value  interface{} `json:"value"`
}

// API is the main interface of Mackerel API.
type API struct {
	BaseURL *url.URL
	APIKey  string
	Verbose bool
}

// NewAPI creates a new instance of API.
func NewAPI(rawurl string, apiKey string, verbose bool) (*API, error) {
	u, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}
	return &API{u, apiKey, verbose}, nil
}

func (api *API) urlFor(path string) *url.URL {
	newURL, err := url.Parse(api.BaseURL.String())
	if err != nil {
		panic("invalid url passed")
	}

	newURL.Path = path
	return newURL
}

var apiRequestTimeout = 30 * time.Second

func (api *API) do(req *http.Request) (resp *http.Response, err error) {
	req.Header.Add("X-Api-Key", api.APIKey)
	req.Header.Add("X-Agent-Version", version.VERSION)
	req.Header.Add("X-Revision", version.GITCOMMIT)
	req.Header.Set("User-Agent", version.UserAgent())

	if api.Verbose {
		dump, err := httputil.DumpRequest(req, true)
		if err == nil {
			logger.Tracef("%s", dump)
		}
	}

	client := &http.Client{} // same as http.DefaultClient
	client.Timeout = apiRequestTimeout
	resp, err = client.Do(req)
	if err != nil {
		return nil, err
	}
	if api.Verbose {
		dump, err := httputil.DumpResponse(resp, true)
		if err == nil {
			logger.Tracef("%s", dump)
		}
	}
	return resp, nil
}

func closeResp(resp *http.Response) {
	if resp != nil {
		resp.Body.Close()
	}
}

// FindHost XXX
func (api *API) FindHost(id string) (*Host, error) {
	resp, err := api.get(fmt.Sprintf("/api/v0/hosts/%s", id))
	defer closeResp(resp)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != 200 {
		return nil, errors.New("status code is not 200")
	}

	var data struct {
		Host *Host `json:"host"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return nil, err
	}
	return data.Host, err
}

// CreateHost XXX
func (api *API) CreateHost(name string, meta map[string]interface{}, interfaces []map[string]interface{}, roleFullnames []string, displayName string) (string, error) {
	requestJSON, err := json.Marshal(map[string]interface{}{
		"name":          name,
		"type":          "unknown",
		"status":        "working",
		"meta":          meta,
		"interfaces":    interfaces,
		"roleFullnames": roleFullnames,
		"displayName":   displayName,
	})
	if err != nil {
		return "", err
	}

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/hosts").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return "", err
	}
	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return "", err
	}

	if resp.StatusCode != 200 {
		return "", fmt.Errorf("API result failed: %s", resp.Status)
	}

	var data struct {
		ID string `json:"id"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return "", err
	}

	return data.ID, nil
}

// UpdateHost updates the host information on Mackerel.
func (api *API) UpdateHost(hostID string, hostSpec HostSpec) error {
	url := api.urlFor("/api/v0/hosts/" + hostID)

	requestJSON, err := json.Marshal(hostSpec)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("PUT", url.String(), bytes.NewReader(requestJSON))
	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}

	return nil
}

// PostMetricsValues XXX
func (api *API) PostMetricsValues(metricsValues [](*CreatingMetricsValue)) error {
	requestJSON, err := json.Marshal(metricsValues)
	if err != nil {
		return err
	}
	logger.Debugf("Metrics Post Request: %s", string(requestJSON))

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/tsdb").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return err
	}
	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}
	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		return fmt.Errorf("API result failed: %s", resp.Status)
	}

	return nil
}

// CreateGraphDefsPayload XXX
type CreateGraphDefsPayload struct {
	Name        string                         `json:"name"`
	DisplayName string                         `json:"displayName"`
	Unit        string                         `json:"unit"`
	Metrics     []CreateGraphDefsPayloadMetric `json:"metrics"`
}

// CreateGraphDefsPayloadMetric XXX
type CreateGraphDefsPayloadMetric struct {
	Name        string `json:"name"`
	DisplayName string `json:"displayName"`
	IsStacked   bool   `json:"isStacked"`
}

// CreateGraphDefs XXX
func (api *API) CreateGraphDefs(payloads []CreateGraphDefsPayload) error {
	requestJSON, err := json.Marshal(payloads)
	if err != nil {
		return err
	}

	req, err := http.NewRequest(
		"POST",
		api.urlFor("/api/v0/graph-defs/create").String(),
		bytes.NewReader(requestJSON),
	)
	if err != nil {
		return err
	}

	logger.Debugf("Create grpah defs request: %s", string(requestJSON))

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	defer closeResp(resp)
	if err != nil {
		return err
	}
	return nil
}

func (api *API) get(path string) (*http.Response, error) {
	req, err := http.NewRequest("GET", api.urlFor(path).String(), nil)
	if err != nil {
		return nil, err
	}
	return api.do(req)
}

func (api *API) requestJSON(method, path string, payload interface{}) (*http.Response, error) {
	var body bytes.Buffer

	err := json.NewEncoder(&body).Encode(payload)
	if err != nil {
		return nil, err
	}
	logger.Debugf("%s %s %s", method, path, body.String())

	req, err := http.NewRequest(method, api.urlFor(path).String(), &body)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")
	resp, err := api.do(req)
	if err != nil {
		return resp, err
	}

	logger.Debugf("%s %s status=%q", method, path, resp.Status)
	if resp.StatusCode >= 400 {
		return resp, fmt.Errorf("request failed: [%s]", resp.Status)
	}
	return resp, nil
}

func (api *API) postJSON(path string, payload interface{}) (*http.Response, error) {
	return api.requestJSON("POST", path, payload)
}

func (api *API) putJSON(path string, payload interface{}) (*http.Response, error) {
	return api.requestJSON("PUT", path, payload)
}

// Time is a type for sending time information to Mackerel API server.
// It is encoded as an epoch seconds integer in JSON.
type Time time.Time

// MarshalJSON implements json.Marshaler.
func (t Time) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Time(t).Unix())
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxd

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

	"github.com/lxc/lxd/shared"

	"github.com/juju/errors"
	"github.com/juju/utils/packaging/config"
	"github.com/juju/utils/packaging/manager"
	"github.com/juju/utils/proxy"

	"syscall"

	"github.com/juju/juju/container"
	"github.com/juju/juju/tools/lxdclient"
)

const lxdBridgeFile = "/etc/default/lxd-bridge"

var requiredPackages = []string{
	"lxd",
}

var xenialPackages = []string{
	"zfsutils-linux",
}

type containerInitialiser struct {
	series string
}

// containerInitialiser implements container.Initialiser.
var _ container.Initialiser = (*containerInitialiser)(nil)

// NewContainerInitialiser returns an instance used to perform the steps
// required to allow a host machine to run a LXC container.
func NewContainerInitialiser(series string) container.Initialiser {
	return &containerInitialiser{series}
}

// Initialise is specified on the container.Initialiser interface.
func (ci *containerInitialiser) Initialise() error {
	err := ensureDependencies(ci.series)
	if err != nil {
		return err
	}

	err = configureLXDBridge()
	if err != nil {
		return err
	}
	proxies := proxy.DetectProxies()
	err = ConfigureLXDProxies(proxies)
	if err != nil {
		return err
	}

	// Well... this will need to change soon once we are passed 17.04 as who
	// knows what the series name will be.
	if ci.series >= "xenial" {
		configureZFS()
	}

	return nil
}

// getPackageManager is a helper function which returns the
// package manager implementation for the current system.
func getPackageManager(series string) (manager.PackageManager, error) {
	return manager.NewPackageManager(series)
}

// getPackagingConfigurer is a helper function which returns the
// packaging configuration manager for the current system.
func getPackagingConfigurer(series string) (config.PackagingConfigurer, error) {
	return config.NewPackagingConfigurer(series)
}

// ConfigureLXDProxies will try to set the lxc config core.proxy_http and core.proxy_https
// configuration values based on the current environment.
func ConfigureLXDProxies(proxies proxy.Settings) error {
	setter, err := getLXDConfigSetter()
	if err != nil {
		return errors.Trace(err)
	}
	return errors.Trace(configureLXDProxies(setter, proxies))
}

var getLXDConfigSetter = getConfigSetterConnect

func getConfigSetterConnect() (configSetter, error) {
	return ConnectLocal()
}

type configSetter interface {
	SetConfig(key, value string) error
}

func configureLXDProxies(setter configSetter, proxies proxy.Settings) error {
	err := setter.SetConfig("core.proxy_http", proxies.Http)
	if err != nil {
		return errors.Trace(err)
	}
	err = setter.SetConfig("core.proxy_https", proxies.Https)
	if err != nil {
		return errors.Trace(err)
	}
	err = setter.SetConfig("core.proxy_ignore_hosts", proxies.NoProxy)
	if err != nil {
		return errors.Trace(err)
	}
	return nil
}

// df returns the number of free bytes on the file system at the given path
var df = func(path string) (uint64, error) {
	statfs := syscall.Statfs_t{}
	err := syscall.Statfs(path, &statfs)
	if err != nil {
		return 0, err
	}

	return uint64(statfs.Bsize) * statfs.Bfree, nil
}

var configureZFS = func() {
	/* create a pool that will occupy 90% of the free disk space
	   (sparse, so it won't actually fill that immediately)
	*/

	// Find 90% of the free disk space
	freeBytes, err := df("/")
	if err != nil {
		logger.Errorf("configuring zfs failed - unable to find file system size: %s", err)
	}
	freeBytes = freeBytes * 9 / 10

	output, err := exec.Command(
		"lxd",
		"init",
		"--auto",
		"--storage-backend", "zfs",
		"--storage-pool", "lxd",
		"--storage-create-loop", fmt.Sprintf("%d", freeBytes/(1024*1024*1024)),
	).CombinedOutput()

	if err != nil {
		logger.Errorf("configuring zfs failed with %s: %s", err, string(output))
	}
}

var configureLXDBridge = func() error {
	client, err := ConnectLocal()
	if err != nil {
		return errors.Trace(err)
	}

	status, err := client.ServerStatus()
	if err != nil {
		return errors.Trace(err)
	}

	if shared.StringInSlice("network", status.APIExtensions) {
		return lxdclient.CreateDefaultBridgeInDefaultProfile(client)
	}

	f, err := os.OpenFile(lxdBridgeFile, os.O_RDWR, 0777)
	if err != nil {
		/* We're using an old version of LXD which doesn't have
		 * lxd-bridge; let's not fail here.
		 */
		if os.IsNotExist(err) {
			logger.Debugf("couldn't find %s, not configuring it", lxdBridgeFile)
			return nil
		}
		return errors.Trace(err)
	}
	defer f.Close()

	existing, err := ioutil.ReadAll(f)
	if err != nil {
		return errors.Trace(err)
	}

	newBridgeCfg, err := bridgeConfiguration(string(existing))
	if err != nil {
		return errors.Trace(err)
	}

	if newBridgeCfg == string(existing) {
		return nil
	}

	_, err = f.Seek(0, 0)
	if err != nil {
		return errors.Trace(err)
	}
	_, err = f.WriteString(newBridgeCfg)
	if err != nil {
		return errors.Trace(err)
	}

	/* non-systemd systems don't have the lxd-bridge service, so this always fails */
	_ = exec.Command("service", "lxd-bridge", "restart").Run()
	return exec.Command("service", "lxd", "restart").Run()
}

var interfaceAddrs = func() ([]net.Addr, error) {
	return net.InterfaceAddrs()
}

func editLXDBridgeFile(input string, subnet string) string {
	buffer := bytes.Buffer{}

	newValues := map[string]string{
		"USE_LXD_BRIDGE":      "true",
		"EXISTING_BRIDGE":     "",
		"LXD_BRIDGE":          "lxdbr0",
		"LXD_IPV4_ADDR":       fmt.Sprintf("10.0.%s.1", subnet),
		"LXD_IPV4_NETMASK":    "255.255.255.0",
		"LXD_IPV4_NETWORK":    fmt.Sprintf("10.0.%s.1/24", subnet),
		"LXD_IPV4_DHCP_RANGE": fmt.Sprintf("10.0.%s.2,10.0.%s.254", subnet, subnet),
		"LXD_IPV4_DHCP_MAX":   "253",
		"LXD_IPV4_NAT":        "true",
		"LXD_IPV6_PROXY":      "false",
	}
	found := map[string]bool{}

	for _, line := range strings.Split(input, "\n") {
		out := line

		for prefix, value := range newValues {
			if strings.HasPrefix(line, prefix+"=") {
				out = fmt.Sprintf(`%s="%s"`, prefix, value)
				found[prefix] = true
				break
			}
		}

		buffer.WriteString(out)
		buffer.WriteString("\n")
	}

	for prefix, value := range newValues {
		if !found[prefix] {
			buffer.WriteString(prefix)
			buffer.WriteString("=")
			buffer.WriteString(value)
			buffer.WriteString("\n")
			found[prefix] = true // not necessary but keeps "found" logically consistent
		}
	}

	return buffer.String()
}

// ensureDependencies creates a set of install packages using
// apt.GetPreparePackages and runs each set of packages through
// apt.GetInstall.
func ensureDependencies(series string) error {
	if series == "precise" {
		return fmt.Errorf("LXD is not supported in precise.")
	}

	pacman, err := getPackageManager(series)
	if err != nil {
		return err
	}
	pacconfer, err := getPackagingConfigurer(series)
	if err != nil {
		return err
	}

	for _, pack := range requiredPackages {
		pkg := pack
		if config.SeriesRequiresCloudArchiveTools(series) &&
			pacconfer.IsCloudArchivePackage(pack) {
			pkg = strings.Join(pacconfer.ApplyCloudArchiveTarget(pack), " ")
		}

		if config.RequiresBackports(series, pack) {
			pkg = fmt.Sprintf("--target-release %s-backports %s", series, pkg)
		}

		if err := pacman.Install(pkg); err != nil {
			return err
		}
	}

	if series >= "xenial" {
		for _, pack := range xenialPackages {
			pacman.Install(fmt.Sprintf("--no-install-recommends %s", pack))
		}
	}

	return err
}

// findNextAvailableIPv4Subnet scans the list of interfaces on the machine
// looking for 10.0.0.0/16 networks and returns the next subnet not in
// use, having first detected the highest subnet. The next subnet can
// actually be lower if we overflowed 255 whilst seeking out the next
// unused subnet. If all subnets are in use an error is returned.
//
// TODO(frobware): this is not an ideal solution as it doesn't take
// into account any static routes that may be set up on the machine.
//
// TODO(frobware): this only caters for IPv4 setups.
func findNextAvailableIPv4Subnet() (string, error) {
	_, ip10network, err := net.ParseCIDR("10.0.0.0/16")
	if err != nil {
		return "", errors.Trace(err)
	}

	addrs, err := interfaceAddrs()
	if err != nil {
		return "", errors.Annotatef(err, "cannot get network interface addresses")
	}

	max := 0
	usedSubnets := make(map[int]bool)

	for _, address := range addrs {
		addr, network, err := net.ParseCIDR(address.String())
		if err != nil {
			logger.Debugf("cannot parse address %q: %v (ignoring)", address.String(), err)
			continue
		}
		if !ip10network.Contains(addr) {
			logger.Debugf("find available subnet, skipping %q", network.String())
			continue
		}
		subnet := int(network.IP[2])
		usedSubnets[subnet] = true
		if subnet > max {
			max = subnet
		}
	}

	if len(usedSubnets) == 0 {
		return "0", nil
	}

	for i := 0; i < 256; i++ {
		max = (max + 1) % 256
		if _, inUse := usedSubnets[max]; !inUse {
			return fmt.Sprintf("%d", max), nil
		}
	}

	return "", errors.New("could not find unused subnet")
}

func parseLXDBridgeConfigValues(input string) map[string]string {
	values := make(map[string]string)

	for _, line := range strings.Split(input, "\n") {
		line = strings.TrimSpace(line)

		if line == "" || strings.HasPrefix(line, "#") || !strings.Contains(line, "=") {
			continue
		}

		tokens := strings.Split(line, "=")

		if tokens[0] == "" {
			continue // no key
		}

		value := ""

		if len(tokens) > 1 {
			value = tokens[1]
			if strings.HasPrefix(value, `"`) && strings.HasSuffix(value, `"`) {
				value = strings.Trim(value, `"`)
			}
		}

		values[tokens[0]] = value
	}
	return values
}

// bridgeConfiguration ensures that input has a valid setting for
// LXD_IPV4_ADDR, returning the existing input if is already set, and
// allocating the next available subnet if it is not.
func bridgeConfiguration(input string) (string, error) {
	values := parseLXDBridgeConfigValues(input)
	ipAddr := net.ParseIP(values["LXD_IPV4_ADDR"])

	if ipAddr == nil || ipAddr.To4() == nil {
		logger.Infof("LXD_IPV4_ADDR is not set; searching for unused subnet")
		subnet, err := findNextAvailableIPv4Subnet()
		if err != nil {
			return "", errors.Trace(err)
		}
		logger.Infof("setting LXD_IPV4_ADDR=10.0.%s.1", subnet)
		return editLXDBridgeFile(input, subnet), nil
	}
	return input, nil
}
<commit_msg>* Using golang.org/x/sys/unix  * Better variable names<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxd

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

	"github.com/juju/errors"
	"github.com/juju/utils/packaging/config"
	"github.com/juju/utils/packaging/manager"
	"github.com/juju/utils/proxy"
	"github.com/lxc/lxd/shared"
	"golang.org/x/sys/unix"

	"github.com/juju/juju/container"
	"github.com/juju/juju/tools/lxdclient"
)

const lxdBridgeFile = "/etc/default/lxd-bridge"

var requiredPackages = []string{
	"lxd",
}

var xenialPackages = []string{
	"zfsutils-linux",
}

type containerInitialiser struct {
	series string
}

// containerInitialiser implements container.Initialiser.
var _ container.Initialiser = (*containerInitialiser)(nil)

// NewContainerInitialiser returns an instance used to perform the steps
// required to allow a host machine to run a LXC container.
func NewContainerInitialiser(series string) container.Initialiser {
	return &containerInitialiser{series}
}

// Initialise is specified on the container.Initialiser interface.
func (ci *containerInitialiser) Initialise() error {
	err := ensureDependencies(ci.series)
	if err != nil {
		return err
	}

	err = configureLXDBridge()
	if err != nil {
		return err
	}
	proxies := proxy.DetectProxies()
	err = ConfigureLXDProxies(proxies)
	if err != nil {
		return err
	}

	// Well... this will need to change soon once we are passed 17.04 as who
	// knows what the series name will be.
	if ci.series >= "xenial" {
		configureZFS()
	}

	return nil
}

// getPackageManager is a helper function which returns the
// package manager implementation for the current system.
func getPackageManager(series string) (manager.PackageManager, error) {
	return manager.NewPackageManager(series)
}

// getPackagingConfigurer is a helper function which returns the
// packaging configuration manager for the current system.
func getPackagingConfigurer(series string) (config.PackagingConfigurer, error) {
	return config.NewPackagingConfigurer(series)
}

// ConfigureLXDProxies will try to set the lxc config core.proxy_http and core.proxy_https
// configuration values based on the current environment.
func ConfigureLXDProxies(proxies proxy.Settings) error {
	setter, err := getLXDConfigSetter()
	if err != nil {
		return errors.Trace(err)
	}
	return errors.Trace(configureLXDProxies(setter, proxies))
}

var getLXDConfigSetter = getConfigSetterConnect

func getConfigSetterConnect() (configSetter, error) {
	return ConnectLocal()
}

type configSetter interface {
	SetConfig(key, value string) error
}

func configureLXDProxies(setter configSetter, proxies proxy.Settings) error {
	err := setter.SetConfig("core.proxy_http", proxies.Http)
	if err != nil {
		return errors.Trace(err)
	}
	err = setter.SetConfig("core.proxy_https", proxies.Https)
	if err != nil {
		return errors.Trace(err)
	}
	err = setter.SetConfig("core.proxy_ignore_hosts", proxies.NoProxy)
	if err != nil {
		return errors.Trace(err)
	}
	return nil
}

// df returns the number of free bytes on the file system at the given path
var df = func(path string) (uint64, error) {
	statfs := unix.Statfs_t{}
	err := unix.Statfs(path, &statfs)
	if err != nil {
		return 0, err
	}

	return uint64(statfs.Bsize) * statfs.Bfree, nil
}

var configureZFS = func() {
	/* create a pool that will occupy 90% of the free disk space
	   (sparse, so it won't actually fill that immediately)
	*/

	// Find 90% of the free disk space
	freeBytes, err := df("/")
	if err != nil {
		logger.Errorf("configuring zfs failed - unable to find file system size: %s", err)
	}
	GigaBytesToUse := freeBytes * 9 / (10 * 1024 * 1024 * 1024)

	output, err := exec.Command(
		"lxd",
		"init",
		"--auto",
		"--storage-backend", "zfs",
		"--storage-pool", "lxd",
		"--storage-create-loop", fmt.Sprintf("%d", GigaBytesToUse),
	).CombinedOutput()

	if err != nil {
		logger.Errorf("configuring zfs failed with %s: %s", err, string(output))
	}
}

var configureLXDBridge = func() error {
	client, err := ConnectLocal()
	if err != nil {
		return errors.Trace(err)
	}

	status, err := client.ServerStatus()
	if err != nil {
		return errors.Trace(err)
	}

	if shared.StringInSlice("network", status.APIExtensions) {
		return lxdclient.CreateDefaultBridgeInDefaultProfile(client)
	}

	f, err := os.OpenFile(lxdBridgeFile, os.O_RDWR, 0777)
	if err != nil {
		/* We're using an old version of LXD which doesn't have
		 * lxd-bridge; let's not fail here.
		 */
		if os.IsNotExist(err) {
			logger.Debugf("couldn't find %s, not configuring it", lxdBridgeFile)
			return nil
		}
		return errors.Trace(err)
	}
	defer f.Close()

	existing, err := ioutil.ReadAll(f)
	if err != nil {
		return errors.Trace(err)
	}

	newBridgeCfg, err := bridgeConfiguration(string(existing))
	if err != nil {
		return errors.Trace(err)
	}

	if newBridgeCfg == string(existing) {
		return nil
	}

	_, err = f.Seek(0, 0)
	if err != nil {
		return errors.Trace(err)
	}
	_, err = f.WriteString(newBridgeCfg)
	if err != nil {
		return errors.Trace(err)
	}

	/* non-systemd systems don't have the lxd-bridge service, so this always fails */
	_ = exec.Command("service", "lxd-bridge", "restart").Run()
	return exec.Command("service", "lxd", "restart").Run()
}

var interfaceAddrs = func() ([]net.Addr, error) {
	return net.InterfaceAddrs()
}

func editLXDBridgeFile(input string, subnet string) string {
	buffer := bytes.Buffer{}

	newValues := map[string]string{
		"USE_LXD_BRIDGE":      "true",
		"EXISTING_BRIDGE":     "",
		"LXD_BRIDGE":          "lxdbr0",
		"LXD_IPV4_ADDR":       fmt.Sprintf("10.0.%s.1", subnet),
		"LXD_IPV4_NETMASK":    "255.255.255.0",
		"LXD_IPV4_NETWORK":    fmt.Sprintf("10.0.%s.1/24", subnet),
		"LXD_IPV4_DHCP_RANGE": fmt.Sprintf("10.0.%s.2,10.0.%s.254", subnet, subnet),
		"LXD_IPV4_DHCP_MAX":   "253",
		"LXD_IPV4_NAT":        "true",
		"LXD_IPV6_PROXY":      "false",
	}
	found := map[string]bool{}

	for _, line := range strings.Split(input, "\n") {
		out := line

		for prefix, value := range newValues {
			if strings.HasPrefix(line, prefix+"=") {
				out = fmt.Sprintf(`%s="%s"`, prefix, value)
				found[prefix] = true
				break
			}
		}

		buffer.WriteString(out)
		buffer.WriteString("\n")
	}

	for prefix, value := range newValues {
		if !found[prefix] {
			buffer.WriteString(prefix)
			buffer.WriteString("=")
			buffer.WriteString(value)
			buffer.WriteString("\n")
			found[prefix] = true // not necessary but keeps "found" logically consistent
		}
	}

	return buffer.String()
}

// ensureDependencies creates a set of install packages using
// apt.GetPreparePackages and runs each set of packages through
// apt.GetInstall.
func ensureDependencies(series string) error {
	if series == "precise" {
		return fmt.Errorf("LXD is not supported in precise.")
	}

	pacman, err := getPackageManager(series)
	if err != nil {
		return err
	}
	pacconfer, err := getPackagingConfigurer(series)
	if err != nil {
		return err
	}

	for _, pack := range requiredPackages {
		pkg := pack
		if config.SeriesRequiresCloudArchiveTools(series) &&
			pacconfer.IsCloudArchivePackage(pack) {
			pkg = strings.Join(pacconfer.ApplyCloudArchiveTarget(pack), " ")
		}

		if config.RequiresBackports(series, pack) {
			pkg = fmt.Sprintf("--target-release %s-backports %s", series, pkg)
		}

		if err := pacman.Install(pkg); err != nil {
			return err
		}
	}

	if series >= "xenial" {
		for _, pack := range xenialPackages {
			pacman.Install(fmt.Sprintf("--no-install-recommends %s", pack))
		}
	}

	return err
}

// findNextAvailableIPv4Subnet scans the list of interfaces on the machine
// looking for 10.0.0.0/16 networks and returns the next subnet not in
// use, having first detected the highest subnet. The next subnet can
// actually be lower if we overflowed 255 whilst seeking out the next
// unused subnet. If all subnets are in use an error is returned.
//
// TODO(frobware): this is not an ideal solution as it doesn't take
// into account any static routes that may be set up on the machine.
//
// TODO(frobware): this only caters for IPv4 setups.
func findNextAvailableIPv4Subnet() (string, error) {
	_, ip10network, err := net.ParseCIDR("10.0.0.0/16")
	if err != nil {
		return "", errors.Trace(err)
	}

	addrs, err := interfaceAddrs()
	if err != nil {
		return "", errors.Annotatef(err, "cannot get network interface addresses")
	}

	max := 0
	usedSubnets := make(map[int]bool)

	for _, address := range addrs {
		addr, network, err := net.ParseCIDR(address.String())
		if err != nil {
			logger.Debugf("cannot parse address %q: %v (ignoring)", address.String(), err)
			continue
		}
		if !ip10network.Contains(addr) {
			logger.Debugf("find available subnet, skipping %q", network.String())
			continue
		}
		subnet := int(network.IP[2])
		usedSubnets[subnet] = true
		if subnet > max {
			max = subnet
		}
	}

	if len(usedSubnets) == 0 {
		return "0", nil
	}

	for i := 0; i < 256; i++ {
		max = (max + 1) % 256
		if _, inUse := usedSubnets[max]; !inUse {
			return fmt.Sprintf("%d", max), nil
		}
	}

	return "", errors.New("could not find unused subnet")
}

func parseLXDBridgeConfigValues(input string) map[string]string {
	values := make(map[string]string)

	for _, line := range strings.Split(input, "\n") {
		line = strings.TrimSpace(line)

		if line == "" || strings.HasPrefix(line, "#") || !strings.Contains(line, "=") {
			continue
		}

		tokens := strings.Split(line, "=")

		if tokens[0] == "" {
			continue // no key
		}

		value := ""

		if len(tokens) > 1 {
			value = tokens[1]
			if strings.HasPrefix(value, `"`) && strings.HasSuffix(value, `"`) {
				value = strings.Trim(value, `"`)
			}
		}

		values[tokens[0]] = value
	}
	return values
}

// bridgeConfiguration ensures that input has a valid setting for
// LXD_IPV4_ADDR, returning the existing input if is already set, and
// allocating the next available subnet if it is not.
func bridgeConfiguration(input string) (string, error) {
	values := parseLXDBridgeConfigValues(input)
	ipAddr := net.ParseIP(values["LXD_IPV4_ADDR"])

	if ipAddr == nil || ipAddr.To4() == nil {
		logger.Infof("LXD_IPV4_ADDR is not set; searching for unused subnet")
		subnet, err := findNextAvailableIPv4Subnet()
		if err != nil {
			return "", errors.Trace(err)
		}
		logger.Infof("setting LXD_IPV4_ADDR=10.0.%s.1", subnet)
		return editLXDBridgeFile(input, subnet), nil
	}
	return input, nil
}
<|endoftext|>