<commit_before>/**********************************************************************************
* Copyright (c) 2009-2018 Misakai Ltd.
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Affero General Public License as published by the  Free Software
* Foundation, either version 3 of the License, or(at your option) any later version.
*
* This program is distributed  in the hope that it  will be useful, but WITHOUT ANY
* WARRANTY;  without even  the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Affero General Public License  for  more details.
*
* You should have  received a copy  of the  GNU Affero General Public License along
* with this program. If not, see<http://www.gnu.org/licenses/>.
************************************************************************************/

package storage

import (
	"context"
	enc "encoding/binary"
	"io"
	"os"
	"time"

	"github.com/dgraph-io/badger"
	"github.com/dgraph-io/badger/protos"
	"github.com/dgraph-io/badger/y"
	"github.com/emitter-io/emitter/async"
	"github.com/emitter-io/emitter/message"
	"github.com/emitter-io/emitter/provider/logging"
	"github.com/kelindar/binary"
)

// ------------------------------------------------------------------------------------ //

// SSD represents an SSD-optimized storage storage.
type SSD struct {
	cluster Surveyor           // The cluster surveyor.
	db      *badger.DB         // The underlying database to use for messages.
	cancel  context.CancelFunc // The cancellation function.
}

// NewSSD creates a new SSD-optimized storage storage.
func NewSSD(cluster Surveyor) *SSD {
	return &SSD{
		cluster: cluster,
	}
}

// Name returns the name of the provider.
func (s *SSD) Name() string {
	return "ssd"
}

// Configure configures the storage. The config parameter provided is
// loosely typed, since various storage mechanisms will require different
// configurations.
func (s *SSD) Configure(config map[string]interface{}) error {

	// Get the interval from the provider configuration
	dir := "/data"
	if v, ok := config["dir"]; ok {
		if d, ok := v.(string); ok {
			dir = d
		}
	}

	// Make sure we have a directory
	if err := os.MkdirAll(dir, 0777); err != nil {
		panic(err)
	}

	// Create the options
	opts := badger.DefaultOptions
	opts.Dir = dir
	opts.ValueDir = opts.Dir
	opts.SyncWrites = false

	// Attempt to open the database
	db, err := badger.Open(opts)
	if err != nil {
		return err
	}

	// Setup the database and start GC
	s.db = db
	s.cancel = async.Repeat(context.Background(), 30*time.Minute, s.GC)
	return nil
}

// Store appends the messages to the store.
func (s *SSD) Store(m *message.Message) error {

	// TODO: add batching instead of storing one by one
	return s.storeFrame(message.Frame{*m})
}

// storeFrame appends the frame of messages to the store.
func (s *SSD) storeFrame(msgs message.Frame) error {
	encoded := encodeFrame(msgs)
	return s.db.Update(func(tx *badger.Txn) error {
		for _, m := range encoded {
			entry := m // Copy address
			tx.SetEntry(entry)
		}
		return nil
	})
}

// encodeMessage encodes a message frame so we can store it
func encodeFrame(msgs message.Frame) []*badger.Entry {
	entries := make([]*badger.Entry, 0, len(msgs))
	for _, m := range msgs {
		if val, err := binary.Marshal(m); err == nil {
			entries = append(entries, &badger.Entry{
				Key:       m.ID,
				Value:     val,
				ExpiresAt: uint64(m.Expires().Unix()),
			})
		}
	}
	return entries
}

// Query performs a query and attempts to fetch last n messages where
// n is specified by limit argument. From and until times can also be specified
// for time-series retrieval.
func (s *SSD) Query(ssid message.Ssid, from, until time.Time, limit int) (message.Frame, error) {

	// Construct a query and lookup locally first
	query := newLookupQuery(ssid, from, until, limit)
	match := s.lookup(query)

	// Issue the message survey to the cluster
	if req, err := binary.Marshal(query); err == nil && s.cluster != nil {
		if awaiter, err := s.cluster.Survey("ssdstore", req); err == nil {

			// Wait for all presence updates to come back (or a deadline)
			for _, resp := range awaiter.Gather(2000 * time.Millisecond) {
				if frame, err := message.DecodeFrame(resp); err == nil {
					match = append(match, frame...)
				}
			}
		}
	}

	match.Sort()
	match.Limit(limit)
	return match, nil
}

// OnSurvey handles an incoming cluster lookup request.
func (s *SSD) OnSurvey(surveyType string, payload []byte) ([]byte, bool) {
	if surveyType != "ssdstore" {
		return nil, false
	}

	// Decode the request
	var query lookupQuery
	if err := binary.Unmarshal(payload, &query); err != nil {
		return nil, false
	}

	// Check if the SSID is properly constructed
	if len(query.Ssid) < 2 {
		return nil, false
	}

	logging.LogTarget("ssd", surveyType+" survey received", query)

	// Send back the response
	f := s.lookup(query)
	b := f.Encode()
	return b, true
}

// Lookup performs a against the storage.
func (s *SSD) lookup(q lookupQuery) (matches message.Frame) {
	matches = make(message.Frame, 0, q.Limit)
	if err := s.db.View(func(tx *badger.Txn) error {
		it := tx.NewIterator(badger.IteratorOptions{
			PrefetchValues: false,
		})
		defer it.Close()

		// Since we're starting backwards, seek to the 'until' position first and then
		// we'll iterate forward but have reverse time ('until' -> 'from')
		prefix := message.NewPrefix(q.Ssid, q.Until)

		// Seek the prefix and check the key so we can quickly exit the iteration.
		for it.Seek(prefix); it.Valid() && message.ID(it.Item().Key()).HasPrefix(q.Ssid, q.From) &&
			len(matches) < q.Limit; it.Next() {
			if message.ID(it.Item().Key()).Match(q.Ssid, q.From, q.Until) {
				if msg, err := loadMessage(it.Item()); err == nil {
					matches = append(matches, msg)
				}
			}
		}

		return nil
	}); err != nil {
		logging.LogError("ssd", "query lookup", err)
	}
	return
}

// Close is used to gracefully close the connection.
func (s *SSD) Close() error {
	if s.cancel != nil {
		s.cancel()
	}

	return s.db.Close()
}

// LoadMessage loads the message from badger item.
func loadMessage(item *badger.Item) (msg message.Message, err error) {
	var data []byte
	if data, err = item.ValueCopy(nil); err == nil {
		err = binary.Unmarshal(data, &msg)
	}
	return
}

// Restore loads a previous snapshot
func (s *SSD) Restore(reader io.Reader) error {
	logging.LogAction("ssd", "reading from snapshot")
	return s.db.Load(reader)
}

// GC runs the garbage collection on the storage
func (s *SSD) GC() {
	s.db.RunValueLogGC(0.50)
}

// Backup creates a snaphshot of the store.
func (s *SSD) Backup(writer io.Writer) error {

	// Run GC before backing up
	s.GC()

	// This is a copy of badger backup except it doesn't write any
	// deleted or expired items in the snapshot.
	logging.LogAction("ssd", "writing a snapshot")
	return s.db.View(func(txn *badger.Txn) error {
		it := txn.NewIterator(badger.DefaultIteratorOptions)
		for it.Rewind(); it.Valid(); it.Next() {
			item := it.Item()
			val, err := item.Value()
			if err != nil {
				continue
			}

			entry := &protos.KVPair{
				Key:       y.Copy(item.Key()),
				Value:     y.Copy(val),
				UserMeta:  []byte{item.UserMeta()},
				Version:   item.Version(),
				ExpiresAt: item.ExpiresAt(),
			}

			// Write entries to disk
			if err := writeTo(entry, writer); err != nil {
				return err
			}
		}
		return nil
	})
}

func writeTo(entry *protos.KVPair, w io.Writer) error {
	if err := enc.Write(w, binary.LittleEndian, uint64(entry.Size())); err != nil {
		return err
	}
	buf, err := entry.Marshal()
	if err != nil {
		return err
	}
	_, err = w.Write(buf)
	return err
}
<commit_msg>removed unnecessary log<commit_after>/**********************************************************************************
* Copyright (c) 2009-2018 Misakai Ltd.
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Affero General Public License as published by the  Free Software
* Foundation, either version 3 of the License, or(at your option) any later version.
*
* This program is distributed  in the hope that it  will be useful, but WITHOUT ANY
* WARRANTY;  without even  the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Affero General Public License  for  more details.
*
* You should have  received a copy  of the  GNU Affero General Public License along
* with this program. If not, see<http://www.gnu.org/licenses/>.
************************************************************************************/

package storage

import (
	"context"
	enc "encoding/binary"
	"io"
	"os"
	"time"

	"github.com/dgraph-io/badger"
	"github.com/dgraph-io/badger/protos"
	"github.com/dgraph-io/badger/y"
	"github.com/emitter-io/emitter/async"
	"github.com/emitter-io/emitter/message"
	"github.com/emitter-io/emitter/provider/logging"
	"github.com/kelindar/binary"
)

// ------------------------------------------------------------------------------------ //

// SSD represents an SSD-optimized storage storage.
type SSD struct {
	cluster Surveyor           // The cluster surveyor.
	db      *badger.DB         // The underlying database to use for messages.
	cancel  context.CancelFunc // The cancellation function.
}

// NewSSD creates a new SSD-optimized storage storage.
func NewSSD(cluster Surveyor) *SSD {
	return &SSD{
		cluster: cluster,
	}
}

// Name returns the name of the provider.
func (s *SSD) Name() string {
	return "ssd"
}

// Configure configures the storage. The config parameter provided is
// loosely typed, since various storage mechanisms will require different
// configurations.
func (s *SSD) Configure(config map[string]interface{}) error {

	// Get the interval from the provider configuration
	dir := "/data"
	if v, ok := config["dir"]; ok {
		if d, ok := v.(string); ok {
			dir = d
		}
	}

	// Make sure we have a directory
	if err := os.MkdirAll(dir, 0777); err != nil {
		panic(err)
	}

	// Create the options
	opts := badger.DefaultOptions
	opts.Dir = dir
	opts.ValueDir = opts.Dir
	opts.SyncWrites = false

	// Attempt to open the database
	db, err := badger.Open(opts)
	if err != nil {
		return err
	}

	// Setup the database and start GC
	s.db = db
	s.cancel = async.Repeat(context.Background(), 30*time.Minute, s.GC)
	return nil
}

// Store appends the messages to the store.
func (s *SSD) Store(m *message.Message) error {

	// TODO: add batching instead of storing one by one
	return s.storeFrame(message.Frame{*m})
}

// storeFrame appends the frame of messages to the store.
func (s *SSD) storeFrame(msgs message.Frame) error {
	encoded := encodeFrame(msgs)
	return s.db.Update(func(tx *badger.Txn) error {
		for _, m := range encoded {
			entry := m // Copy address
			tx.SetEntry(entry)
		}
		return nil
	})
}

// encodeMessage encodes a message frame so we can store it
func encodeFrame(msgs message.Frame) []*badger.Entry {
	entries := make([]*badger.Entry, 0, len(msgs))
	for _, m := range msgs {
		if val, err := binary.Marshal(m); err == nil {
			entries = append(entries, &badger.Entry{
				Key:       m.ID,
				Value:     val,
				ExpiresAt: uint64(m.Expires().Unix()),
			})
		}
	}
	return entries
}

// Query performs a query and attempts to fetch last n messages where
// n is specified by limit argument. From and until times can also be specified
// for time-series retrieval.
func (s *SSD) Query(ssid message.Ssid, from, until time.Time, limit int) (message.Frame, error) {

	// Construct a query and lookup locally first
	query := newLookupQuery(ssid, from, until, limit)
	match := s.lookup(query)

	// Issue the message survey to the cluster
	if req, err := binary.Marshal(query); err == nil && s.cluster != nil {
		if awaiter, err := s.cluster.Survey("ssdstore", req); err == nil {

			// Wait for all presence updates to come back (or a deadline)
			for _, resp := range awaiter.Gather(2000 * time.Millisecond) {
				if frame, err := message.DecodeFrame(resp); err == nil {
					match = append(match, frame...)
				}
			}
		}
	}

	match.Sort()
	match.Limit(limit)
	return match, nil
}

// OnSurvey handles an incoming cluster lookup request.
func (s *SSD) OnSurvey(surveyType string, payload []byte) ([]byte, bool) {
	if surveyType != "ssdstore" {
		return nil, false
	}

	// Decode the request
	var query lookupQuery
	if err := binary.Unmarshal(payload, &query); err != nil {
		return nil, false
	}

	// Check if the SSID is properly constructed
	if len(query.Ssid) < 2 {
		return nil, false
	}

	//logging.LogTarget("ssd", surveyType+" survey received", query)

	// Send back the response
	f := s.lookup(query)
	b := f.Encode()
	return b, true
}

// Lookup performs a against the storage.
func (s *SSD) lookup(q lookupQuery) (matches message.Frame) {
	matches = make(message.Frame, 0, q.Limit)
	if err := s.db.View(func(tx *badger.Txn) error {
		it := tx.NewIterator(badger.IteratorOptions{
			PrefetchValues: false,
		})
		defer it.Close()

		// Since we're starting backwards, seek to the 'until' position first and then
		// we'll iterate forward but have reverse time ('until' -> 'from')
		prefix := message.NewPrefix(q.Ssid, q.Until)

		// Seek the prefix and check the key so we can quickly exit the iteration.
		for it.Seek(prefix); it.Valid() && message.ID(it.Item().Key()).HasPrefix(q.Ssid, q.From) &&
			len(matches) < q.Limit; it.Next() {
			if message.ID(it.Item().Key()).Match(q.Ssid, q.From, q.Until) {
				if msg, err := loadMessage(it.Item()); err == nil {
					matches = append(matches, msg)
				}
			}
		}

		return nil
	}); err != nil {
		logging.LogError("ssd", "query lookup", err)
	}
	return
}

// Close is used to gracefully close the connection.
func (s *SSD) Close() error {
	if s.cancel != nil {
		s.cancel()
	}

	return s.db.Close()
}

// LoadMessage loads the message from badger item.
func loadMessage(item *badger.Item) (msg message.Message, err error) {
	var data []byte
	if data, err = item.ValueCopy(nil); err == nil {
		err = binary.Unmarshal(data, &msg)
	}
	return
}

// Restore loads a previous snapshot
func (s *SSD) Restore(reader io.Reader) error {
	logging.LogAction("ssd", "reading from snapshot")
	return s.db.Load(reader)
}

// GC runs the garbage collection on the storage
func (s *SSD) GC() {
	s.db.RunValueLogGC(0.50)
}

// Backup creates a snaphshot of the store.
func (s *SSD) Backup(writer io.Writer) error {

	// Run GC before backing up
	s.GC()

	// This is a copy of badger backup except it doesn't write any
	// deleted or expired items in the snapshot.
	logging.LogAction("ssd", "writing a snapshot")
	return s.db.View(func(txn *badger.Txn) error {
		it := txn.NewIterator(badger.DefaultIteratorOptions)
		for it.Rewind(); it.Valid(); it.Next() {
			item := it.Item()
			val, err := item.Value()
			if err != nil {
				continue
			}

			entry := &protos.KVPair{
				Key:       y.Copy(item.Key()),
				Value:     y.Copy(val),
				UserMeta:  []byte{item.UserMeta()},
				Version:   item.Version(),
				ExpiresAt: item.ExpiresAt(),
			}

			// Write entries to disk
			if err := writeTo(entry, writer); err != nil {
				return err
			}
		}
		return nil
	})
}

func writeTo(entry *protos.KVPair, w io.Writer) error {
	if err := enc.Write(w, binary.LittleEndian, uint64(entry.Size())); err != nil {
		return err
	}
	buf, err := entry.Marshal()
	if err != nil {
		return err
	}
	_, err = w.Write(buf)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package commands

import (
	"os"
	"runtime"
	"strings"

	"github.com/bogem/vnehm/applescript"
	"github.com/bogem/vnehm/config"
	"github.com/bogem/vnehm/ui"
	"github.com/bogem/vnehm/util"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var RootCmd = listCommand

// Variables used in flags
var (
	limit, offset                       uint
	dlFolder, itunesPlaylist, permalink string
)

func Execute() {
	RootCmd.AddCommand(authCommand)
	RootCmd.AddCommand(getCommand)
	RootCmd.AddCommand(searchCommand)
	RootCmd.AddCommand(versionCommand)
	RootCmd.Execute()
}

// addCommonFlags adds common flags related to download tracks.
func addCommonFlags(cmd *cobra.Command) {
	cmd.Flags().StringVarP(&dlFolder, "dlFolder", "f", "", "filesystem path to download folder")

	if runtime.GOOS == "darwin" {
		cmd.Flags().StringVarP(&itunesPlaylist, "itunesPlaylist", "i", "", "name of iTunes playlist")
	}
}

func addLimitFlag(cmd *cobra.Command) {
	cmd.Flags().UintVarP(&limit, "limit", "l", 10, "count of tracks on each page")
}

func addOffsetFlag(cmd *cobra.Command) {
	cmd.Flags().UintVarP(&offset, "offset", "o", 0, "offset relative to first like")
}

// initializeConfig initializes a config with flags.
func initializeConfig(cmd *cobra.Command) {
	err := config.ReadInConfig()
	if err == config.ErrNotExist {
		ui.Warning("There is no config file. Read README to configure vnehm")
	} else if err != nil {
		ui.Term("", err)
	}
	checkToken()

	loadDefaultSettings()

	initializeDlFolder(cmd)
	if runtime.GOOS == "darwin" {
		initializeItunesPlaylist(cmd)
	}
}

func checkToken() {
	if config.Get("token") == "" {
		ui.Term("You aren't authorized. Please execute `vnehm auth` command to authorize", nil)
	}
}

func loadDefaultSettings() {
	config.SetDefault("dlFolder", os.Getenv("HOME"))
	config.SetDefault("itunesPlaylist", "")
}

func flagChanged(fs *pflag.FlagSet, key string) bool {
	flag := fs.Lookup(key)
	if flag == nil {
		return false
	}
	return flag.Changed
}

// initializeDlFolder initializes dlFolder value. If there is no dlFolder
// set up, then dlFolder is set to HOME env variable.
func initializeDlFolder(cmd *cobra.Command) {
	var df string
	if flagChanged(cmd.Flags(), "dlFolder") {
		df = dlFolder
	} else {
		df = config.Get("dlFolder")
	}
	config.Set("dlFolder", util.SanitizePath(df))
}

// initializeItunesPlaylist initializes itunesPlaylist value. If there is no
// itunesPlaylist set up, then itunesPlaylist set up to blank string. Blank
// string is the sign, what tracks should not to be added to iTunes.
func initializeItunesPlaylist(cmd *cobra.Command) {
	var playlist string
	if flagChanged(cmd.Flags(), "itunesPlaylist") {
		playlist = itunesPlaylist
	} else {
		playlist = config.Get("itunesPlaylist")
	}
	if playlist != "" {
		playlistsList, err := applescript.ListOfPlaylists()
		if err != nil {
			ui.Term("Couldn't get list of playlists", err)
		}
		if !strings.Contains(playlistsList, playlist) {
			ui.Term("Playlist "+playlist+" doesn't exist. Please enter correct name.", nil)
		}
	}
	config.Set("itunesPlaylist", playlist)
}
<commit_msg>Fix flags<commit_after>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package commands

import (
	"os"
	"runtime"
	"strings"

	"github.com/bogem/vnehm/applescript"
	"github.com/bogem/vnehm/config"
	"github.com/bogem/vnehm/ui"
	"github.com/bogem/vnehm/util"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var RootCmd = listCommand

// Variables used in flags
var (
	limit, offset                       uint
	dlFolder, itunesPlaylist, permalink string
)

func Execute() {
	RootCmd.AddCommand(authCommand)
	RootCmd.AddCommand(getCommand)
	RootCmd.AddCommand(searchCommand)
	RootCmd.AddCommand(versionCommand)
	RootCmd.Execute()
}

// addCommonFlags adds common flags related to download tracks.
func addCommonFlags(cmd *cobra.Command) {
	cmd.Flags().StringVarP(&dlFolder, "dlFolder", "f", "", "filesystem path to download folder")

	if runtime.GOOS == "darwin" {
		cmd.Flags().StringVarP(&itunesPlaylist, "itunesPlaylist", "i", "", "name of iTunes playlist")
	}
}

func addLimitFlag(cmd *cobra.Command) {
	cmd.Flags().UintVarP(&limit, "limit", "l", 10, "count of tracks on each page")
}

func addOffsetFlag(cmd *cobra.Command) {
	cmd.Flags().UintVarP(&offset, "offset", "o", 0, "offset relative to first like")
}

// initializeConfig initializes a config with flags.
func initializeConfig(cmd *cobra.Command) {
	err := config.ReadInConfig()
	if err == config.ErrNotExist {
		ui.Warning("There is no config file. Read README to configure vnehm")
	} else if err != nil {
		ui.Term("", err)
	}
	checkToken()

	loadDefaultSettings()

	initializeDlFolder(cmd)
	if runtime.GOOS == "darwin" {
		initializeItunesPlaylist(cmd)
	}
}

func checkToken() {
	if config.Get("token") == "" {
		ui.Term("You aren't authorized. Please execute `vnehm auth` command to authorize", nil)
	}
}

func loadDefaultSettings() {
	config.SetDefault("dlFolder", os.Getenv("HOME"))
	config.SetDefault("itunesPlaylist", "")
}

func flagChanged(fs *pflag.FlagSet, key string) bool {
	flag := fs.Lookup(key)
	if flag == nil {
		return false
	}
	return flag.Changed
}

// initializeDlFolder initializes dlFolder value. If there is no dlFolder
// set up, then dlFolder is set to HOME env variable.
func initializeDlFolder(cmd *cobra.Command) {
	var df string

	if flagChanged(cmd.Flags(), "dlFolder") {
		df = dlFolder
	} else {
		df = config.Get("dlFolder")
	}

	if df == "" {
		df = os.Getenv("HOME")
	}

	config.Set("dlFolder", util.SanitizePath(df))
}

// initializeItunesPlaylist initializes itunesPlaylist value. If there is no
// itunesPlaylist set up, then itunesPlaylist set up to blank string. Blank
// string is the sign, what tracks should not to be added to iTunes.
func initializeItunesPlaylist(cmd *cobra.Command) {
	var playlist string

	if flagChanged(cmd.Flags(), "itunesPlaylist") {
		playlist = itunesPlaylist
	} else {
		playlist = config.Get("itunesPlaylist")
	}

	if playlist != "" {
		playlistsList, err := applescript.ListOfPlaylists()
		if err != nil {
			ui.Term("Couldn't get list of playlists", err)
		}
		if !strings.Contains(playlistsList, playlist) {
			ui.Term("Playlist "+playlist+" doesn't exist. Please enter correct name.", nil)
		}
	}

	config.Set("itunesPlaylist", playlist)
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

// Populate man pages
//go:generate go run ../docs/man/mangen.go

var (
	Debugging    = false
	ErrorBuffer  = &bytes.Buffer{}
	ErrorWriter  = io.MultiWriter(os.Stderr, ErrorBuffer)
	OutputWriter = io.MultiWriter(os.Stdout, ErrorBuffer)
	RootCmd      = &cobra.Command{
		Use:   "git-lfs",
		Short: "Git LFS provides large file storage to Git.",
		Run: func(cmd *cobra.Command, args []string) {
			versionCommand(cmd, args)
			cmd.Usage()
		},
	}
	ManPages = make(map[string]string, 20)
)

// Error prints a formatted message to Stderr.  It also gets printed to the
// panic log if one is created for this command.
func Error(format string, args ...interface{}) {
	line := format
	if len(args) > 0 {
		line = fmt.Sprintf(format, args...)
	}
	fmt.Fprintln(ErrorWriter, line)
}

// Print prints a formatted message to Stdout.  It also gets printed to the
// panic log if one is created for this command.
func Print(format string, args ...interface{}) {
	line := fmt.Sprintf(format, args...)
	fmt.Fprintln(OutputWriter, line)
}

// Exit prints a formatted message and exits.
func Exit(format string, args ...interface{}) {
	Error(format, args...)
	os.Exit(2)
}

// Debug prints a formatted message if debugging is enabled.  The formatted
// message also shows up in the panic log, if created.
func Debug(format string, args ...interface{}) {
	if !Debugging {
		return
	}
	log.Printf(format, args...)
}

// LoggedError prints a formatted message to Stderr and writes a stack trace for
// the error to a log file without exiting.
func LoggedError(err error, format string, args ...interface{}) {
	Error(format, args...)
	file := handlePanic(err)

	if len(file) > 0 {
		fmt.Fprintf(os.Stderr, "\nErrors logged to %s\nUse `git lfs logs last` to view the log.\n", file)
	}
}

// Panic prints a formatted message, and writes a stack trace for the error to
// a log file before exiting.
func Panic(err error, format string, args ...interface{}) {
	LoggedError(err, format, args...)
	os.Exit(2)
}

func Run() {
	RootCmd.Execute()
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func requireStdin(msg string) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		Error("Cannot read from STDIN. %s", msg)
		os.Exit(1)
	}
}

func requireInRepo() {
	if !lfs.InRepo() {
		Print("Not in a git repository.")
		os.Exit(128)
	}
}

func handlePanic(err error) string {
	if err == nil {
		return ""
	}

	return logPanic(err)
}

func logPanic(loggedError error) string {
	var fmtWriter io.Writer = os.Stderr

	now := time.Now()
	name := now.Format("20060102T150405.999999999")
	full := filepath.Join(lfs.LocalLogDir, name+".log")

	if err := os.MkdirAll(lfs.LocalLogDir, 0755); err != nil {
		full = ""
		fmt.Fprintf(fmtWriter, "Unable to log panic to %s: %s\n\n", lfs.LocalLogDir, err.Error())
	} else if file, err := os.Create(full); err != nil {
		filename := full
		full = ""
		defer func() {
			fmt.Fprintf(fmtWriter, "Unable to log panic to %s\n\n", filename)
			logPanicToWriter(fmtWriter, err)
		}()
	} else {
		fmtWriter = file
		defer file.Close()
	}

	logPanicToWriter(fmtWriter, loggedError)

	return full
}

func logPanicToWriter(w io.Writer, loggedError error) {
	// log the version
	gitV, err := git.Config.Version()
	if err != nil {
		gitV = "Error getting git version: " + err.Error()
	}

	fmt.Fprintln(w, lfs.UserAgent)
	fmt.Fprintln(w, gitV)

	// log the command that was run
	fmt.Fprintln(w)
	fmt.Fprintf(w, "$ %s", filepath.Base(os.Args[0]))
	if len(os.Args) > 0 {
		fmt.Fprintf(w, " %s", strings.Join(os.Args[1:], " "))
	}
	fmt.Fprintln(w)

	// log the error message and stack trace
	w.Write(ErrorBuffer.Bytes())
	fmt.Fprintln(w)

	fmt.Fprintln(w, loggedError.Error())

	if err, ok := loggedError.(ErrorWithStack); ok {
		fmt.Fprintln(w, err.InnerError())
		for key, value := range err.Context() {
			fmt.Fprintf(w, "%s=%s\n", key, value)
		}
		w.Write(err.Stack())
	} else {
		w.Write(lfs.Stack())
	}
	fmt.Fprintln(w, "\nENV:")

	// log the environment
	for _, env := range lfs.Environ() {
		fmt.Fprintln(w, env)
	}
}

type ErrorWithStack interface {
	Context() map[string]string
	InnerError() string
	Stack() []byte
}

// determineIncludeExcludePaths is a common function to take the string arguments
// for include/exclude and derive slices either from these options or from the
// common global config
func determineIncludeExcludePaths(includeArg, excludeArg string) (include, exclude []string) {
	var includePaths, excludePaths []string
	if len(includeArg) > 0 {
		for _, inc := range strings.Split(includeArg, ",") {
			inc = strings.TrimSpace(inc)
			includePaths = append(includePaths, inc)
		}
	} else {
		includePaths = lfs.Config.FetchIncludePaths()
	}
	if len(excludeArg) > 0 {
		for _, ex := range strings.Split(excludeArg, ",") {
			ex = strings.TrimSpace(ex)
			excludePaths = append(excludePaths, ex)
		}
	} else {
		excludePaths = lfs.Config.FetchExcludePaths()
	}
	return includePaths, excludePaths
}

func printHelp(commandName string) {
	if txt, ok := ManPages[commandName]; ok {
		fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(txt))
	} else {
		fmt.Fprintf(os.Stderr, "Sorry, no usage text found for %q\n", commandName)
	}
}

// help is used for 'git-lfs help <command>'
func help(cmd *cobra.Command, args []string) {
	if len(args) == 0 {
		printHelp("git-lfs")
	} else {
		printHelp(args[0])
	}

}

// usage is used for 'git-lfs <command> --help' or when invoked manually
func usage(cmd *cobra.Command) error {
	printHelp(cmd.Name())
	return nil
}

func init() {
	log.SetOutput(ErrorWriter)
	// Set up help/usage funcs based on manpage text
	RootCmd.SetHelpFunc(help)
	RootCmd.SetUsageFunc(usage)
}
<commit_msg>アーア アアアア アーアー<commit_after>package commands

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

// Populate man pages
//go:generate go run ../docs/man/mangen.go

var (
	Debugging    = false
	ErrorBuffer  = &bytes.Buffer{}
	ErrorWriter  = io.MultiWriter(os.Stderr, ErrorBuffer)
	OutputWriter = io.MultiWriter(os.Stdout, ErrorBuffer)
	RootCmd      = &cobra.Command{
		Use:   "git-lfs",
		Short: "Git LFS provides large file storage to Git.",
		Run: func(cmd *cobra.Command, args []string) {
			versionCommand(cmd, args)
			cmd.Usage()
		},
	}
	ManPages = make(map[string]string, 20)
)

// Error prints a formatted message to Stderr.  It also gets printed to the
// panic log if one is created for this command.
func Error(format string, args ...interface{}) {
	line := format
	if len(args) > 0 {
		line = fmt.Sprintf(format, args...)
	}
	fmt.Fprintln(ErrorWriter, line)
}

// Print prints a formatted message to Stdout.  It also gets printed to the
// panic log if one is created for this command.
func Print(format string, args ...interface{}) {
	line := fmt.Sprintf(format, args...)
	fmt.Fprintln(OutputWriter, line)
}

// Exit prints a formatted message and exits.
func Exit(format string, args ...interface{}) {
	Error(format, args...)
	os.Exit(2)
}

// Debug prints a formatted message if debugging is enabled.  The formatted
// message also shows up in the panic log, if created.
func Debug(format string, args ...interface{}) {
	if !Debugging {
		return
	}
	log.Printf(format, args...)
}

// LoggedError prints a formatted message to Stderr and writes a stack trace for
// the error to a log file without exiting.
func LoggedError(err error, format string, args ...interface{}) {
	Error(format, args...)
	file := handlePanic(err)

	if len(file) > 0 {
		fmt.Fprintf(os.Stderr, "\nErrors logged to %s\nUse `git lfs logs last` to view the log.\n", file)
	}
}

// Panic prints a formatted message, and writes a stack trace for the error to
// a log file before exiting.
func Panic(err error, format string, args ...interface{}) {
	LoggedError(err, format, args...)
	os.Exit(2)
}

func Run() {
	RootCmd.Execute()
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func requireStdin(msg string) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		Error("Cannot read from STDIN. %s", msg)
		os.Exit(1)
	}
}

func requireInRepo() {
	if !lfs.InRepo() {
		Print("Not in a git repository.")
		os.Exit(128)
	}
}

func handlePanic(err error) string {
	if err == nil {
		return ""
	}

	return logPanic(err)
}

func logPanic(loggedError error) string {
	var fmtWriter io.Writer = os.Stderr

	now := time.Now()
	name := now.Format("20060102T150405.999999999")
	full := filepath.Join(lfs.LocalLogDir, name+".log")

	if err := os.MkdirAll(lfs.LocalLogDir, 0755); err != nil {
		full = ""
		fmt.Fprintf(fmtWriter, "Unable to log panic to %s: %s\n\n", lfs.LocalLogDir, err.Error())
	} else if file, err := os.Create(full); err != nil {
		filename := full
		full = ""
		defer func() {
			fmt.Fprintf(fmtWriter, "Unable to log panic to %s\n\n", filename)
			logPanicToWriter(fmtWriter, err)
		}()
	} else {
		fmtWriter = file
		defer file.Close()
	}

	logPanicToWriter(fmtWriter, loggedError)

	return full
}

func logPanicToWriter(w io.Writer, loggedError error) {
	// log the version
	gitV, err := git.Config.Version()
	if err != nil {
		gitV = "Error getting git version: " + err.Error()
	}

	fmt.Fprintln(w, lfs.UserAgent)
	fmt.Fprintln(w, gitV)

	// log the command that was run
	fmt.Fprintln(w)
	fmt.Fprintf(w, "$ %s", filepath.Base(os.Args[0]))
	if len(os.Args) > 0 {
		fmt.Fprintf(w, " %s", strings.Join(os.Args[1:], " "))
	}
	fmt.Fprintln(w)

	// log the error message and stack trace
	w.Write(ErrorBuffer.Bytes())
	fmt.Fprintln(w)

	fmt.Fprintln(w, loggedError.Error())

	if err, ok := loggedError.(ErrorWithStack); ok {
		fmt.Fprintln(w, err.InnerError())
		for key, value := range err.Context() {
			fmt.Fprintf(w, "%s=%s\n", key, value)
		}
		w.Write(err.Stack())
	} else {
		w.Write(lfs.Stack())
	}
	fmt.Fprintln(w, "\nENV:")

	// log the environment
	for _, env := range lfs.Environ() {
		fmt.Fprintln(w, env)
	}
}

type ErrorWithStack interface {
	Context() map[string]string
	InnerError() string
	Stack() []byte
}

// determineIncludeExcludePaths is a common function to take the string arguments
// for include/exclude and derive slices either from these options or from the
// common global config
func determineIncludeExcludePaths(includeArg, excludeArg string) (include, exclude []string) {
	var includePaths, excludePaths []string
	if len(includeArg) > 0 {
		for _, inc := range strings.Split(includeArg, ",") {
			inc = strings.TrimSpace(inc)
			includePaths = append(includePaths, inc)
		}
	} else {
		includePaths = lfs.Config.FetchIncludePaths()
	}
	if len(excludeArg) > 0 {
		for _, ex := range strings.Split(excludeArg, ",") {
			ex = strings.TrimSpace(ex)
			excludePaths = append(excludePaths, ex)
		}
	} else {
		excludePaths = lfs.Config.FetchExcludePaths()
	}
	return includePaths, excludePaths
}

func printHelp(commandName string) {
	if txt, ok := ManPages[commandName]; ok {
		fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(txt))
	} else {
		fmt.Fprintf(os.Stderr, "Sorry, no usage text found for %q\n", commandName)
	}
}

// help is used for 'git-lfs help <command>'
func help(cmd *cobra.Command, args []string) {
	if len(args) == 0 {
		printHelp("git-lfs")
	} else {
		printHelp(args[0])
	}

}

// usage is used for 'git-lfs <command> --help' or when invoked manually
func usage(cmd *cobra.Command) error {
	printHelp(cmd.Name())
	return nil
}

func init() {
	log.SetOutput(ErrorWriter)
	// Set up help/usage funcs based on manpage text
	RootCmd.SetHelpFunc(help)
	RootCmd.SetHelpTemplate("{{.UsageString}}")
	RootCmd.SetUsageFunc(usage)
}
<|endoftext|>


<commit_before>package log

import (
	"io"
	"log"
	"os"
	"time"

	"v2ray.com/core/common/platform"
	"v2ray.com/core/common/signal"
)

type LogWriter interface {
	io.WriteCloser
}

type LogWriterCreator func() LogWriter

type generalLogger struct {
	creator LogWriterCreator
	buffer  chan Message
	access  *signal.Semaphore
}

// NewLogger returns a generic log handler that can handle all type of messages.
func NewLogger(logWriterCreator LogWriterCreator) Handler {
	return &generalLogger{
		creator: logWriterCreator,
		buffer:  make(chan Message, 16),
		access:  signal.NewSemaphore(1),
	}
}

func (l *generalLogger) run() {
	defer l.access.Signal()

	dataWritten := false
	ticker := time.NewTicker(time.Minute)
	defer ticker.Stop()

	logger := l.creator()
	if logger == nil {
		return
	}
	defer logger.Close()

	ls := []byte(platform.LineSeparator())

	for {
		select {
		case msg := <-l.buffer:
			logger.Write([]byte(msg.String()))
			logger.Write(ls)
			dataWritten = true
		case <-ticker.C:
			if !dataWritten {
				return
			}
			dataWritten = false
		}
	}
}

func (l *generalLogger) Handle(msg Message) {
	select {
	case l.buffer <- msg:
	default:
	}

	select {
	case <-l.access.Wait():
		go l.run()
	default:
	}
}

type consoleLogWriter struct {
	logger *log.Logger
}

func (w *consoleLogWriter) Write(b []byte) (int, error) {
	w.logger.Print(string(b))
	return len(b), nil
}

func (w *consoleLogWriter) Close() error {
	return nil
}

type fileLogWriter struct {
	file   *os.File
	logger *log.Logger
}

func (w *fileLogWriter) Write(b []byte) (int, error) {
	w.logger.Print(string(b))
	return len(b), nil
}

func (w *fileLogWriter) Close() error {
	return w.file.Close()
}

func CreateStdoutLogWriter() LogWriterCreator {
	return func() LogWriter {
		return &consoleLogWriter{
			logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
		}
	}
}

func CreateFileLogWriter(path string) (LogWriterCreator, error) {
	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
	if err != nil {
		return nil, err
	}
	file.Close()
	return func() LogWriter {
		file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
		if err != nil {
			return nil
		}
		return &fileLogWriter{
			file:   file,
			logger: log.New(file, "", log.Ldate|log.Ltime),
		}
	}, nil
}

func init() {
	RegisterHandler(NewLogger(CreateStdoutLogWriter()))
}
<commit_msg>fix log format<commit_after>package log

import (
	"io"
	"log"
	"os"
	"time"

	"v2ray.com/core/common/platform"
	"v2ray.com/core/common/signal"
)

type LogWriter interface {
	Write(string) error
	io.Closer
}

type LogWriterCreator func() LogWriter

type generalLogger struct {
	creator LogWriterCreator
	buffer  chan Message
	access  *signal.Semaphore
}

// NewLogger returns a generic log handler that can handle all type of messages.
func NewLogger(logWriterCreator LogWriterCreator) Handler {
	return &generalLogger{
		creator: logWriterCreator,
		buffer:  make(chan Message, 16),
		access:  signal.NewSemaphore(1),
	}
}

func (l *generalLogger) run() {
	defer l.access.Signal()

	dataWritten := false
	ticker := time.NewTicker(time.Minute)
	defer ticker.Stop()

	logger := l.creator()
	if logger == nil {
		return
	}
	defer logger.Close()

	for {
		select {
		case msg := <-l.buffer:
			logger.Write(msg.String() + platform.LineSeparator())
			dataWritten = true
		case <-ticker.C:
			if !dataWritten {
				return
			}
			dataWritten = false
		}
	}
}

func (l *generalLogger) Handle(msg Message) {
	select {
	case l.buffer <- msg:
	default:
	}

	select {
	case <-l.access.Wait():
		go l.run()
	default:
	}
}

type consoleLogWriter struct {
	logger *log.Logger
}

func (w *consoleLogWriter) Write(s string) error {
	w.logger.Print(s)
	return nil
}

func (w *consoleLogWriter) Close() error {
	return nil
}

type fileLogWriter struct {
	file   *os.File
	logger *log.Logger
}

func (w *fileLogWriter) Write(s string) error {
	w.logger.Print(s)
	return nil
}

func (w *fileLogWriter) Close() error {
	return w.file.Close()
}

func CreateStdoutLogWriter() LogWriterCreator {
	return func() LogWriter {
		return &consoleLogWriter{
			logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
		}
	}
}

func CreateFileLogWriter(path string) (LogWriterCreator, error) {
	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
	if err != nil {
		return nil, err
	}
	file.Close()
	return func() LogWriter {
		file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
		if err != nil {
			return nil
		}
		return &fileLogWriter{
			file:   file,
			logger: log.New(file, "", log.Ldate|log.Ltime),
		}
	}, nil
}

func init() {
	RegisterHandler(NewLogger(CreateStdoutLogWriter()))
}
<|endoftext|>


<commit_before>package openstack

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
)

func resourceNetworkingRouterInterfaceV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingRouterInterfaceV2Create,
		Read:   resourceNetworkingRouterInterfaceV2Read,
		Delete: resourceNetworkingRouterInterfaceV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
			},
			"router_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subnet_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"port_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

func resourceNetworkingRouterInterfaceV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	createOpts := routers.AddInterfaceOpts{
		SubnetID: d.Get("subnet_id").(string),
		PortID:   d.Get("port_id").(string),
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)
	n, err := routers.AddInterface(networkingClient, d.Get("router_id").(string), createOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error creating OpenStack Neutron router interface: %s", err)
	}
	log.Printf("[INFO] Router interface Port ID: %s", n.PortID)

	log.Printf("[DEBUG] Waiting for Router Interface (%s) to become available", n.PortID)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
		Target:     []string{"ACTIVE"},
		Refresh:    waitForRouterInterfaceActive(networkingClient, n.PortID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(n.PortID)

	return resourceNetworkingRouterInterfaceV2Read(d, meta)
}

func resourceNetworkingRouterInterfaceV2Read(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	n, err := ports.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		if _, ok := err.(gophercloud.ErrDefault404); ok {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving OpenStack Neutron Router Interface: %s", err)
	}

	log.Printf("[DEBUG] Retreived Router Interface %s: %+v", d.Id(), n)

	return nil
}

func resourceNetworkingRouterInterfaceV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE"},
		Target:     []string{"DELETED"},
		Refresh:    waitForRouterInterfaceDelete(networkingClient, d),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack Neutron Router Interface: %s", err)
	}

	d.SetId("")
	return nil
}

func waitForRouterInterfaceActive(networkingClient *gophercloud.ServiceClient, rId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		r, err := ports.Get(networkingClient, rId).Extract()
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] OpenStack Neutron Router Interface: %+v", r)
		return r, r.Status, nil
	}
}

func waitForRouterInterfaceDelete(networkingClient *gophercloud.ServiceClient, d *schema.ResourceData) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		routerId := d.Get("router_id").(string)
		routerInterfaceId := d.Id()

		log.Printf("[DEBUG] Attempting to delete OpenStack Router Interface %s.\n", routerInterfaceId)

		removeOpts := routers.RemoveInterfaceOpts{
			SubnetID: d.Get("subnet_id").(string),
			PortID:   d.Get("port_id").(string),
		}

		r, err := ports.Get(networkingClient, routerInterfaceId).Extract()
		if err != nil {
			if _, ok := err.(gophercloud.ErrDefault404); ok {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
				return r, "DELETED", nil
			}
			return r, "ACTIVE", err
		}

		_, err = routers.RemoveInterface(networkingClient, routerId, removeOpts).Extract()
		if err != nil {
			if _, ok := err.(gophercloud.ErrDefault404); ok {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
				return r, "DELETED", nil
			}
			return r, "ACTIVE", err
		}

		log.Printf("[DEBUG] OpenStack Router Interface %s still active.\n", routerInterfaceId)
		return r, "ACTIVE", nil
	}
}
<commit_msg>provider/openstack: gophercloud migration: router interface error response<commit_after>package openstack

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
)

func resourceNetworkingRouterInterfaceV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingRouterInterfaceV2Create,
		Read:   resourceNetworkingRouterInterfaceV2Read,
		Delete: resourceNetworkingRouterInterfaceV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
			},
			"router_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subnet_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"port_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

func resourceNetworkingRouterInterfaceV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	createOpts := routers.AddInterfaceOpts{
		SubnetID: d.Get("subnet_id").(string),
		PortID:   d.Get("port_id").(string),
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)
	n, err := routers.AddInterface(networkingClient, d.Get("router_id").(string), createOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error creating OpenStack Neutron router interface: %s", err)
	}
	log.Printf("[INFO] Router interface Port ID: %s", n.PortID)

	log.Printf("[DEBUG] Waiting for Router Interface (%s) to become available", n.PortID)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
		Target:     []string{"ACTIVE"},
		Refresh:    waitForRouterInterfaceActive(networkingClient, n.PortID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(n.PortID)

	return resourceNetworkingRouterInterfaceV2Read(d, meta)
}

func resourceNetworkingRouterInterfaceV2Read(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	n, err := ports.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		if _, ok := err.(gophercloud.ErrDefault404); ok {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving OpenStack Neutron Router Interface: %s", err)
	}

	log.Printf("[DEBUG] Retreived Router Interface %s: %+v", d.Id(), n)

	return nil
}

func resourceNetworkingRouterInterfaceV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE"},
		Target:     []string{"DELETED"},
		Refresh:    waitForRouterInterfaceDelete(networkingClient, d),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack Neutron Router Interface: %s", err)
	}

	d.SetId("")
	return nil
}

func waitForRouterInterfaceActive(networkingClient *gophercloud.ServiceClient, rId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		r, err := ports.Get(networkingClient, rId).Extract()
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] OpenStack Neutron Router Interface: %+v", r)
		return r, r.Status, nil
	}
}

func waitForRouterInterfaceDelete(networkingClient *gophercloud.ServiceClient, d *schema.ResourceData) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		routerId := d.Get("router_id").(string)
		routerInterfaceId := d.Id()

		log.Printf("[DEBUG] Attempting to delete OpenStack Router Interface %s.", routerInterfaceId)

		removeOpts := routers.RemoveInterfaceOpts{
			SubnetID: d.Get("subnet_id").(string),
			PortID:   d.Get("port_id").(string),
		}

		r, err := ports.Get(networkingClient, routerInterfaceId).Extract()
		if err != nil {
			if _, ok := err.(gophercloud.ErrDefault404); ok {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
				return r, "DELETED", nil
			}
			return r, "ACTIVE", err
		}

		_, err = routers.RemoveInterface(networkingClient, routerId, removeOpts).Extract()
		if err != nil {
			if _, ok := err.(gophercloud.ErrDefault404); ok {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
				return r, "DELETED", nil
			}

			if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok {
				if errCode.Actual == 409 {
					log.Printf("[DEBUG] Received a 409 response. Interface still in use.")
					return r, "ACTIVE", nil
				}
			}

			return r, "ACTIVE", err
		}

		log.Printf("[DEBUG] OpenStack Router Interface %s still active.", routerInterfaceId)
		return r, "ACTIVE", nil
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

// This file sets up the variables used, including testInitFns.
// Each file should add initialization that should be performed
// after flags are parsed.
//
// init is a multi-step process:
//   - setup vars (handled by init functions in each file)
//   - parse flags
//   - setup derived vars (handled by pre-init registered functions - registered in init function)
//   - post init (handled by post-init registered functions - registered in init function)
// This way, no one has to manage carefully control the initialization
// using file names, etc.
//
// Tests which require external dependencies need the -tag=x parameter.
// They should be run as:
//    go test -tags=x -run=. <other parameters ...>
// Benchmarks should also take this parameter, to include the sereal, xdr, etc.
// To run against codecgen, etc, make sure you pass extra parameters.
// Example usage:
//    go test "-tags=x codecgen" -bench=. <other parameters ...>
//
// To fully test everything:
//    go test -tags=x -benchtime=100ms -tv -bg -bi  -brw -bu -v -run=. -bench=.

// Handling flags
// codec_test.go will define a set of global flags for testing, including:
//   - Use Reset
//   - Use IO reader/writer (vs direct bytes)
//   - Set Canonical
//   - Set InternStrings
//   - Use Symbols
//
// This way, we can test them all by running same set of tests with a different
// set of flags.
//
// Following this, all the benchmarks will utilize flags set by codec_test.go
// and will not redefine these "global" flags.

import (
	"bytes"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"sync"
)

import . "github.com/ugorji/go/codec"

type testHED struct {
	H Handle
	E *Encoder
	D *Decoder
}

type ioReaderWrapper struct {
	r io.Reader
}

func (x ioReaderWrapper) Read(p []byte) (n int, err error) {
	return x.r.Read(p)
}

type ioWriterWrapper struct {
	w io.Writer
}

func (x ioWriterWrapper) Write(p []byte) (n int, err error) {
	return x.w.Write(p)
}

var (
	// testNoopH    = NoopHandle(8)
	testMsgpackH = &MsgpackHandle{}
	testBincH    = &BincHandle{}
	testSimpleH  = &SimpleHandle{}
	testCborH    = &CborHandle{}
	testJsonH    = &JsonHandle{}

	testHandles     []Handle
	testPreInitFns  []func()
	testPostInitFns []func()

	testOnce sync.Once

	testHEDs []testHED
)

// flag variables used by tests (and bench)
var (
	testVerbose bool

	//depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc
	//For depth>1, we likely trigger stack growth for encoders, making benchmarking unreliable.
	testDepth int

	testMaxInitLen int

	testInitDebug bool
	testUseReset  bool
	testSkipIntf  bool
	testUseMust   bool

	testUseIoEncDec  int
	testUseIoWrapper bool

	testNumRepeatString int

	testRpcBufsize       int
	testMapStringKeyOnly bool
)

// variables that are not flags, but which can configure the handles
var (
	testEncodeOptions EncodeOptions
	testDecodeOptions DecodeOptions
)

func init() {
	log.SetOutput(ioutil.Discard) // don't allow things log to standard out/err
	testHEDs = make([]testHED, 0, 32)
	testHandles = append(testHandles,
		// testNoopH,
		testMsgpackH, testBincH, testSimpleH, testCborH, testJsonH)
	// JSON should do HTMLCharsAsIs by default
	testJsonH.HTMLCharsAsIs = true
	// set ExplicitRelease on each handle
	testMsgpackH.ExplicitRelease = true
	testBincH.ExplicitRelease = true
	testSimpleH.ExplicitRelease = true
	testCborH.ExplicitRelease = true
	testJsonH.ExplicitRelease = true

	testInitFlags()
	benchInitFlags()
}

func testInitFlags() {
	// delete(testDecOpts.ExtFuncs, timeTyp)
	flag.BoolVar(&testVerbose, "tv", false, "Text Extra Verbose Logging if -v if set")
	flag.BoolVar(&testInitDebug, "tg", false, "Test Init Debug")
	flag.IntVar(&testUseIoEncDec, "ti", -1, "Use IO Reader/Writer for Marshal/Unmarshal ie >= 0")
	flag.BoolVar(&testUseIoWrapper, "tiw", false, "Wrap the IO Reader/Writer with a base pass-through reader/writer")

	flag.BoolVar(&testSkipIntf, "tf", false, "Skip Interfaces")
	flag.BoolVar(&testUseReset, "tr", false, "Use Reset")
	flag.IntVar(&testNumRepeatString, "trs", 8, "Create string variables by repeating a string N times")
	flag.BoolVar(&testUseMust, "tm", true, "Use Must(En|De)code")

	flag.IntVar(&testMaxInitLen, "tx", 0, "Max Init Len")

	flag.IntVar(&testDepth, "tsd", 0, "Test Struc Depth")
	flag.BoolVar(&testMapStringKeyOnly, "tsk", false, "use maps with string keys only")
}

func benchInitFlags() {
	// flags reproduced here for compatibility (duplicate some in testInitFlags)
	flag.BoolVar(&testMapStringKeyOnly, "bs", false, "use maps with string keys only")
	flag.IntVar(&testDepth, "bd", 1, "Bench Depth")
}

func testHEDGet(h Handle) *testHED {
	for i := range testHEDs {
		v := &testHEDs[i]
		if v.H == h {
			return v
		}
	}
	testHEDs = append(testHEDs, testHED{h, NewEncoder(nil, h), NewDecoder(nil, h)})
	return &testHEDs[len(testHEDs)-1]
}

func testReinit() {
	testOnce = sync.Once{}
	testHEDs = nil
}

func testInitAll() {
	// only parse it once.
	if !flag.Parsed() {
		flag.Parse()
	}
	for _, f := range testPreInitFns {
		f()
	}
	for _, f := range testPostInitFns {
		f()
	}
}

func sTestCodecEncode(ts interface{}, bsIn []byte, fn func([]byte) *bytes.Buffer,
	h Handle, bh *BasicHandle) (bs []byte, err error) {
	// bs = make([]byte, 0, approxSize)
	var e *Encoder
	var buf *bytes.Buffer
	if testUseReset {
		e = testHEDGet(h).E
	} else {
		e = NewEncoder(nil, h)
	}
	var oldWriteBufferSize int
	if testUseIoEncDec >= 0 {
		buf = fn(bsIn)
		// set the encode options for using a buffer
		oldWriteBufferSize = bh.WriterBufferSize
		bh.WriterBufferSize = testUseIoEncDec
		if testUseIoWrapper {
			e.Reset(ioWriterWrapper{buf})
		} else {
			e.Reset(buf)
		}
	} else {
		bs = bsIn
		e.ResetBytes(&bs)
	}
	if testUseMust {
		e.MustEncode(ts)
	} else {
		err = e.Encode(ts)
	}
	if testUseIoEncDec >= 0 {
		bs = buf.Bytes()
		bh.WriterBufferSize = oldWriteBufferSize
	}
	if !testUseReset {
		e.Release()
	}
	return
}

func sTestCodecDecode(bs []byte, ts interface{}, h Handle, bh *BasicHandle) (err error) {
	var d *Decoder
	// var buf *bytes.Reader
	if testUseReset {
		d = testHEDGet(h).D
	} else {
		d = NewDecoder(nil, h)
	}
	var oldReadBufferSize int
	if testUseIoEncDec >= 0 {
		buf := bytes.NewReader(bs)
		oldReadBufferSize = bh.ReaderBufferSize
		bh.ReaderBufferSize = testUseIoEncDec
		if testUseIoWrapper {
			d.Reset(ioReaderWrapper{buf})
		} else {
			d.Reset(buf)
		}
	} else {
		d.ResetBytes(bs)
	}
	if testUseMust {
		d.MustDecode(ts)
	} else {
		err = d.Decode(ts)
	}
	if testUseIoEncDec >= 0 {
		bh.ReaderBufferSize = oldReadBufferSize
	}
	if !testUseReset {
		d.Release()
	}
	return
}

// // --- functions below are used by both benchmarks and tests

// // log message only when testVerbose = true (ie go test ... -- -tv).
// //
// // These are for intormational messages that do not necessarily
// // help with diagnosing a failure, or which are too large.
// func logTv(x interface{}, format string, args ...interface{}) {
// 	if !testVerbose {
// 		return
// 	}
// 	if t, ok := x.(testing.TB); ok { // only available from go 1.9
// 		t.Helper()
// 	}
// 	logT(x, format, args...)
// }

// // logT logs messages when running as go test -v
// //
// // Use it for diagnostics messages that help diagnost failure,
// // and when the output is not too long ie shorter than like 100 characters.
// //
// // In general, any logT followed by failT should call this.
// func logT(x interface{}, format string, args ...interface{}) {
// 	if x == nil {
// 		if len(format) == 0 || format[len(format)-1] != '\n' {
// 			format = format + "\n"
// 		}
// 		fmt.Printf(format, args...)
// 		return
// 	}
// 	if t, ok := x.(testing.TB); ok { // only available from go 1.9
// 		t.Helper()
// 		t.Logf(format, args...)
// 	}
// }

// func failTv(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	if testVerbose {
// 		failTMsg(x, args...)
// 	}
// 	x.FailNow()
// }

// func failT(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	failTMsg(x, args...)
// 	x.FailNow()
// }

// func failTMsg(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	if len(args) > 0 {
// 		if format, ok := args[0].(string); ok {
// 			logT(x, format, args[1:]...)
// 		} else if len(args) == 1 {
// 			logT(x, "%v", args[0])
// 		} else {
// 			logT(x, "%v", args)
// 		}
// 	}
// }

// --- functions below are used only by benchmarks alone

func fnBenchmarkByteBuf(bsIn []byte) (buf *bytes.Buffer) {
	// var buf bytes.Buffer
	// buf.Grow(approxSize)
	buf = bytes.NewBuffer(bsIn)
	buf.Truncate(0)
	return
}

// func benchFnCodecEncode(ts interface{}, bsIn []byte, h Handle) (bs []byte, err error) {
// 	return testCodecEncode(ts, bsIn, fnBenchmarkByteBuf, h)
// }

// func benchFnCodecDecode(bs []byte, ts interface{}, h Handle) (err error) {
// 	return testCodecDecode(bs, ts, h)
// }
<commit_msg>codec bench: re-factoring<commit_after>// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

// This file sets up the variables used, including testInitFns.
// Each file should add initialization that should be performed
// after flags are parsed.
//
// init is a multi-step process:
//   - setup vars (handled by init functions in each file)
//   - parse flags
//   - setup derived vars (handled by pre-init registered functions - registered in init function)
//   - post init (handled by post-init registered functions - registered in init function)
// This way, no one has to manage carefully control the initialization
// using file names, etc.
//
// Tests which require external dependencies need the -tag=x parameter.
// They should be run as:
//    go test -tags=x -run=. <other parameters ...>
// Benchmarks should also take this parameter, to include the sereal, xdr, etc.
// To run against codecgen, etc, make sure you pass extra parameters.
// Example usage:
//    go test "-tags=x codecgen" -bench=. <other parameters ...>
//
// To fully test everything:
//    go test -tags=x -benchtime=100ms -tv -bg -bi  -brw -bu -v -run=. -bench=.

// Handling flags
// codec_test.go will define a set of global flags for testing, including:
//   - Use Reset
//   - Use IO reader/writer (vs direct bytes)
//   - Set Canonical
//   - Set InternStrings
//   - Use Symbols
//
// This way, we can test them all by running same set of tests with a different
// set of flags.
//
// Following this, all the benchmarks will utilize flags set by codec_test.go
// and will not redefine these "global" flags.

import (
	"bytes"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"sync"
)

import . "github.com/ugorji/go/codec"

type testHED struct {
	H Handle
	E *Encoder
	D *Decoder
}

type ioReaderWrapper struct {
	r io.Reader
}

func (x ioReaderWrapper) Read(p []byte) (n int, err error) {
	return x.r.Read(p)
}

type ioWriterWrapper struct {
	w io.Writer
}

func (x ioWriterWrapper) Write(p []byte) (n int, err error) {
	return x.w.Write(p)
}

var (
	// testNoopH    = NoopHandle(8)
	testMsgpackH = &MsgpackHandle{}
	testBincH    = &BincHandle{}
	testSimpleH  = &SimpleHandle{}
	testCborH    = &CborHandle{}
	testJsonH    = &JsonHandle{}

	testHandles     []Handle
	testPreInitFns  []func()
	testPostInitFns []func()

	testOnce sync.Once

	testHEDs []testHED
)

// flag variables used by tests (and bench)
var (
	testVerbose bool

	//depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc
	//For depth>1, we likely trigger stack growth for encoders, making benchmarking unreliable.
	testDepth int

	testMaxInitLen int

	testInitDebug bool
	testUseReset  bool
	testSkipIntf  bool
	testUseMust   bool

	testUseIoEncDec  int
	testUseIoWrapper bool

	testNumRepeatString int

	testRpcBufsize       int
	testMapStringKeyOnly bool
)

// variables that are not flags, but which can configure the handles
var (
	testEncodeOptions EncodeOptions
	testDecodeOptions DecodeOptions
)

func init() {
	log.SetOutput(ioutil.Discard) // don't allow things log to standard out/err
	testHEDs = make([]testHED, 0, 32)
	testHandles = append(testHandles,
		// testNoopH,
		testMsgpackH, testBincH, testSimpleH, testCborH, testJsonH)
	// JSON should do HTMLCharsAsIs by default
	testJsonH.HTMLCharsAsIs = true
	// set ExplicitRelease on each handle
	testMsgpackH.ExplicitRelease = true
	testBincH.ExplicitRelease = true
	testSimpleH.ExplicitRelease = true
	testCborH.ExplicitRelease = true
	testJsonH.ExplicitRelease = true

	testInitFlags()
	benchInitFlags()
}

func testInitFlags() {
	// delete(testDecOpts.ExtFuncs, timeTyp)
	flag.BoolVar(&testVerbose, "tv", false, "Text Extra Verbose Logging if -v if set")
	flag.BoolVar(&testInitDebug, "tg", false, "Test Init Debug")
	flag.IntVar(&testUseIoEncDec, "ti", -1, "Use IO Reader/Writer for Marshal/Unmarshal ie >= 0")
	flag.BoolVar(&testUseIoWrapper, "tiw", false, "Wrap the IO Reader/Writer with a base pass-through reader/writer")

	flag.BoolVar(&testSkipIntf, "tf", false, "Skip Interfaces")
	flag.BoolVar(&testUseReset, "tr", false, "Use Reset")
	flag.IntVar(&testNumRepeatString, "trs", 8, "Create string variables by repeating a string N times")
	flag.BoolVar(&testUseMust, "tm", true, "Use Must(En|De)code")

	flag.IntVar(&testMaxInitLen, "tx", 0, "Max Init Len")

	flag.IntVar(&testDepth, "tsd", 0, "Test Struc Depth")
	flag.BoolVar(&testMapStringKeyOnly, "tsk", false, "use maps with string keys only")
}

func benchInitFlags() {
	// flags reproduced here for compatibility (duplicate some in testInitFlags)
	flag.BoolVar(&testMapStringKeyOnly, "bs", false, "use maps with string keys only")
	flag.IntVar(&testDepth, "bd", 1, "Bench Depth")
}

func testHEDGet(h Handle) *testHED {
	for i := range testHEDs {
		v := &testHEDs[i]
		if v.H == h {
			return v
		}
	}
	testHEDs = append(testHEDs, testHED{h, NewEncoder(nil, h), NewDecoder(nil, h)})
	return &testHEDs[len(testHEDs)-1]
}

func testReinit() {
	testOnce = sync.Once{}
	testHEDs = nil
}

func testInitAll() {
	// only parse it once.
	if !flag.Parsed() {
		flag.Parse()
	}
	for _, f := range testPreInitFns {
		f()
	}
	for _, f := range testPostInitFns {
		f()
	}
}

func sTestCodecEncode(ts interface{}, bsIn []byte, fn func([]byte) *bytes.Buffer,
	h Handle, bh *BasicHandle) (bs []byte, err error) {
	// bs = make([]byte, 0, approxSize)
	var e *Encoder
	var buf *bytes.Buffer
	if testUseReset {
		e = testHEDGet(h).E
	} else {
		e = NewEncoder(nil, h)
	}
	var oldWriteBufferSize int
	if testUseIoEncDec >= 0 {
		buf = fn(bsIn)
		// set the encode options for using a buffer
		oldWriteBufferSize = bh.WriterBufferSize
		bh.WriterBufferSize = testUseIoEncDec
		if testUseIoWrapper {
			e.Reset(ioWriterWrapper{buf})
		} else {
			e.Reset(buf)
		}
	} else {
		bs = bsIn
		e.ResetBytes(&bs)
	}
	if testUseMust {
		e.MustEncode(ts)
	} else {
		err = e.Encode(ts)
	}
	if testUseIoEncDec >= 0 {
		bs = buf.Bytes()
		bh.WriterBufferSize = oldWriteBufferSize
	}
	if !testUseReset {
		e.Release()
	}
	return
}

func sTestCodecDecoder(bs []byte, h Handle, bh *BasicHandle) (d *Decoder, oldReadBufferSize int) {
	// var buf *bytes.Reader
	if testUseReset {
		d = testHEDGet(h).D
	} else {
		d = NewDecoder(nil, h)
	}
	if testUseIoEncDec >= 0 {
		buf := bytes.NewReader(bs)
		oldReadBufferSize = bh.ReaderBufferSize
		bh.ReaderBufferSize = testUseIoEncDec
		if testUseIoWrapper {
			d.Reset(ioReaderWrapper{buf})
		} else {
			d.Reset(buf)
		}
	} else {
		d.ResetBytes(bs)
	}
	return
}

func sTestCodecDecode(bs []byte, ts interface{}, h Handle, bh *BasicHandle) (err error) {
	d, oldReadBufferSize := sTestCodecDecoder(bs, h, bh)
	if testUseMust {
		d.MustDecode(ts)
	} else {
		err = d.Decode(ts)
	}
	if testUseIoEncDec >= 0 {
		bh.ReaderBufferSize = oldReadBufferSize
	}
	if !testUseReset {
		d.Release()
	}
	return
}

// // --- functions below are used by both benchmarks and tests

// // log message only when testVerbose = true (ie go test ... -- -tv).
// //
// // These are for intormational messages that do not necessarily
// // help with diagnosing a failure, or which are too large.
// func logTv(x interface{}, format string, args ...interface{}) {
// 	if !testVerbose {
// 		return
// 	}
// 	if t, ok := x.(testing.TB); ok { // only available from go 1.9
// 		t.Helper()
// 	}
// 	logT(x, format, args...)
// }

// // logT logs messages when running as go test -v
// //
// // Use it for diagnostics messages that help diagnost failure,
// // and when the output is not too long ie shorter than like 100 characters.
// //
// // In general, any logT followed by failT should call this.
// func logT(x interface{}, format string, args ...interface{}) {
// 	if x == nil {
// 		if len(format) == 0 || format[len(format)-1] != '\n' {
// 			format = format + "\n"
// 		}
// 		fmt.Printf(format, args...)
// 		return
// 	}
// 	if t, ok := x.(testing.TB); ok { // only available from go 1.9
// 		t.Helper()
// 		t.Logf(format, args...)
// 	}
// }

// func failTv(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	if testVerbose {
// 		failTMsg(x, args...)
// 	}
// 	x.FailNow()
// }

// func failT(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	failTMsg(x, args...)
// 	x.FailNow()
// }

// func failTMsg(x testing.TB, args ...interface{}) {
// 	x.Helper()
// 	if len(args) > 0 {
// 		if format, ok := args[0].(string); ok {
// 			logT(x, format, args[1:]...)
// 		} else if len(args) == 1 {
// 			logT(x, "%v", args[0])
// 		} else {
// 			logT(x, "%v", args)
// 		}
// 	}
// }

// --- functions below are used only by benchmarks alone

func fnBenchmarkByteBuf(bsIn []byte) (buf *bytes.Buffer) {
	// var buf bytes.Buffer
	// buf.Grow(approxSize)
	buf = bytes.NewBuffer(bsIn)
	buf.Truncate(0)
	return
}

// func benchFnCodecEncode(ts interface{}, bsIn []byte, h Handle) (bs []byte, err error) {
// 	return testCodecEncode(ts, bsIn, fnBenchmarkByteBuf, h)
// }

// func benchFnCodecDecode(bs []byte, ts interface{}, h Handle) (err error) {
// 	return testCodecDecode(bs, ts, h)
// }
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"compress/gzip"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/go-check/check"
)

func (s *DockerSuite) TestImportDisplay(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
	cleanedContainerID := strings.TrimSpace(out)

	out, _, err := runCommandPipelineWithOutput(
		exec.Command(dockerBinary, "export", cleanedContainerID),
		exec.Command(dockerBinary, "import", "-"),
	)
	c.Assert(err, checker.IsNil)

	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))

	image := strings.TrimSpace(out)
	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportBadURL(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _, err := dockerCmdWithError("import", "http://nourl/bad")
	c.Assert(err, checker.NotNil, check.Commentf("import was supposed to fail but didn't"))
	// Depending on your system you can get either of these errors
	if !strings.Contains(out, "dial tcp") &&
		!strings.Contains(out, "Error processing tar file") {
		c.Fatalf("expected an error msg but didn't get one.\nErr: %v\nOut: %v", err, out)
	}
}

func (s *DockerSuite) TestImportFile(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	runCmd.Stdout = bufio.NewWriter(temporaryFile)

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))

	out, _ := dockerCmd(c, "import", temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportGzipped(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	w := gzip.NewWriter(temporaryFile)
	runCmd.Stdout = w

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))
	err = w.Close()
	c.Assert(err, checker.IsNil, check.Commentf("failed to close gzip writer"))
	temporaryFile.Close()
	out, _ := dockerCmd(c, "import", temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportFileWithMessage(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	runCmd.Stdout = bufio.NewWriter(temporaryFile)

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))

	message := "Testing commit message"
	out, _ := dockerCmd(c, "import", "-m", message, temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "history", image)
	split := strings.Split(out, "\n")

	c.Assert(split, checker.HasLen, 3, check.Commentf("expected 3 lines from image history"))
	r := regexp.MustCompile("[\\s]{2,}")
	split = r.Split(split[1], -1)

	c.Assert(message, checker.Equals, split[3], check.Commentf("didn't get expected value in commit message"))

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing"))
}

func (s *DockerSuite) TestImportFileNonExistentFile(c *check.C) {
	_, _, err := dockerCmdWithError("import", "example.com/myImage.tar")
	c.Assert(err, checker.NotNil, check.Commentf("import non-existing file must failed"))
}
<commit_msg>integration-cli: fix TestImportBadURL w/o network<commit_after>package main

import (
	"bufio"
	"compress/gzip"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/go-check/check"
)

func (s *DockerSuite) TestImportDisplay(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
	cleanedContainerID := strings.TrimSpace(out)

	out, _, err := runCommandPipelineWithOutput(
		exec.Command(dockerBinary, "export", cleanedContainerID),
		exec.Command(dockerBinary, "import", "-"),
	)
	c.Assert(err, checker.IsNil)

	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))

	image := strings.TrimSpace(out)
	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportBadURL(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _, err := dockerCmdWithError("import", "http://nourl/bad")
	c.Assert(err, checker.NotNil, check.Commentf("import was supposed to fail but didn't"))
	// Depending on your system you can get either of these errors
	if !strings.Contains(out, "dial tcp") &&
		!strings.Contains(out, "ApplyLayer exit status 1 stdout:  stderr: archive/tar: invalid tar header") &&
		!strings.Contains(out, "Error processing tar file") {
		c.Fatalf("expected an error msg but didn't get one.\nErr: %v\nOut: %v", err, out)
	}
}

func (s *DockerSuite) TestImportFile(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	runCmd.Stdout = bufio.NewWriter(temporaryFile)

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))

	out, _ := dockerCmd(c, "import", temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportGzipped(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	w := gzip.NewWriter(temporaryFile)
	runCmd.Stdout = w

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))
	err = w.Close()
	c.Assert(err, checker.IsNil, check.Commentf("failed to close gzip writer"))
	temporaryFile.Close()
	out, _ := dockerCmd(c, "import", temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing."))
}

func (s *DockerSuite) TestImportFileWithMessage(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "--name", "test-import", "busybox", "true")

	temporaryFile, err := ioutil.TempFile("", "exportImportTest")
	c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file"))
	defer os.Remove(temporaryFile.Name())

	runCmd := exec.Command(dockerBinary, "export", "test-import")
	runCmd.Stdout = bufio.NewWriter(temporaryFile)

	_, err = runCommand(runCmd)
	c.Assert(err, checker.IsNil, check.Commentf("failed to export a container"))

	message := "Testing commit message"
	out, _ := dockerCmd(c, "import", "-m", message, temporaryFile.Name())
	c.Assert(out, checker.Count, "\n", 1, check.Commentf("display is expected 1 '\\n' but didn't"))
	image := strings.TrimSpace(out)

	out, _ = dockerCmd(c, "history", image)
	split := strings.Split(out, "\n")

	c.Assert(split, checker.HasLen, 3, check.Commentf("expected 3 lines from image history"))
	r := regexp.MustCompile("[\\s]{2,}")
	split = r.Split(split[1], -1)

	c.Assert(message, checker.Equals, split[3], check.Commentf("didn't get expected value in commit message"))

	out, _ = dockerCmd(c, "run", "--rm", image, "true")
	c.Assert(out, checker.Equals, "", check.Commentf("command output should've been nothing"))
}

func (s *DockerSuite) TestImportFileNonExistentFile(c *check.C) {
	_, _, err := dockerCmdWithError("import", "example.com/myImage.tar")
	c.Assert(err, checker.NotNil, check.Commentf("import non-existing file must failed"))
}
<|endoftext|>


<commit_before>package agent

import (
	"bytes"
	"github.com/hashicorp/consul/consul/structs"
	"io"
	"net/http"
	"strconv"
	"strings"
)

func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	// Set default DC
	args := structs.KeyRequest{}
	if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
		return nil, nil
	}

	// Pull out the key name, validation left to each sub-handler
	args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")

	// Switch on the method
	switch req.Method {
	case "GET":
		return s.KVSGet(resp, req, &args)
	case "PUT":
		return s.KVSPut(resp, req, &args)
	case "DELETE":
		return s.KVSDelete(resp, req, &args)
	default:
		resp.WriteHeader(405)
		return nil, nil
	}
	return nil, nil
}

// KVSGet handles a GET request
func (s *HTTPServer) KVSGet(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for recurse
	method := "KVS.Get"
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		method = "KVS.List"
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out structs.IndexedDirEntries
	if err := s.agent.RPC(method, &args, &out); err != nil {
		return nil, err
	}
	setIndex(resp, out.Index)
	return out.Entries, nil
}

// KVSPut handles a PUT request
func (s *HTTPServer) KVSPut(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	if missingKey(resp, args) {
		return nil, nil
	}
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSSet,
		DirEnt: structs.DirEntry{
			Key:   args.Key,
			Flags: 0,
			Value: nil,
		},
	}

	// Check for flags
	params := req.URL.Query()
	if _, ok := params["flags"]; ok {
		flagVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.Flags = flagVal
	}

	// Check for cas value
	if _, ok := params["cas"]; ok {
		casVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.ModifyIndex = casVal
		applyReq.Op = structs.KVSCAS
	}

	// Copy the value
	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, req.Body); err != nil {
		return nil, err
	}
	applyReq.DirEnt.Value = buf.Bytes()

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}

	// Only use the out value if this was a CAS
	if applyReq.Op == structs.KVSSet {
		return true, nil
	} else {
		return out, nil
	}
}

// KVSPut handles a DELETE request
func (s *HTTPServer) KVSDelete(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSDelete,
		DirEnt: structs.DirEntry{
			Key: args.Key,
		},
	}

	// Check for recurse
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		applyReq.Op = structs.KVSDeleteTree
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}
	return nil, nil
}

// missingKey checks if the key is missing
func missingKey(resp http.ResponseWriter, args *structs.KeyRequest) bool {
	if args.Key == "" {
		resp.WriteHeader(400)
		resp.Write([]byte("Missing key name"))
		return true
	}
	return false
}
<commit_msg>consul: Return 404 if no entries found<commit_after>package agent

import (
	"bytes"
	"github.com/hashicorp/consul/consul/structs"
	"io"
	"net/http"
	"strconv"
	"strings"
)

func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	// Set default DC
	args := structs.KeyRequest{}
	if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
		return nil, nil
	}

	// Pull out the key name, validation left to each sub-handler
	args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")

	// Switch on the method
	switch req.Method {
	case "GET":
		return s.KVSGet(resp, req, &args)
	case "PUT":
		return s.KVSPut(resp, req, &args)
	case "DELETE":
		return s.KVSDelete(resp, req, &args)
	default:
		resp.WriteHeader(405)
		return nil, nil
	}
	return nil, nil
}

// KVSGet handles a GET request
func (s *HTTPServer) KVSGet(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for recurse
	method := "KVS.Get"
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		method = "KVS.List"
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out structs.IndexedDirEntries
	if err := s.agent.RPC(method, &args, &out); err != nil {
		return nil, err
	}
	setIndex(resp, out.Index)

	// Check if we get a not found
	if len(out.Entries) == 0 {
		resp.WriteHeader(404)
		return nil, nil
	}
	return out.Entries, nil
}

// KVSPut handles a PUT request
func (s *HTTPServer) KVSPut(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	if missingKey(resp, args) {
		return nil, nil
	}
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSSet,
		DirEnt: structs.DirEntry{
			Key:   args.Key,
			Flags: 0,
			Value: nil,
		},
	}

	// Check for flags
	params := req.URL.Query()
	if _, ok := params["flags"]; ok {
		flagVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.Flags = flagVal
	}

	// Check for cas value
	if _, ok := params["cas"]; ok {
		casVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.ModifyIndex = casVal
		applyReq.Op = structs.KVSCAS
	}

	// Copy the value
	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, req.Body); err != nil {
		return nil, err
	}
	applyReq.DirEnt.Value = buf.Bytes()

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}

	// Only use the out value if this was a CAS
	if applyReq.Op == structs.KVSSet {
		return true, nil
	} else {
		return out, nil
	}
}

// KVSPut handles a DELETE request
func (s *HTTPServer) KVSDelete(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSDelete,
		DirEnt: structs.DirEntry{
			Key: args.Key,
		},
	}

	// Check for recurse
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		applyReq.Op = structs.KVSDeleteTree
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}
	return nil, nil
}

// missingKey checks if the key is missing
func missingKey(resp http.ResponseWriter, args *structs.KeyRequest) bool {
	if args.Key == "" {
		resp.WriteHeader(400)
		resp.Write([]byte("Missing key name"))
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/digital-ocean-service/domain"
)

type DOInteractor interface {
	GetOauthURL(id, redirectURI, scope string) string
	GetToken(code, id, secret, redirectURL string) (*domain.DOToken, error)
	ShowKeys(token string) ([]domain.Key, error)
	CreateKey(name, publicKey, token string) (*domain.Key, error)
	CreateDroplet(droplet domain.DropletRequest, token string) (*domain.Droplet, error)
	ListDroplets(token string) ([]domain.Droplet, error)
}

type UserRepo interface {
}

type WebServiceHandler struct {
	Interactor  DOInteractor
	UserRepo    UserRepo
	ID          string
	Secret      string
	RedirectURI string
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url := handler.Interactor.GetOauthURL(handler.ID, handler.RedirectURI, "read write")

	htmlIndex := `
                Log in with <a href="` + url + `">Digital Ocean
                `

	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))

}

func (handler WebServiceHandler) DOCallback(res http.ResponseWriter, req *http.Request) {
	code := req.FormValue("code")

	token, err := handler.Interactor.GetToken(code, handler.ID, handler.Secret, handler.RedirectURI)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(token)
	if err != nil {
		fmt.Println(err.Error())

		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write(b)

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	token := req.Header.Get("token")
	keys, err := handler.Interactor.ShowKeys(token)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write(keysB)

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {

	defer req.Body.Close()

	token := req.Header.Get("token")

	key := &domain.Key{}

	decoder := json.NewDecoder(req.Body)

	err := decoder.Decode(key)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	key, err = handler.Interactor.CreateKey(key.Name, key.PublicKey, token)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(keyB)
}

func (handler WebServiceHandler) CreateDroplet(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	token := req.Header.Get("token")

	decoder := json.NewDecoder(req.Body)
	dropletRequest := domain.DropletRequest{}

	err := decoder.Decode(&dropletRequest)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	droplet, err := handler.Interactor.CreateDroplet(dropletRequest, token)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, _ := json.Marshal(droplet)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(b)
}

func (handler WebServiceHandler) ListDroplets(res http.ResponseWriter, req *http.Request) {
	token := req.Header.Get("token")

	droplets, err := handler.Interactor.ListDroplets(token)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	dB, _ := json.Marshal(droplets)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(dB)
}
<commit_msg>Inject scope used to form the auth URL<commit_after>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/digital-ocean-service/domain"
)

type DOInteractor interface {
	GetOauthURL(id, redirectURI string, scope []string) string
	GetToken(code, id, secret, redirectURL string) (*domain.DOToken, error)
	ShowKeys(token string) ([]domain.Key, error)
	CreateKey(name, publicKey, token string) (*domain.Key, error)
	CreateDroplet(droplet domain.DropletRequest, token string) (*domain.Droplet, error)
	ListDroplets(token string) ([]domain.Droplet, error)
}

type UserRepo interface {
}

type WebServiceHandler struct {
	Interactor  DOInteractor
	UserRepo    UserRepo
	ID          string
	Secret      string
	RedirectURI string
	Scopes      []string
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url := handler.Interactor.GetOauthURL(handler.ID, handler.RedirectURI, handler.Scopes)

	htmlIndex := `
                Log in with <a href="` + url + `">Digital Ocean
                `

	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))

}

func (handler WebServiceHandler) DOCallback(res http.ResponseWriter, req *http.Request) {
	code := req.FormValue("code")

	token, err := handler.Interactor.GetToken(code, handler.ID, handler.Secret, handler.RedirectURI)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(token)
	if err != nil {
		fmt.Println(err.Error())

		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write(b)

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	token := req.Header.Get("token")
	keys, err := handler.Interactor.ShowKeys(token)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write(keysB)

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {

	defer req.Body.Close()

	token := req.Header.Get("token")

	key := &domain.Key{}

	decoder := json.NewDecoder(req.Body)

	err := decoder.Decode(key)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	key, err = handler.Interactor.CreateKey(key.Name, key.PublicKey, token)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(keyB)
}

func (handler WebServiceHandler) CreateDroplet(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	token := req.Header.Get("token")

	decoder := json.NewDecoder(req.Body)
	dropletRequest := domain.DropletRequest{}

	err := decoder.Decode(&dropletRequest)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	droplet, err := handler.Interactor.CreateDroplet(dropletRequest, token)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, _ := json.Marshal(droplet)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(b)
}

func (handler WebServiceHandler) ListDroplets(res http.ResponseWriter, req *http.Request) {
	token := req.Header.Get("token")

	droplets, err := handler.Interactor.ListDroplets(token)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	dB, _ := json.Marshal(droplets)
	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(dB)
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package types

// Patch represent either a Strategic Merge Patch or a JSON patch
// and its targets.
// The content of the patch can either be from a file
// or from an inline string.
type Patch struct {
	// Path is a relative file path to the patch file.
	Path string `json:"path,omitempty" yaml:"path,omitempty"`

	// Patch is the content of a patch.
	Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`

	// Target points to the resources that the patch is applied to
	Target *Selector `json:"target,omitempty" yaml:"target,omitempty"`
}

// Equals return true if p equals another.
func (p *Patch) Equals(another Patch) bool {
	targetEqual := (p.Target == another.Target) ||
		(p.Target != nil && another.Target != nil && *p.Target == *another.Target)
	return p.Path == another.Path &&
		p.Patch == another.Patch &&
		targetEqual
}
<commit_msg>code review<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package types

// Patch represent either a Strategic Merge Patch or a JSON patch
// and its targets.
// The content of the patch can either be from a file
// or from an inline string.
type Patch struct {
	// Path is a relative file path to the patch file.
	Path string `json:"path,omitempty" yaml:"path,omitempty"`

	// Patch is the content of a patch.
	Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`

	// Target points to the resources that the patch is applied to
	Target *Selector `json:"target,omitempty" yaml:"target,omitempty"`
}

// Equals return true if p equals o.
func (p *Patch) Equals(o Patch) bool {
	targetEqual := (p.Target == o.Target) ||
		(p.Target != nil && o.Target != nil && *p.Target == *o.Target)
	return p.Path == o.Path &&
		p.Patch == o.Patch &&
		targetEqual
}
<|endoftext|>