<commit_before>package valente

import (
	"errors"
	"log"

	"golang.org/x/net/websocket"
)

const (
	endofmessage = "___ENDOFMESSAGE___"
)

var (
	ProtocolError = errors.New("Protocol Error")
)

//HandlerFunc is a function of handle an event received into websocket.Conn
type HandlerFunc func(*websocket.Conn, *App, []string)

//Form represents the unit of user interaction
type Form interface {
	AddEventHandler(evt string, f HandlerFunc) Form
	Run(ws *websocket.Conn, app *App) error
	Initialize(ws *websocket.Conn) Form
}

//FormImpl its a simple Form
type FormImpl struct {
	trans map[string]HandlerFunc
}

//AddEventHandler add an f function to handle evt event
func (form FormImpl) AddEventHandler(evt string, f HandlerFunc) Form {
	if form.trans == nil {
		form.trans = map[string]HandlerFunc{}
	}
	form.trans[evt] = f
	return form
}

//Run execs the form
func (form FormImpl) Run(ws *websocket.Conn, app *App) error {
	msgs := []string{}
	for {
		msg := ""
		err := websocket.Message.Receive(ws, &msg)
		if err != nil {
			log.Println("Error on WS Receive", err)
			return err
		}
		if msg == endofmessage {
			break
		} else {
			msgs = append(msgs, msg)
		}
	}
	println(msgs)
	if len(msgs) < 1 {
		return ProtocolError
	}

	f, present := form.trans[msgs[0]]
	if present {
		f(ws, app, msgs)
	} else {
		log.Println("Evt not found", msgs[0])
	}
	return nil
}

//Initialize inits the form
func (form FormImpl) Initialize(ws *websocket.Conn) Form {
	log.Println("FormImpl Initialize")
	return form
}

//App is a Web Application representation
type App struct {
	WS          *websocket.Conn
	Forms       map[string]Form
	Data        map[string]interface{}
	CurrentForm Form
}

//GoTo replace the current form into app
func (app *App) GoTo(formName string) error {
	log.Println("App goto", formName)
	form, present := app.Forms[formName]
	if present {
		app.CurrentForm = form.Initialize(app.WS)
	} else {
		log.Println("[ERROR] Form not registred", formName)
	}
	return nil
}

//Run handle events
func (app *App) Run() {
	app.Data = map[string]interface{}{}
	for {
		err := app.CurrentForm.Run(app.WS, app)
		if err != nil {
			return
		}
	}
}

//Initialize inits the App
func (app *App) Initialize() {
	log.Println("App Initialize")
}

//AddForm add a new form to App
func (app *App) AddForm(name string, f Form) {
	log.Println("AddForm", name, f)
	if app.Forms == nil {
		app.Forms = map[string]Form{}
	}

	app.Forms[name] = f
}
<commit_msg>better log mesg<commit_after>package valente

import (
	"errors"
	"log"

	"golang.org/x/net/websocket"
)

const (
	endofmessage = "___ENDOFMESSAGE___"
)

var (
	ProtocolError = errors.New("Protocol Error")
)

//HandlerFunc is a function of handle an event received into websocket.Conn
type HandlerFunc func(*websocket.Conn, *App, []string)

//Form represents the unit of user interaction
type Form interface {
	AddEventHandler(evt string, f HandlerFunc) Form
	Run(ws *websocket.Conn, app *App) error
	Initialize(ws *websocket.Conn) Form
}

//FormImpl its a simple Form
type FormImpl struct {
	trans map[string]HandlerFunc
}

//AddEventHandler add an f function to handle evt event
func (form FormImpl) AddEventHandler(evt string, f HandlerFunc) Form {
	if form.trans == nil {
		form.trans = map[string]HandlerFunc{}
	}
	form.trans[evt] = f
	return form
}

//Run execs the form
func (form FormImpl) Run(ws *websocket.Conn, app *App) error {
	msgs := []string{}
	for {
		msg := ""
		err := websocket.Message.Receive(ws, &msg)
		if err != nil {
			log.Println("Error on WS Receive", err)
			return err
		}
		if msg == endofmessage {
			break
		} else {
			msgs = append(msgs, msg)
		}
	}
	println("msgs = ", msgs)
	if len(msgs) < 1 {
		return ProtocolError
	}

	f, present := form.trans[msgs[0]]
	if present {
		f(ws, app, msgs)
	} else {
		log.Println("Evt not found", msgs[0])
	}
	return nil
}

//Initialize inits the form
func (form FormImpl) Initialize(ws *websocket.Conn) Form {
	log.Println("FormImpl Initialize")
	return form
}

//App is a Web Application representation
type App struct {
	WS          *websocket.Conn
	Forms       map[string]Form
	Data        map[string]interface{}
	CurrentForm Form
}

//GoTo replace the current form into app
func (app *App) GoTo(formName string) error {
	log.Println("App goto", formName)
	form, present := app.Forms[formName]
	if present {
		app.CurrentForm = form.Initialize(app.WS)
	} else {
		log.Println("[ERROR] Form not registred", formName)
	}
	return nil
}

//Run handle events
func (app *App) Run() {
	app.Data = map[string]interface{}{}
	for {
		err := app.CurrentForm.Run(app.WS, app)
		if err != nil {
			return
		}
	}
}

//Initialize inits the App
func (app *App) Initialize() {
	log.Println("App Initialize")
}

//AddForm add a new form to App
func (app *App) AddForm(name string, f Form) {
	log.Println("AddForm", name, f)
	if app.Forms == nil {
		app.Forms = map[string]Form{}
	}

	app.Forms[name] = f
}
<|endoftext|>


<commit_before>package ipv4

import (
	"network/ipv4/ipv4tps"
	"time"

	"github.com/hsheth2/logs"
	"sync"
)

type IP_Reader struct {
	incomingPackets chan []byte
	irm             *IP_Read_Manager
	protocol        uint8
	ip              *ipv4tps.IPaddress
	fragBuf         map[string](chan []byte)
	fragBufMutex *sync.RWMutex
}

func NewIP_Reader(irm *IP_Read_Manager, ip *ipv4tps.IPaddress, protocol uint8) (*IP_Reader, error) {
	c, err := irm.Bind(ip, protocol)
	if err != nil {
		return nil, err
	}

	return &IP_Reader{
		incomingPackets: c,
		protocol:        protocol,
		ip:              ip,
		fragBuf:         make(map[string](chan []byte)),
		fragBufMutex: &sync.RWMutex{},
	}, nil
}

func slicePacket(b []byte) (hrd, payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	//fmt.Println("HdrLen: ", hdrLen)
	return b[:hdrLen], b[hdrLen:]
}

func (ipr *IP_Reader) fragmentAssembler(in <-chan []byte, quit <-chan bool, didQuit chan<- bool, done chan bool) {
	payload := make([]byte, 0)
	extraFrags := make(map[uint64]([]byte))
	recvLast := false

	for {
		select {
		case <-quit:
			//Trace.Println("quitting upon quit signal")
			didQuit <- true
			return
		case frag := <-in:
			//Trace.Println("got a fragment packet. len:", len(frag))
			hdr, p := slicePacket(frag)
			//offset := 8 * (uint64(hdr[6]&0x1f)<<8 + uint64(hdr[7]))
			//fmt.Println("RECEIVED FRAG")
			//fmt.Println("Offset:", offset)
			//fmt.Println(len(payload))

			// add to map
			offset := 8 * (uint64(hdr[6]&0x1F)<<8 + uint64(hdr[7]))
			//Trace.Println("Offset:", offset)
			extraFrags[offset] = p

			// check more fragments flag
			if (hdr[6]>>5)&0x01 == 0 {
				recvLast = true
			}

			// add to payload
			//Trace.Println("Begin to add to the payload")
			for {
				if storedFrag, found := extraFrags[uint64(len(payload))]; found {
					//Trace.Println("New Payload Len: ", len(payload))
					delete(extraFrags, uint64(len(payload)))
					payload = append(payload, storedFrag...)
				} else {
					break
				}
			}
			//Trace.Println("Finished add to the payload")

			// deal with the payload
			if recvLast && len(extraFrags) == 0 {
				//Trace.Println("Done")
				// correct the header
				fullPacketHdr := hdr
				totalLen := uint16(fullPacketHdr[0]&0x0F)*4 + uint16(len(payload))
				fullPacketHdr[2] = byte(totalLen >> 8)
				fullPacketHdr[3] = byte(totalLen)
				fullPacketHdr[6] = 0
				fullPacketHdr[7] = 0

				// update the checksum
				check := calculateIPChecksum(fullPacketHdr[:20])
				fullPacketHdr[10] = byte(check >> 8)
				fullPacketHdr[11] = byte(check)

				// send the packet back into processing
				//go func() {
				select {
				case ipr.incomingPackets <- append(fullPacketHdr, payload...):
				default:
					logs.Warn.Println("Dropping defragmented packet, no space in buffer")
				}
				//fmt.Println("FINISHED")
				//}()
				//Trace.Println("Just wrote back in")
				done <- true
				return // from goroutine
			}
			//Trace.Println("Looping")
		}
	}

	// drop the packet upon timeout
	//Trace.Println(errors.New("Fragments took too long, packet dropped"))
	//return
}

func (ipr *IP_Reader) killFragmentAssembler(quit chan<- bool, didQuit <-chan bool, done <-chan bool, bufID string) {
	// sends quit to the assembler if it doesn't send done
	select {
	case <-time.After(FRAGMENT_TIMEOUT):
		//Trace.Println("Force quitting packet assembler")
		quit <- true
		<-didQuit // will block until it has been received
	case <-done:
		//Trace.Println("Recieved done msg.")
	}

	//Trace.Println("Frag Assemble Ended, finished")
	ipr.fragBufMutex.Lock()
	delete(ipr.fragBuf, bufID)
	ipr.fragBufMutex.Unlock()
}

func (ipr *IP_Reader) ReadFrom() (rip, lip *ipv4tps.IPaddress, b, payload []byte, e error) {
	//fmt.Println("STARTING READ")
	b = <-ipr.incomingPackets
	//	logs.Info.Println("Read IP packet")
	//fmt.Println("RAW READ COMPLETED")
	//fmt.Println("Read Length: ", len(b))
	//fmt.Print(".")
	//fmt.Println("Full Read Data: ", b)

	hdr, p := slicePacket(b)

	// extract source IP and protocol
	rip = &ipv4tps.IPaddress{IP: hdr[12:16]}
	lip = &ipv4tps.IPaddress{IP: hdr[16:20]}
	//	proto := uint8(hdr[9])
	//	if !((bytes.Equal(ipr.ip.IP, rip.IP) || bytes.Equal(ipr.ip.IP, ipv4tps.IP_ALL)) && ipr.protocol == proto) {
	//		//Info.Println("Not interested in packet: dropping.")
	//		// TODO should this already have been done in the read manager?
	//		return ipr.ReadFrom()
	//	}

	// verify checksum
	if !verifyIPChecksum(hdr) {
		//Info.Println("Header checksum incorrect, packet dropped")
		return ipr.ReadFrom() // return another packet instead
	}

	packetOffset := uint16(hdr[6]&0x1f)<<8 + uint16(hdr[7])
	//fmt.Println("PACK OFF", packetOffset, "HEADER FLAGS", (hdr[6] >> 5))
	if ((hdr[6]>>5)&0x01 == 0) && (packetOffset == 0) {
		// not a fragment
		return rip, lip, b, p, nil
	} else {
		// is a fragment
		bufID := string([]byte{hdr[12], hdr[13], hdr[14], hdr[15], // the source IP
			hdr[16], hdr[17], hdr[18], hdr[19], // the destination IP
			hdr[9],         // protocol
			hdr[4], hdr[5], // identification
		})
		//Trace.Printf("rcvd a fragment-bufId: %x, len: %d\n", bufID, len(b))

		ipr.fragBufMutex.RLock()
		if _, ok := ipr.fragBuf[bufID]; !ok {
			ipr.fragBufMutex.RUnlock()
			ipr.fragBufMutex.Lock()
			// create the fragment buffer and quit
			//Trace.Printf("creating a new buffer for %x\n", bufID)
			ipr.fragBuf[bufID] = make(chan []byte, FRAGMENT_ASSEMBLER_BUFFER_SIZE)
			ipr.fragBufMutex.Unlock()

			quit := make(chan bool, 1)
			done := make(chan bool, 1)
			didQuit := make(chan bool, 1)

			// create the packet assembler in a goroutine to allow the program to continue
			go ipr.fragmentAssembler(ipr.fragBuf[bufID], quit, didQuit, done)
			go ipr.killFragmentAssembler(quit, didQuit, done, bufID)
		}

		// send the packet to the assembler
		select {
		case ipr.fragBuf[bufID] <- b:
		default:
			logs.Warn.Println("Dropping fragmented packet, no space in fragment buffer")
		}

		// after dealing with the fragment, try reading again
		return ipr.ReadFrom()
	}
}

func (ipr *IP_Reader) Close() error {
	return ipr.irm.Unbind(ipr.ip, ipr.protocol)
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<commit_msg>Another fix  for fragBuf race<commit_after>package ipv4

import (
	"network/ipv4/ipv4tps"
	"time"

	"github.com/hsheth2/logs"
	"sync"
)

type IP_Reader struct {
	incomingPackets chan []byte
	irm             *IP_Read_Manager
	protocol        uint8
	ip              *ipv4tps.IPaddress
	fragBuf         map[string](chan []byte)
	fragBufMutex    *sync.RWMutex
}

func NewIP_Reader(irm *IP_Read_Manager, ip *ipv4tps.IPaddress, protocol uint8) (*IP_Reader, error) {
	c, err := irm.Bind(ip, protocol)
	if err != nil {
		return nil, err
	}

	return &IP_Reader{
		incomingPackets: c,
		protocol:        protocol,
		ip:              ip,
		fragBuf:         make(map[string](chan []byte)),
		fragBufMutex:    &sync.RWMutex{},
	}, nil
}

func slicePacket(b []byte) (hrd, payload []byte) {
	hdrLen := int(b[0]&0x0f) * 4
	//fmt.Println("HdrLen: ", hdrLen)
	return b[:hdrLen], b[hdrLen:]
}

func (ipr *IP_Reader) fragmentAssembler(in <-chan []byte, quit <-chan bool, didQuit chan<- bool, done chan bool) {
	payload := make([]byte, 0)
	extraFrags := make(map[uint64]([]byte))
	recvLast := false

	for {
		select {
		case <-quit:
			//Trace.Println("quitting upon quit signal")
			didQuit <- true
			return
		case frag := <-in:
			//Trace.Println("got a fragment packet. len:", len(frag))
			hdr, p := slicePacket(frag)
			//offset := 8 * (uint64(hdr[6]&0x1f)<<8 + uint64(hdr[7]))
			//fmt.Println("RECEIVED FRAG")
			//fmt.Println("Offset:", offset)
			//fmt.Println(len(payload))

			// add to map
			offset := 8 * (uint64(hdr[6]&0x1F)<<8 + uint64(hdr[7]))
			//Trace.Println("Offset:", offset)
			extraFrags[offset] = p

			// check more fragments flag
			if (hdr[6]>>5)&0x01 == 0 {
				recvLast = true
			}

			// add to payload
			//Trace.Println("Begin to add to the payload")
			for {
				if storedFrag, found := extraFrags[uint64(len(payload))]; found {
					//Trace.Println("New Payload Len: ", len(payload))
					delete(extraFrags, uint64(len(payload)))
					payload = append(payload, storedFrag...)
				} else {
					break
				}
			}
			//Trace.Println("Finished add to the payload")

			// deal with the payload
			if recvLast && len(extraFrags) == 0 {
				//Trace.Println("Done")
				// correct the header
				fullPacketHdr := hdr
				totalLen := uint16(fullPacketHdr[0]&0x0F)*4 + uint16(len(payload))
				fullPacketHdr[2] = byte(totalLen >> 8)
				fullPacketHdr[3] = byte(totalLen)
				fullPacketHdr[6] = 0
				fullPacketHdr[7] = 0

				// update the checksum
				check := calculateIPChecksum(fullPacketHdr[:20])
				fullPacketHdr[10] = byte(check >> 8)
				fullPacketHdr[11] = byte(check)

				// send the packet back into processing
				//go func() {
				select {
				case ipr.incomingPackets <- append(fullPacketHdr, payload...):
				default:
					logs.Warn.Println("Dropping defragmented packet, no space in buffer")
				}
				//fmt.Println("FINISHED")
				//}()
				//Trace.Println("Just wrote back in")
				done <- true
				return // from goroutine
			}
			//Trace.Println("Looping")
		}
	}

	// drop the packet upon timeout
	//Trace.Println(errors.New("Fragments took too long, packet dropped"))
	//return
}

func (ipr *IP_Reader) killFragmentAssembler(quit chan<- bool, didQuit <-chan bool, done <-chan bool, bufID string) {
	// sends quit to the assembler if it doesn't send done
	select {
	case <-time.After(FRAGMENT_TIMEOUT):
		//Trace.Println("Force quitting packet assembler")
		quit <- true
		<-didQuit // will block until it has been received
	case <-done:
		//Trace.Println("Recieved done msg.")
	}

	//Trace.Println("Frag Assemble Ended, finished")
	ipr.fragBufMutex.Lock()
	delete(ipr.fragBuf, bufID)
	ipr.fragBufMutex.Unlock()
}

func (ipr *IP_Reader) ReadFrom() (rip, lip *ipv4tps.IPaddress, b, payload []byte, e error) {
	//fmt.Println("STARTING READ")
	b = <-ipr.incomingPackets
	//	logs.Info.Println("Read IP packet")
	//fmt.Println("RAW READ COMPLETED")
	//fmt.Println("Read Length: ", len(b))
	//fmt.Print(".")
	//fmt.Println("Full Read Data: ", b)

	hdr, p := slicePacket(b)

	// extract source IP and protocol
	rip = &ipv4tps.IPaddress{IP: hdr[12:16]}
	lip = &ipv4tps.IPaddress{IP: hdr[16:20]}
	//	proto := uint8(hdr[9])
	//	if !((bytes.Equal(ipr.ip.IP, rip.IP) || bytes.Equal(ipr.ip.IP, ipv4tps.IP_ALL)) && ipr.protocol == proto) {
	//		//Info.Println("Not interested in packet: dropping.")
	//		// TODO should this already have been done in the read manager?
	//		return ipr.ReadFrom()
	//	}

	// verify checksum
	if !verifyIPChecksum(hdr) {
		//Info.Println("Header checksum incorrect, packet dropped")
		return ipr.ReadFrom() // return another packet instead
	}

	packetOffset := uint16(hdr[6]&0x1f)<<8 + uint16(hdr[7])
	//fmt.Println("PACK OFF", packetOffset, "HEADER FLAGS", (hdr[6] >> 5))
	if ((hdr[6]>>5)&0x01 == 0) && (packetOffset == 0) {
		// not a fragment
		return rip, lip, b, p, nil
	} else {
		// is a fragment
		bufID := string([]byte{hdr[12], hdr[13], hdr[14], hdr[15], // the source IP
			hdr[16], hdr[17], hdr[18], hdr[19], // the destination IP
			hdr[9],         // protocol
			hdr[4], hdr[5], // identification
		})
		//Trace.Printf("rcvd a fragment-bufId: %x, len: %d\n", bufID, len(b))

		ipr.fragBufMutex.RLock()
		if _, ok := ipr.fragBuf[bufID]; !ok {
			ipr.fragBufMutex.RUnlock()
			ipr.fragBufMutex.Lock()
			// create the fragment buffer and quit
			//Trace.Printf("creating a new buffer for %x\n", bufID)
			ipr.fragBuf[bufID] = make(chan []byte, FRAGMENT_ASSEMBLER_BUFFER_SIZE)
			ipr.fragBufMutex.Unlock()

			quit := make(chan bool, 1)
			done := make(chan bool, 1)
			didQuit := make(chan bool, 1)

			// create the packet assembler in a goroutine to allow the program to continue
			go ipr.fragmentAssembler(ipr.fragBuf[bufID], quit, didQuit, done)
			go ipr.killFragmentAssembler(quit, didQuit, done, bufID)
		}

		// send the packet to the assembler
		ipr.fragBufMutex.RLock()
		select {
		case ipr.fragBuf[bufID] <- b:
		default:
			logs.Warn.Println("Dropping fragmented packet, no space in fragment buffer")
		}
		ipr.fragBufMutex.RUnlock()

		// after dealing with the fragment, try reading again
		return ipr.ReadFrom()
	}
}

func (ipr *IP_Reader) Close() error {
	return ipr.irm.Unbind(ipr.ip, ipr.protocol)
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<|endoftext|>


<commit_before>package vcs

import(
  "../helpers"
  "errors"
)

type Git struct {
  commit, tag string
}

func (g *Git) SetCommit(commit string) {
    g.commit = commit
}

func (g Git) Update() bool {
  if g.commit == "" {
    errors.New("git: you haven't mentioned the commit message")
    return false
  }

  helpers.Run("git", "add", "-A")

  if g.tag != "" {
    helpers.Run("git", "tag", g.tag)
  }

  helpers.Run("git", "commit", "-m", "\"" + g.commit + "\"")
  helpers.Run("git", "push")

  if g.tag != "" {
    helpers.Run("git", "push", "--tags")
  }

  return true
}
<commit_msg>"teste"<commit_after>package vcs

import(
  "../helpers"
  "errors"
)

type Git struct {
  commit, tag string
}

func (g *Git) SetCommit(commit string) {
    g.commit = commit
}

func (g Git) Update() bool {
  if g.commit == "" {
    errors.New("git: you haven't mentioned the commit message")
    return false
  }

  helpers.Run("git", "add", "-A")

  if g.tag != "" {
    helpers.Run("git", "tag", g.tag)
  }

  helpers.Run("git", "commit", "-m", "\"" + g.commit + "\"")
  helpers.Run("git", "push", "origin", "master")

  if g.tag != "" {
    helpers.Run("git", "push", "--tags")
  }

  return true
}
<|endoftext|>


<commit_before>package main

const Version = "1.4"
<commit_msg>Bump version to 1.5<commit_after>package main

const Version = "1.5"
<|endoftext|>


<commit_before>// Copyright 2016-2020 The Libsacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package libsacloud

// Version バージョン
const Version = "2.1.6"
<commit_msg>Bump to v2.1.7<commit_after>// Copyright 2016-2020 The Libsacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package libsacloud

// Version バージョン
const Version = "2.1.7"
<|endoftext|>


<commit_before>package periodic

// Version of periodic
var Version = "0.1.6"
<commit_msg>set version 0.1.7<commit_after>package periodic

// Version of periodic
var Version = "0.1.7"
<|endoftext|>


<commit_before>package gf

const VERSION  = "v1.5.16"
const AUTHORS  = "john<john@goframe.org>"

<commit_msg>version updates<commit_after>package gf

const VERSION  = "v1.5.17"
const AUTHORS  = "john<john@goframe.org>"

<|endoftext|>


<commit_before>// Copyright (c) 2015-2017 Magnus Bäck <magnus@noun.se>

package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/alecthomas/kingpin"
	"github.com/blang/semver"
	"github.com/magnusbaeck/logstash-filter-verifier/logging"
	"github.com/magnusbaeck/logstash-filter-verifier/logstash"
	"github.com/magnusbaeck/logstash-filter-verifier/testcase"
	"github.com/mattn/go-shellwords"
	oplogging "github.com/op/go-logging"
)

var (
	log = logging.MustGetLogger()

	loglevels = []string{"CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"}

	autoVersion = "auto"

	defaultKeptEnvVars = []string{
		"PATH",
	}
	defaultLogstashPaths = []string{
		"/opt/logstash/bin/logstash",
		"/usr/share/logstash/bin/logstash",
	}

	// Flags
	diffCommand = kingpin.
			Flag("diff-command", "Set the command to run to compare two events. The command will receive the two files to compare as arguments.").
			Default("diff -u").
			String()
	keptEnvVars = kingpin.
			Flag("keep-env", fmt.Sprintf("Add this environment variable to the list of variables that will be preserved from the calling process's environment. Initial list of variables: %s", strings.Join(defaultKeptEnvVars, ", "))).
			PlaceHolder("VARNAME").
			Strings()
	loglevel = kingpin.
			Flag("loglevel", fmt.Sprintf("Set the desired level of logging (one of: %s).", strings.Join(loglevels, ", "))).
			Default("WARNING").
			Enum(loglevels...)
	logstashArgs = kingpin.
			Flag("logstash-arg", "Command line arguments, which are passed to Logstash. Flag and value have to be provided as a flag each, e.g.: --logstash-arg=-n --logstash-arg=InstanceName").
			PlaceHolder("ARG").
			Strings()
	logstashOutput = kingpin.
			Flag("logstash-output", "Print the debug output of logstash.").
			Default("false").
			Bool()
	logstashPaths = kingpin.
			Flag("logstash-path", "Add a path to the list of Logstash executable paths that will be tried in order (first match is used).").
			PlaceHolder("PATH").
			Strings()
	logstashVersion = kingpin.
			Flag("logstash-version", "The version of Logstash that's being targeted.").
			PlaceHolder("VERSION").
			Default(autoVersion).
			String()
	unixSockets = kingpin.
			Flag("sockets", "Use Unix domain sockets for the communication with Logstash.").
			Default("false").
			Bool()
	unixSocketCommTimeout = kingpin.
				Flag("sockets-timeout", "Timeout (duration) for the communication with Logstash via Unix domain sockets. Has no effect unless --sockets is used.").
				Default("60s").
				Duration()

	// Arguments
	testcasePath = kingpin.
			Arg("testcases", "Test case file or a directory containing one or more test case files.").
			Required().
			ExistingFileOrDir()
	configPaths = kingpin.
			Arg("config", "Logstash configuration file or a directory containing one or more configuration files.").
			Required().
			ExistingFilesOrDirs()
)

// findExecutable examines the passed file paths and returns the first
// one that is an existing executable file.
func findExecutable(paths []string) (string, error) {
	for _, p := range paths {
		stat, err := os.Stat(p)
		if err != nil {
			log.Debug("Logstash path candidate rejected: %s", err)
			continue
		}
		if !stat.Mode().IsRegular() || stat.Mode().Perm()&0111 != 0111 {
			log.Debug("Logstash path candidate not an executable regular file: %s", p)
			continue
		}
		log.Debug("Logstash path candidate accepted: %s", p)
		return p, nil
	}
	return "", fmt.Errorf("no existing executable found among candidates: %s", strings.Join(paths, ", "))
}

// runTests runs Logstash with a set of configuration files against a
// slice of test cases and compares the actual events against the
// expected set. Returns an error if at least one test case fails or
// if there's a problem running the tests.
func runTests(inv *logstash.Invocation, tests []testcase.TestCaseSet, diffCommand []string, keptEnvVars []string) error {
	ok := true
	for _, t := range tests {
		fmt.Printf("Running tests in %s...\n", filepath.Base(t.File))
		p, err := logstash.NewProcess(inv, t.Codec, t.InputFields, keptEnvVars)
		if err != nil {
			return err
		}
		defer p.Release()
		if err = p.Start(); err != nil {
			return err
		}

		for _, line := range t.InputLines {
			_, err = p.Input.Write([]byte(line + "\n"))
			if err != nil {
				return err
			}
		}
		if err = p.Input.Close(); err != nil {
			return err
		}

		result, err := p.Wait()
		if err != nil || *logstashOutput {
			var message string
			if err != nil {
				message += fmt.Sprintf("Error running Logstash: %s.", err)
			}
			if result.Output != "" {
				message += fmt.Sprintf("\nProcess output:\n%s", result.Output)
			} else {
				message += "\nThe process wrote nothing to stdout or stderr."
			}
			if result.Log != "" {
				message += fmt.Sprintf("\nLog:\n%s", result.Log)
			} else {
				message += "\nThe process wrote nothing to its logfile."
			}
			if err != nil {
				return errors.New(message)
			}
			userError("%s", message)
		}
		if err = t.Compare(result.Events, false, diffCommand); err != nil {
			userError("Testcase failed, continuing with the rest: %s", err)
			ok = false
		}
	}
	if !ok {
		return errors.New("one or more testcases failed")
	}
	return nil
}

// runParallelTests runs multiple set of configuration in a single
// instance of Logstash against a slice of test cases and compares
// the actual events against the expected set. Returns an error if
// at least one test case fails or if there's a problem running the tests.
func runParallelTests(inv *logstash.Invocation, tests []testcase.TestCaseSet, diffCommand []string, keptEnvVars []string) error {
	var testStreams []*logstash.TestStream

	badCodecs := map[string]string{
		"json":  "json_lines",
		"plain": "line",
	}
	for _, t := range tests {
		if repl, ok := badCodecs[t.Codec]; ok {
			log.Warning(
				"The testcase file %q uses the %q codec. That codec "+
					"will most likely not work as expected when --sockets is used. Try %q instead.",
				t.File, t.Codec, repl)
		}
	}

	for _, t := range tests {
		ts, err := logstash.NewTestStream(t.Codec, t.InputFields, *unixSocketCommTimeout)
		if err != nil {
			logstash.CleanupTestStreams(testStreams)
			return err
		}
		testStreams = append(testStreams, ts)
	}

	p, err := logstash.NewParallelProcess(inv, testStreams, keptEnvVars)
	if err != nil {
		return err
	}
	defer p.Release()
	if err = p.Start(); err != nil {
		return err
	}

	for i, t := range tests {
		for _, line := range t.InputLines {
			_, err = testStreams[i].Write([]byte(line + "\n"))
			if err != nil {
				return err
			}
		}

		if err = testStreams[i].Close(); err != nil {
			return err
		}
	}

	result, err := p.Wait()
	if err != nil || *logstashOutput {
		var message string
		if err != nil {
			message += fmt.Sprintf("Error running Logstash: %s.", err)
		}
		if result.Output != "" {
			message += fmt.Sprintf("\nProcess output:\n%s", result.Output)
		} else {
			message += "\nThe process wrote nothing to stdout or stderr."
		}
		if result.Log != "" {
			message += fmt.Sprintf("\nLog:\n%s", result.Log)
		} else {
			message += "\nThe process wrote nothing to its logfile."
		}
		if err != nil {
			return errors.New(message)
		}
		userError("%s", message)
	}
	ok := true
	for i, t := range tests {
		if err = t.Compare(result.Events[i], false, diffCommand); err != nil {
			userError("Testcase failed, continuing with the rest: %s", err)
			ok = false
		}
	}

	if !ok {
		return errors.New("one or more testcases failed")
	}
	return nil
}

// prefixedUserError prints an error message to stderr and prefixes it
// with the name of the program file (e.g. "logstash-filter-verifier:
// something bad happened.").
func prefixedUserError(format string, a ...interface{}) {
	basename := filepath.Base(os.Args[0])
	message := fmt.Sprintf(format, a...)
	if strings.HasSuffix(message, "\n") {
		fmt.Fprintf(os.Stderr, "%s: %s", basename, message)
	} else {
		fmt.Fprintf(os.Stderr, "%s: %s\n", basename, message)
	}
}

// userError prints an error message to stderr.
func userError(format string, a ...interface{}) {
	if strings.HasSuffix(format, "\n") {
		fmt.Fprintf(os.Stderr, format, a...)
	} else {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

// mainEntrypoint functions as the main function of the program and
// returns the desired exit code.
func mainEntrypoint() int {
	kingpin.Version(fmt.Sprintf("%s %s", kingpin.CommandLine.Name, version))
	kingpin.Parse()

	level, err := oplogging.LogLevel(*loglevel)
	if err != nil {
		prefixedUserError("Bad loglevel: %s", loglevel)
		return 1
	}
	logging.SetLevel(level)

	diffCmd, err := shellwords.NewParser().Parse(*diffCommand)
	if err != nil {
		userError("Error parsing diff command %q: %s", *diffCommand, err)
		return 1
	}

	tests, err := testcase.DiscoverTests(*testcasePath)
	if err != nil {
		userError(err.Error())
		return 1
	}

	allKeptEnvVars := append(defaultKeptEnvVars, *keptEnvVars...)

	logstashPath, err := findExecutable(append(*logstashPaths, defaultLogstashPaths...))
	if err != nil {
		userError("Error locating Logstash: %s", err)
		return 1
	}

	var targetVersion *semver.Version
	if *logstashVersion == autoVersion {
		targetVersion, err = logstash.DetectVersion(logstashPath, allKeptEnvVars)
		if err != nil {
			userError("Could not auto-detect the Logstash version: %s", err)
			return 1
		}
	} else {
		targetVersion, err = semver.New(*logstashVersion)
		if err != nil {
			userError("The given Logstash version %q could not be parsed as a version number (%s).", *logstashVersion, err)
			return 1
		}
	}

	inv, err := logstash.NewInvocation(logstashPath, *logstashArgs, targetVersion, *configPaths...)
	if err != nil {
		userError("An error occurred while setting up the Logstash environment: %s", err)
		return 1
	}
	defer inv.Release()
	if *unixSockets {
		if runtime.GOOS == "windows" {
			userError("Use of Unix domain sockets for communication with Logstash is not supported on Windows.")
			return 1
		}
		fmt.Println("Use Unix domain sockets.")
		if err = runParallelTests(inv, tests, diffCmd, allKeptEnvVars); err != nil {
			userError(err.Error())
			return 1
		}
	} else {
		if err = runTests(inv, tests, diffCmd, allKeptEnvVars); err != nil {
			userError(err.Error())
			return 1
		}
	}
	return 0
}

func main() {
	os.Exit(mainEntrypoint())
}
<commit_msg>Reduce code duplication in logstash-filter-verifier.go<commit_after>// Copyright (c) 2015-2017 Magnus Bäck <magnus@noun.se>

package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/alecthomas/kingpin"
	"github.com/blang/semver"
	"github.com/magnusbaeck/logstash-filter-verifier/logging"
	"github.com/magnusbaeck/logstash-filter-verifier/logstash"
	"github.com/magnusbaeck/logstash-filter-verifier/testcase"
	"github.com/mattn/go-shellwords"
	oplogging "github.com/op/go-logging"
)

var (
	log = logging.MustGetLogger()

	loglevels = []string{"CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"}

	autoVersion = "auto"

	defaultKeptEnvVars = []string{
		"PATH",
	}
	defaultLogstashPaths = []string{
		"/opt/logstash/bin/logstash",
		"/usr/share/logstash/bin/logstash",
	}

	// Flags
	diffCommand = kingpin.
			Flag("diff-command", "Set the command to run to compare two events. The command will receive the two files to compare as arguments.").
			Default("diff -u").
			String()
	keptEnvVars = kingpin.
			Flag("keep-env", fmt.Sprintf("Add this environment variable to the list of variables that will be preserved from the calling process's environment. Initial list of variables: %s", strings.Join(defaultKeptEnvVars, ", "))).
			PlaceHolder("VARNAME").
			Strings()
	loglevel = kingpin.
			Flag("loglevel", fmt.Sprintf("Set the desired level of logging (one of: %s).", strings.Join(loglevels, ", "))).
			Default("WARNING").
			Enum(loglevels...)
	logstashArgs = kingpin.
			Flag("logstash-arg", "Command line arguments, which are passed to Logstash. Flag and value have to be provided as a flag each, e.g.: --logstash-arg=-n --logstash-arg=InstanceName").
			PlaceHolder("ARG").
			Strings()
	logstashOutput = kingpin.
			Flag("logstash-output", "Print the debug output of logstash.").
			Default("false").
			Bool()
	logstashPaths = kingpin.
			Flag("logstash-path", "Add a path to the list of Logstash executable paths that will be tried in order (first match is used).").
			PlaceHolder("PATH").
			Strings()
	logstashVersion = kingpin.
			Flag("logstash-version", "The version of Logstash that's being targeted.").
			PlaceHolder("VERSION").
			Default(autoVersion).
			String()
	unixSockets = kingpin.
			Flag("sockets", "Use Unix domain sockets for the communication with Logstash.").
			Default("false").
			Bool()
	unixSocketCommTimeout = kingpin.
				Flag("sockets-timeout", "Timeout (duration) for the communication with Logstash via Unix domain sockets. Has no effect unless --sockets is used.").
				Default("60s").
				Duration()

	// Arguments
	testcasePath = kingpin.
			Arg("testcases", "Test case file or a directory containing one or more test case files.").
			Required().
			ExistingFileOrDir()
	configPaths = kingpin.
			Arg("config", "Logstash configuration file or a directory containing one or more configuration files.").
			Required().
			ExistingFilesOrDirs()
)

// findExecutable examines the passed file paths and returns the first
// one that is an existing executable file.
func findExecutable(paths []string) (string, error) {
	for _, p := range paths {
		stat, err := os.Stat(p)
		if err != nil {
			log.Debug("Logstash path candidate rejected: %s", err)
			continue
		}
		if !stat.Mode().IsRegular() || stat.Mode().Perm()&0111 != 0111 {
			log.Debug("Logstash path candidate not an executable regular file: %s", p)
			continue
		}
		log.Debug("Logstash path candidate accepted: %s", p)
		return p, nil
	}
	return "", fmt.Errorf("no existing executable found among candidates: %s", strings.Join(paths, ", "))
}

// runTests runs Logstash with a set of configuration files against a
// slice of test cases and compares the actual events against the
// expected set. Returns an error if at least one test case fails or
// if there's a problem running the tests.
func runTests(inv *logstash.Invocation, tests []testcase.TestCaseSet, diffCommand []string, keptEnvVars []string) error {
	ok := true
	for _, t := range tests {
		fmt.Printf("Running tests in %s...\n", filepath.Base(t.File))
		p, err := logstash.NewProcess(inv, t.Codec, t.InputFields, keptEnvVars)
		if err != nil {
			return err
		}
		defer p.Release()
		if err = p.Start(); err != nil {
			return err
		}

		for _, line := range t.InputLines {
			_, err = p.Input.Write([]byte(line + "\n"))
			if err != nil {
				return err
			}
		}
		if err = p.Input.Close(); err != nil {
			return err
		}

		result, err := p.Wait()
		if err != nil || *logstashOutput {
			message := getLogstashOutputMessage(result.Output, result.Log)
			if err != nil {
				return fmt.Errorf("Error running Logstash: %s.%s", err, message)
			}
			userError("%s", message)
		}
		if err = t.Compare(result.Events, false, diffCommand); err != nil {
			userError("Testcase failed, continuing with the rest: %s", err)
			ok = false
		}
	}
	if !ok {
		return errors.New("one or more testcases failed")
	}
	return nil
}

// runParallelTests runs multiple set of configuration in a single
// instance of Logstash against a slice of test cases and compares
// the actual events against the expected set. Returns an error if
// at least one test case fails or if there's a problem running the tests.
func runParallelTests(inv *logstash.Invocation, tests []testcase.TestCaseSet, diffCommand []string, keptEnvVars []string) error {
	var testStreams []*logstash.TestStream

	badCodecs := map[string]string{
		"json":  "json_lines",
		"plain": "line",
	}
	for _, t := range tests {
		if repl, ok := badCodecs[t.Codec]; ok {
			log.Warning(
				"The testcase file %q uses the %q codec. That codec "+
					"will most likely not work as expected when --sockets is used. Try %q instead.",
				t.File, t.Codec, repl)
		}
	}

	for _, t := range tests {
		ts, err := logstash.NewTestStream(t.Codec, t.InputFields, *unixSocketCommTimeout)
		if err != nil {
			logstash.CleanupTestStreams(testStreams)
			return err
		}
		testStreams = append(testStreams, ts)
	}

	p, err := logstash.NewParallelProcess(inv, testStreams, keptEnvVars)
	if err != nil {
		return err
	}
	defer p.Release()
	if err = p.Start(); err != nil {
		return err
	}

	for i, t := range tests {
		for _, line := range t.InputLines {
			_, err = testStreams[i].Write([]byte(line + "\n"))
			if err != nil {
				return err
			}
		}

		if err = testStreams[i].Close(); err != nil {
			return err
		}
	}

	result, err := p.Wait()
	if err != nil || *logstashOutput {
		message := getLogstashOutputMessage(result.Output, result.Log)
		if err != nil {
			return fmt.Errorf("Error running Logstash: %s.%s", err, message)
		}
		userError("%s", message)
	}
	ok := true
	for i, t := range tests {
		if err = t.Compare(result.Events[i], false, diffCommand); err != nil {
			userError("Testcase failed, continuing with the rest: %s", err)
			ok = false
		}
	}

	if !ok {
		return errors.New("one or more testcases failed")
	}
	return nil
}

// getLogstashOutputMessage examines the test result and prepares a
// message describing the process's output, log output, or neither
// (resulting in an empty string).
func getLogstashOutputMessage(output string, log string) string {
	var message string
	if output != "" {
		message += fmt.Sprintf("\nProcess output:\n%s", output)
	} else {
		message += "\nThe process wrote nothing to stdout or stderr."
	}
	if log != "" {
		message += fmt.Sprintf("\nLog:\n%s", log)
	} else {
		message += "\nThe process wrote nothing to its logfile."
	}
	return message
}

// prefixedUserError prints an error message to stderr and prefixes it
// with the name of the program file (e.g. "logstash-filter-verifier:
// something bad happened.").
func prefixedUserError(format string, a ...interface{}) {
	basename := filepath.Base(os.Args[0])
	message := fmt.Sprintf(format, a...)
	if strings.HasSuffix(message, "\n") {
		fmt.Fprintf(os.Stderr, "%s: %s", basename, message)
	} else {
		fmt.Fprintf(os.Stderr, "%s: %s\n", basename, message)
	}
}

// userError prints an error message to stderr.
func userError(format string, a ...interface{}) {
	if strings.HasSuffix(format, "\n") {
		fmt.Fprintf(os.Stderr, format, a...)
	} else {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

// mainEntrypoint functions as the main function of the program and
// returns the desired exit code.
func mainEntrypoint() int {
	kingpin.Version(fmt.Sprintf("%s %s", kingpin.CommandLine.Name, version))
	kingpin.Parse()

	level, err := oplogging.LogLevel(*loglevel)
	if err != nil {
		prefixedUserError("Bad loglevel: %s", loglevel)
		return 1
	}
	logging.SetLevel(level)

	diffCmd, err := shellwords.NewParser().Parse(*diffCommand)
	if err != nil {
		userError("Error parsing diff command %q: %s", *diffCommand, err)
		return 1
	}

	tests, err := testcase.DiscoverTests(*testcasePath)
	if err != nil {
		userError(err.Error())
		return 1
	}

	allKeptEnvVars := append(defaultKeptEnvVars, *keptEnvVars...)

	logstashPath, err := findExecutable(append(*logstashPaths, defaultLogstashPaths...))
	if err != nil {
		userError("Error locating Logstash: %s", err)
		return 1
	}

	var targetVersion *semver.Version
	if *logstashVersion == autoVersion {
		targetVersion, err = logstash.DetectVersion(logstashPath, allKeptEnvVars)
		if err != nil {
			userError("Could not auto-detect the Logstash version: %s", err)
			return 1
		}
	} else {
		targetVersion, err = semver.New(*logstashVersion)
		if err != nil {
			userError("The given Logstash version %q could not be parsed as a version number (%s).", *logstashVersion, err)
			return 1
		}
	}

	inv, err := logstash.NewInvocation(logstashPath, *logstashArgs, targetVersion, *configPaths...)
	if err != nil {
		userError("An error occurred while setting up the Logstash environment: %s", err)
		return 1
	}
	defer inv.Release()
	if *unixSockets {
		if runtime.GOOS == "windows" {
			userError("Use of Unix domain sockets for communication with Logstash is not supported on Windows.")
			return 1
		}
		fmt.Println("Use Unix domain sockets.")
		if err = runParallelTests(inv, tests, diffCmd, allKeptEnvVars); err != nil {
			userError(err.Error())
			return 1
		}
	} else {
		if err = runTests(inv, tests, diffCmd, allKeptEnvVars); err != nil {
			userError(err.Error())
			return 1
		}
	}
	return 0
}

func main() {
	os.Exit(mainEntrypoint())
}
<|endoftext|>


<commit_before>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.27.0"
<commit_msg>Bump go-sensor version to 1.27.1<commit_after>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.27.1"
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
)

// Version of the app
var Version = "snapshot"

var (
	version = flag.Bool("version", false, "Print version")
)

func printVersion() {
	fmt.Printf(`webhookd (%s)
Copyright (C) 2020 Nunux, Org.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Nicolas Carlier.`, Version)
}
<commit_msg>chore(): simplify version output<commit_after>package main

import (
	"flag"
	"fmt"
)

// Version of the app
var Version = "snapshot"

var (
	version = flag.Bool("version", false, "Print version")
)

func printVersion() {
	fmt.Printf(`webhookd (%s)

Copyright (C) 2020 Nicolas Carlier
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.`, Version)
}
<|endoftext|>


<commit_before>package sorg

const (
	// Release is the asset version of the site. Bump when any assets are
	// updated to blow away any browser caches.
	Release = "32"
)
<commit_msg>Bump asset version<commit_after>package sorg

const (
	// Release is the asset version of the site. Bump when any assets are
	// updated to blow away any browser caches.
	Release = "33"
)
<|endoftext|>


<commit_before>package dns

import "fmt"

// Version is current version of this library.
var Version = V{1, 0, 3}

// V holds the version of this library.
type V struct {
	Major, Minor, Patch int
}

func (v V) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<commit_msg>Release 1.0.4<commit_after>package dns

import "fmt"

// Version is current version of this library.
var Version = V{1, 0, 4}

// V holds the version of this library.
type V struct {
	Major, Minor, Patch int
}

func (v V) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<|endoftext|>


<commit_before>package dns

import "fmt"

// Version is current version of this library.
var Version = V{1, 0, 8}

// V holds the version of this library.
type V struct {
	Major, Minor, Patch int
}

func (v V) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<commit_msg>Release 1.0.9<commit_after>package dns

import "fmt"

// Version is current version of this library.
var Version = V{1, 0, 9}

// V holds the version of this library.
type V struct {
	Major, Minor, Patch int
}

func (v V) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<|endoftext|>


<commit_before>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package db_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/lxc/lxd/lxd/db"
)

func TestGetCertificate(t *testing.T) {
	tx, cleanup := db.NewTestClusterTx(t)
	defer cleanup()

	_, err := tx.CreateCertificate(db.Certificate{Fingerprint: "foobar"})
	require.NoError(t, err)

	cert, err := tx.GetCertificate("foo%")
	require.NoError(t, err)
	assert.Equal(t, cert.Fingerprint, "foobar")
}
<commit_msg>lxd/db/certificates/test: remove wildcard from test<commit_after>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package db_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/lxc/lxd/lxd/db"
)

func TestGetCertificate(t *testing.T) {
	tx, cleanup := db.NewTestClusterTx(t)
	defer cleanup()

	_, err := tx.CreateCertificate(db.Certificate{Fingerprint: "foobar"})
	require.NoError(t, err)

	cert, err := tx.GetCertificate("foobar")
	require.NoError(t, err)
	assert.Equal(t, cert.Fingerprint, "foobar")
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"sync"
	"time"

	"github.com/go-errors/errors"
	irma "github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/server"
	"github.com/privacybydesign/irmago/server/irmaserver"
	"github.com/sietseringers/cobra"
	"github.com/sirupsen/logrus"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
)

var (
	httpServer *http.Server
	irmaServer *irmaserver.Server
	defaulturl string

	logger = logrus.New()
)

// sessionCmd represents the session command
var sessionCmd = &cobra.Command{
	Use:   "session",
	Short: "Perform an IRMA disclosure, issuance or signature session",
	Long: `Perform an IRMA disclosure, issuance or signature session on the command line

Using either the builtin IRMA server library, or an external IRMA server (specify its URL
with --server), an IRMA session is started; the QR is printed in the terminal; and the session
result is printed when the session completes or fails.

A session request can either be constructed using the --disclose, --issue, and --sign together
with --message flags, or it can be specified as JSON to the --request flag.`,
	Example: `irma session --disclose irma-demo.MijnOverheid.root.BSN
irma session --sign irma-demo.MijnOverheid.root.BSN --message message
irma session --issue irma-demo.MijnOverheid.ageLower=yes,yes,yes,no --disclose irma-demo.MijnOverheid.root.BSN
irma session --request '{"type":"disclosing","content":[{"label":"BSN","attributes":["irma-demo.MijnOverheid.root.BSN"]}]}'
irma session --server http://localhost:8088 --authmethod token --key mytoken --disclose irma-demo.MijnOverheid.root.BSN`,
	Run: func(cmd *cobra.Command, args []string) {
		request, irmaconfig, err := configureSession(cmd)
		if err != nil {
			die("", err)
		}

		// Make sure we always run with latest configuration
		flags := cmd.Flags()
		disableUpdate, _ := flags.GetBool("disable-schemes-update")
		if !disableUpdate {
			if err = irmaconfig.UpdateSchemes(); err != nil {
				die("failed updating schemes", err)
			}
		}

		var result *server.SessionResult
		url, _ := cmd.Flags().GetString("url")
		serverurl, _ := cmd.Flags().GetString("server")
		noqr, _ := cmd.Flags().GetBool("noqr")
		binding, _ := cmd.Flags().GetBool("binding")

		if url != defaulturl && serverurl != "" {
			die("Failed to read configuration", errors.New("--url can't be combined with --server"))
		}

		if serverurl == "" {
			port, _ := flags.GetInt("port")
			privatekeysPath, _ := flags.GetString("privkeys")
			verbosity, _ := cmd.Flags().GetCount("verbose")
			result, err = libraryRequest(request, irmaconfig, url, port, privatekeysPath, noqr, verbosity, binding)
		} else {
			authmethod, _ := flags.GetString("authmethod")
			key, _ := flags.GetString("key")
			name, _ := flags.GetString("name")
			result, err = serverRequest(request, serverurl, authmethod, key, name, noqr, binding)
		}
		if err != nil {
			die("Session failed", err)
		}

		printSessionResult(result)

		// Done!
		if httpServer != nil {
			_ = httpServer.Close()
		}
	},
}

func libraryRequest(
	request irma.RequestorRequest,
	irmaconfig *irma.Configuration,
	url string,
	port int,
	privatekeysPath string,
	noqr bool,
	verbosity int,
	binding bool,
) (*server.SessionResult, error) {
	if err := configureSessionServer(url, port, privatekeysPath, irmaconfig, verbosity); err != nil {
		return nil, err
	}
	startServer(port)

	// Start the session
	resultchan := make(chan *server.SessionResult)
	qr, requestorToken, _, err := irmaServer.StartSession(request, func(r *server.SessionResult) {
		resultchan <- r
	})
	if err != nil {
		return nil, errors.WrapPrefix(err, "IRMA session failed", 0)
	}

	// Enable binding if necessary
	var sessionOptions *irma.SessionOptions
	if binding {
		optionsRequest := irma.NewOptionsRequest()
		optionsRequest.BindingMethod = irma.BindingMethodPin
		if sessionOptions, err = irmaServer.SetFrontendOptions(requestorToken, &optionsRequest); err != nil {
			return nil, errors.WrapPrefix(err, "IRMA enable binding failed", 0)
		}
	}

	// Print QR code
	if err := printQr(qr, noqr); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to print QR", 0)
	}

	if binding {
		// Listen for session status
		statuschan := make(chan irma.ServerStatus)
		go func() {
			var status irma.ServerStatus
			for {
				newStatus := irmaServer.GetSessionResult(requestorToken).Status
				if newStatus != status {
					status = newStatus
					statuschan <- status
					if status.Finished() {
						return
					}
				}
				time.Sleep(500 * time.Millisecond)
			}
		}()

		_, err = handleBinding(sessionOptions, statuschan, func() error {
			return irmaServer.BindingCompleted(requestorToken)
		})
		if err != nil {
			return nil, errors.WrapPrefix(err, "Failed to handle binding", 0)
		}
	}

	// Wait for session to finish and then return session result
	return <-resultchan, nil
}

func serverRequest(
	request irma.RequestorRequest,
	serverurl, authmethod, key, name string,
	noqr bool,
	binding bool,
) (*server.SessionResult, error) {
	logger.Debug("Server URL: ", serverurl)

	// Start session at server
	qr, frontendAuth, transport, err := postRequest(serverurl, request, name, authmethod, key)
	if err != nil {
		return nil, err
	}

	// Enable binding if necessary
	var frontendTransport *irma.HTTPTransport
	sessionOptions := &irma.SessionOptions{}
	if binding {
		frontendTransport = irma.NewHTTPTransport(qr.URL, false)
		frontendTransport.SetHeader(irma.AuthorizationHeader, string(frontendAuth))
		optionsRequest := irma.NewOptionsRequest()
		optionsRequest.BindingMethod = irma.BindingMethodPin
		err = frontendTransport.Post("frontend/options", sessionOptions, optionsRequest)
		if err != nil {
			return nil, errors.WrapPrefix(err, "Failed to enable binding", 0)
		}
	}

	// Print session QR
	logger.Debug("QR: ", prettyprint(qr))
	if err := printQr(qr, noqr); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to print QR", 0)
	}

	statuschan := make(chan irma.ServerStatus)
	errorchan := make(chan error)
	var wg sync.WaitGroup

	go irma.WaitStatus(transport, irma.ServerStatusInitialized, statuschan, errorchan)
	go func() {
		err := <-errorchan
		if err != nil {
			_ = server.LogFatal(err)
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()

		var status irma.ServerStatus
		if binding {
			status, err = handleBinding(sessionOptions, statuschan, func() error {
				err = frontendTransport.Post("frontend/bindingcompleted", nil, nil)
				if err != nil {
					return errors.WrapPrefix(err, "Failed to complete binding", 0)
				}
				return nil
			})
			if err != nil {
				err = errors.WrapPrefix(err, "Failed to handle binding", 0)
				return
			}
		} else {
			// Wait until client connects if binding is disabled
			status := <-statuschan
			if status != irma.ServerStatusConnected {
				err = errors.Errorf("Unexpected status: %s", status)
				return
			}
		}

		// Wait until client finishes
		status = <-statuschan
		if status != irma.ServerStatusCancelled && status != irma.ServerStatusDone {
			err = errors.Errorf("Unexpected status: %s", status)
			return
		}
	}()

	wg.Wait()
	if err != nil {
		return nil, err
	}

	// Retrieve session result
	result := &server.SessionResult{}
	if err := transport.Get("result", result); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to get session result", 0)
	}
	return result, nil
}

func postRequest(serverurl string, request irma.RequestorRequest, name, authmethod, key string) (
	*irma.Qr, irma.FrontendAuthorization, *irma.HTTPTransport, error) {
	var (
		err       error
		pkg       = &server.SessionPackage{}
		transport = irma.NewHTTPTransport(serverurl, false)
	)

	switch authmethod {
	case "none":
		err = transport.Post("session", pkg, request)
	case "token":
		transport.SetHeader("Authorization", key)
		err = transport.Post("session", pkg, request)
	case "hmac", "rsa":
		var jwtstr string
		jwtstr, err = signRequest(request, name, authmethod, key)
		if err != nil {
			return nil, "", nil, err
		}
		logger.Debug("Session request JWT: ", jwtstr)
		err = transport.Post("session", pkg, jwtstr)
	default:
		return nil, "", nil, errors.New("Invalid authentication method (must be none, token, hmac or rsa)")
	}

	if err != nil {
		return nil, "", transport, err
	}

	requestorToken := pkg.Token
	transport.Server += fmt.Sprintf("session/%s/", requestorToken)

	return pkg.SessionPtr, pkg.FrontendAuth, transport, err
}

func handleBinding(options *irma.SessionOptions, statusChan chan irma.ServerStatus, completeBinding func() error) (
	irma.ServerStatus, error) {
	errorChan := make(chan error)
	status := irma.ServerStatusInitialized
	bindingStarted := false
	for {
		select {
		case status = <-statusChan:
			if status == irma.ServerStatusInitialized {
				continue
			} else if status == irma.ServerStatusBinding {
				bindingStarted = true
				go requestBindingPermission(options, completeBinding, errorChan)
				continue
			} else if status == irma.ServerStatusConnected && !bindingStarted {
				fmt.Println("Binding is not supported by the connected device.")
			}
			return status, nil
		case err := <-errorChan:
			return status, err
		}
	}
}

func requestBindingPermission(options *irma.SessionOptions, completeBinding func() error, errorChan chan error) {
	if options.BindingMethod == irma.BindingMethodPin {
		fmt.Println("\nBinding code:", options.BindingCode)
		fmt.Println("Press Enter to confirm your device shows the same binding code; otherwise press Ctrl-C.")
		_, err := bufio.NewReader(os.Stdin).ReadString('\n')
		if err != nil {
			errorChan <- err
			return
		}
		if err = completeBinding(); err != nil {
			errorChan <- err
			return
		}
		fmt.Println("Binding completed.")
		errorChan <- nil
		return
	}
	errorChan <- errors.Errorf("Binding method %s is not supported", options.BindingMethod)
}

// Configuration functions

func configureSessionServer(url string, port int, privatekeysPath string, irmaconfig *irma.Configuration, verbosity int) error {
	// Replace "port" in url with actual port
	replace := "$1:" + strconv.Itoa(port)
	url = string(regexp.MustCompile("(https?://[^/]*):port").ReplaceAll([]byte(url), []byte(replace)))

	config := &server.Configuration{
		IrmaConfiguration:    irmaconfig,
		Logger:               logger,
		URL:                  url,
		DisableSchemesUpdate: true,
		Verbose:              verbosity,
	}
	if privatekeysPath != "" {
		config.IssuerPrivateKeysPath = privatekeysPath
	}

	var err error
	irmaServer, err = irmaserver.New(config)
	return err
}

func configureSession(cmd *cobra.Command) (irma.RequestorRequest, *irma.Configuration, error) {
	verbosity, _ := cmd.Flags().GetCount("verbose")
	logger.Level = server.Verbosity(verbosity)
	irma.SetLogger(logger)

	return configureRequest(cmd)
}

func init() {
	RootCmd.AddCommand(sessionCmd)

	logger.Formatter = &prefixed.TextFormatter{FullTimestamp: true}

	var err error
	defaulturl, err = server.LocalIP()
	if err != nil {
		logger.Warn("Could not determine local IP address: ", err.Error())
	} else {
		defaulturl = "http://" + defaulturl + ":port"
	}

	flags := sessionCmd.Flags()
	flags.SortFlags = false
	flags.String("server", "", "External IRMA server to post request to (leave blank to use builtin library)")
	flags.StringP("url", "u", defaulturl, "external URL to which IRMA app connects (when not using --server), \":port\" being replaced by --port value")
	flags.IntP("port", "p", 48680, "port to listen at (when not using --server)")
	flags.Bool("noqr", false, "Print JSON instead of draw QR")
	flags.Bool("binding", false, "Enable explicit binding between server and IRMA app")
	flags.StringP("request", "r", "", "JSON session request")
	flags.StringP("privkeys", "k", "", "path to private keys")
	flags.Bool("disable-schemes-update", false, "disable scheme updates")

	addRequestFlags(flags)

	flags.CountP("verbose", "v", "verbose (repeatable)")
}
<commit_msg>In cmd's postRequest return nil for transport when returning an error<commit_after>package cmd

import (
	"bufio"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"sync"
	"time"

	"github.com/go-errors/errors"
	irma "github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/server"
	"github.com/privacybydesign/irmago/server/irmaserver"
	"github.com/sietseringers/cobra"
	"github.com/sirupsen/logrus"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
)

var (
	httpServer *http.Server
	irmaServer *irmaserver.Server
	defaulturl string

	logger = logrus.New()
)

// sessionCmd represents the session command
var sessionCmd = &cobra.Command{
	Use:   "session",
	Short: "Perform an IRMA disclosure, issuance or signature session",
	Long: `Perform an IRMA disclosure, issuance or signature session on the command line

Using either the builtin IRMA server library, or an external IRMA server (specify its URL
with --server), an IRMA session is started; the QR is printed in the terminal; and the session
result is printed when the session completes or fails.

A session request can either be constructed using the --disclose, --issue, and --sign together
with --message flags, or it can be specified as JSON to the --request flag.`,
	Example: `irma session --disclose irma-demo.MijnOverheid.root.BSN
irma session --sign irma-demo.MijnOverheid.root.BSN --message message
irma session --issue irma-demo.MijnOverheid.ageLower=yes,yes,yes,no --disclose irma-demo.MijnOverheid.root.BSN
irma session --request '{"type":"disclosing","content":[{"label":"BSN","attributes":["irma-demo.MijnOverheid.root.BSN"]}]}'
irma session --server http://localhost:8088 --authmethod token --key mytoken --disclose irma-demo.MijnOverheid.root.BSN`,
	Run: func(cmd *cobra.Command, args []string) {
		request, irmaconfig, err := configureSession(cmd)
		if err != nil {
			die("", err)
		}

		// Make sure we always run with latest configuration
		flags := cmd.Flags()
		disableUpdate, _ := flags.GetBool("disable-schemes-update")
		if !disableUpdate {
			if err = irmaconfig.UpdateSchemes(); err != nil {
				die("failed updating schemes", err)
			}
		}

		var result *server.SessionResult
		url, _ := cmd.Flags().GetString("url")
		serverurl, _ := cmd.Flags().GetString("server")
		noqr, _ := cmd.Flags().GetBool("noqr")
		binding, _ := cmd.Flags().GetBool("binding")

		if url != defaulturl && serverurl != "" {
			die("Failed to read configuration", errors.New("--url can't be combined with --server"))
		}

		if serverurl == "" {
			port, _ := flags.GetInt("port")
			privatekeysPath, _ := flags.GetString("privkeys")
			verbosity, _ := cmd.Flags().GetCount("verbose")
			result, err = libraryRequest(request, irmaconfig, url, port, privatekeysPath, noqr, verbosity, binding)
		} else {
			authmethod, _ := flags.GetString("authmethod")
			key, _ := flags.GetString("key")
			name, _ := flags.GetString("name")
			result, err = serverRequest(request, serverurl, authmethod, key, name, noqr, binding)
		}
		if err != nil {
			die("Session failed", err)
		}

		printSessionResult(result)

		// Done!
		if httpServer != nil {
			_ = httpServer.Close()
		}
	},
}

func libraryRequest(
	request irma.RequestorRequest,
	irmaconfig *irma.Configuration,
	url string,
	port int,
	privatekeysPath string,
	noqr bool,
	verbosity int,
	binding bool,
) (*server.SessionResult, error) {
	if err := configureSessionServer(url, port, privatekeysPath, irmaconfig, verbosity); err != nil {
		return nil, err
	}
	startServer(port)

	// Start the session
	resultchan := make(chan *server.SessionResult)
	qr, requestorToken, _, err := irmaServer.StartSession(request, func(r *server.SessionResult) {
		resultchan <- r
	})
	if err != nil {
		return nil, errors.WrapPrefix(err, "IRMA session failed", 0)
	}

	// Enable binding if necessary
	var sessionOptions *irma.SessionOptions
	if binding {
		optionsRequest := irma.NewOptionsRequest()
		optionsRequest.BindingMethod = irma.BindingMethodPin
		if sessionOptions, err = irmaServer.SetFrontendOptions(requestorToken, &optionsRequest); err != nil {
			return nil, errors.WrapPrefix(err, "IRMA enable binding failed", 0)
		}
	}

	// Print QR code
	if err := printQr(qr, noqr); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to print QR", 0)
	}

	if binding {
		// Listen for session status
		statuschan := make(chan irma.ServerStatus)
		go func() {
			var status irma.ServerStatus
			for {
				newStatus := irmaServer.GetSessionResult(requestorToken).Status
				if newStatus != status {
					status = newStatus
					statuschan <- status
					if status.Finished() {
						return
					}
				}
				time.Sleep(500 * time.Millisecond)
			}
		}()

		_, err = handleBinding(sessionOptions, statuschan, func() error {
			return irmaServer.BindingCompleted(requestorToken)
		})
		if err != nil {
			return nil, errors.WrapPrefix(err, "Failed to handle binding", 0)
		}
	}

	// Wait for session to finish and then return session result
	return <-resultchan, nil
}

func serverRequest(
	request irma.RequestorRequest,
	serverurl, authmethod, key, name string,
	noqr bool,
	binding bool,
) (*server.SessionResult, error) {
	logger.Debug("Server URL: ", serverurl)

	// Start session at server
	qr, frontendAuth, transport, err := postRequest(serverurl, request, name, authmethod, key)
	if err != nil {
		return nil, err
	}

	// Enable binding if necessary
	var frontendTransport *irma.HTTPTransport
	sessionOptions := &irma.SessionOptions{}
	if binding {
		frontendTransport = irma.NewHTTPTransport(qr.URL, false)
		frontendTransport.SetHeader(irma.AuthorizationHeader, string(frontendAuth))
		optionsRequest := irma.NewOptionsRequest()
		optionsRequest.BindingMethod = irma.BindingMethodPin
		err = frontendTransport.Post("frontend/options", sessionOptions, optionsRequest)
		if err != nil {
			return nil, errors.WrapPrefix(err, "Failed to enable binding", 0)
		}
	}

	// Print session QR
	logger.Debug("QR: ", prettyprint(qr))
	if err := printQr(qr, noqr); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to print QR", 0)
	}

	statuschan := make(chan irma.ServerStatus)
	errorchan := make(chan error)
	var wg sync.WaitGroup

	go irma.WaitStatus(transport, irma.ServerStatusInitialized, statuschan, errorchan)
	go func() {
		err := <-errorchan
		if err != nil {
			_ = server.LogFatal(err)
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()

		var status irma.ServerStatus
		if binding {
			status, err = handleBinding(sessionOptions, statuschan, func() error {
				err = frontendTransport.Post("frontend/bindingcompleted", nil, nil)
				if err != nil {
					return errors.WrapPrefix(err, "Failed to complete binding", 0)
				}
				return nil
			})
			if err != nil {
				err = errors.WrapPrefix(err, "Failed to handle binding", 0)
				return
			}
		} else {
			// Wait until client connects if binding is disabled
			status := <-statuschan
			if status != irma.ServerStatusConnected {
				err = errors.Errorf("Unexpected status: %s", status)
				return
			}
		}

		// Wait until client finishes
		status = <-statuschan
		if status != irma.ServerStatusCancelled && status != irma.ServerStatusDone {
			err = errors.Errorf("Unexpected status: %s", status)
			return
		}
	}()

	wg.Wait()
	if err != nil {
		return nil, err
	}

	// Retrieve session result
	result := &server.SessionResult{}
	if err := transport.Get("result", result); err != nil {
		return nil, errors.WrapPrefix(err, "Failed to get session result", 0)
	}
	return result, nil
}

func postRequest(serverurl string, request irma.RequestorRequest, name, authmethod, key string) (
	*irma.Qr, irma.FrontendAuthorization, *irma.HTTPTransport, error) {
	var (
		err       error
		pkg       = &server.SessionPackage{}
		transport = irma.NewHTTPTransport(serverurl, false)
	)

	switch authmethod {
	case "none":
		err = transport.Post("session", pkg, request)
	case "token":
		transport.SetHeader("Authorization", key)
		err = transport.Post("session", pkg, request)
	case "hmac", "rsa":
		var jwtstr string
		jwtstr, err = signRequest(request, name, authmethod, key)
		if err != nil {
			return nil, "", nil, err
		}
		logger.Debug("Session request JWT: ", jwtstr)
		err = transport.Post("session", pkg, jwtstr)
	default:
		return nil, "", nil, errors.New("Invalid authentication method (must be none, token, hmac or rsa)")
	}

	if err != nil {
		return nil, "", nil, err
	}

	requestorToken := pkg.Token
	transport.Server += fmt.Sprintf("session/%s/", requestorToken)

	return pkg.SessionPtr, pkg.FrontendAuth, transport, err
}

func handleBinding(options *irma.SessionOptions, statusChan chan irma.ServerStatus, completeBinding func() error) (
	irma.ServerStatus, error) {
	errorChan := make(chan error)
	status := irma.ServerStatusInitialized
	bindingStarted := false
	for {
		select {
		case status = <-statusChan:
			if status == irma.ServerStatusInitialized {
				continue
			} else if status == irma.ServerStatusBinding {
				bindingStarted = true
				go requestBindingPermission(options, completeBinding, errorChan)
				continue
			} else if status == irma.ServerStatusConnected && !bindingStarted {
				fmt.Println("Binding is not supported by the connected device.")
			}
			return status, nil
		case err := <-errorChan:
			return status, err
		}
	}
}

func requestBindingPermission(options *irma.SessionOptions, completeBinding func() error, errorChan chan error) {
	if options.BindingMethod == irma.BindingMethodPin {
		fmt.Println("\nBinding code:", options.BindingCode)
		fmt.Println("Press Enter to confirm your device shows the same binding code; otherwise press Ctrl-C.")
		_, err := bufio.NewReader(os.Stdin).ReadString('\n')
		if err != nil {
			errorChan <- err
			return
		}
		if err = completeBinding(); err != nil {
			errorChan <- err
			return
		}
		fmt.Println("Binding completed.")
		errorChan <- nil
		return
	}
	errorChan <- errors.Errorf("Binding method %s is not supported", options.BindingMethod)
}

// Configuration functions

func configureSessionServer(url string, port int, privatekeysPath string, irmaconfig *irma.Configuration, verbosity int) error {
	// Replace "port" in url with actual port
	replace := "$1:" + strconv.Itoa(port)
	url = string(regexp.MustCompile("(https?://[^/]*):port").ReplaceAll([]byte(url), []byte(replace)))

	config := &server.Configuration{
		IrmaConfiguration:    irmaconfig,
		Logger:               logger,
		URL:                  url,
		DisableSchemesUpdate: true,
		Verbose:              verbosity,
	}
	if privatekeysPath != "" {
		config.IssuerPrivateKeysPath = privatekeysPath
	}

	var err error
	irmaServer, err = irmaserver.New(config)
	return err
}

func configureSession(cmd *cobra.Command) (irma.RequestorRequest, *irma.Configuration, error) {
	verbosity, _ := cmd.Flags().GetCount("verbose")
	logger.Level = server.Verbosity(verbosity)
	irma.SetLogger(logger)

	return configureRequest(cmd)
}

func init() {
	RootCmd.AddCommand(sessionCmd)

	logger.Formatter = &prefixed.TextFormatter{FullTimestamp: true}

	var err error
	defaulturl, err = server.LocalIP()
	if err != nil {
		logger.Warn("Could not determine local IP address: ", err.Error())
	} else {
		defaulturl = "http://" + defaulturl + ":port"
	}

	flags := sessionCmd.Flags()
	flags.SortFlags = false
	flags.String("server", "", "External IRMA server to post request to (leave blank to use builtin library)")
	flags.StringP("url", "u", defaulturl, "external URL to which IRMA app connects (when not using --server), \":port\" being replaced by --port value")
	flags.IntP("port", "p", 48680, "port to listen at (when not using --server)")
	flags.Bool("noqr", false, "Print JSON instead of draw QR")
	flags.Bool("binding", false, "Enable explicit binding between server and IRMA app")
	flags.StringP("request", "r", "", "JSON session request")
	flags.StringP("privkeys", "k", "", "path to private keys")
	flags.Bool("disable-schemes-update", false, "disable scheme updates")

	addRequestFlags(flags)

	flags.CountP("verbose", "v", "verbose (repeatable)")
}
<|endoftext|>


<commit_before>package wls

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

	"github.com/BurntSushi/toml"
)

// See http://docs.oracle.com/cd/E23943_01/web.1111/e24682/toc.htm#RESTS149

// http(s)://host:port/management/tenant-monitoring/path

const (
	// MonitorPath is the REST resource path from the root / that points to where the RESTful Management API endpoint is located.  As of WLS 12.1.2,
	// this is assumed to be /management/tenant-monitoring
	MonitorPath string = "/management/tenant-monitoring"
)

// AdminServer contains the configurable details necessary to request resources from a particular AdminServer.
// ServerUrl format should be similar to the following: "http(s)://[serverhost]:[adminport]"
type AdminServer struct {
	AdminURL string
	Username string
	Password string
}

// Wrapper handles all responses sent back from a WLS Rest endpoint.  These responses are wrapped by a similar body and item or items tag.
// We simply wrap that so we can get to the meat of it in the underlying Server type
//
// Wrapper is composed of 3 pieces:
// - Body contains
//   - the result of the resource request, included as either a specific Item (Datasource, Server,
//     Cluster, or Application, or
//   - an array of []Item's of the same.
// - Messages contains any error-related messages related to the query.
type Wrapper struct {
	Body struct {
		Items json.RawMessage `json:"items,omitempty"`
		Item  json.RawMessage `json:"item,omitempty"`
	} `json:"body"`
	Messages []string `json:"messages,omitempty"`
}

// requestResource is a wrapper around an http.Client{} instance assuming the following:
// - the request is a GET
// - assumes a JSON Accept header
// - set Basic Authentication based on the *AdminServer passed in
//
// returns the *http.Response or an error
func requestResource(url string, e *AdminServer) (*http.Response, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Accept", "application/json")
	req.SetBasicAuth(e.Username, e.Password)
	return client.Do(req)
}

func requestAndUnmarshal(url string, e *AdminServer) (*Wrapper, error) {
	resp, err := request(url, e)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return unmarshalWrapper(data)
}

// Wrapper function for requestResource(), handling HTTP response codes before unmarshalling responses.
func request(url string, e *AdminServer) (*http.Response, error) {
	resp, err := requestResource(url, e)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return resp, nil
	}
	body, _ := ioutil.ReadAll(resp.Body)
	return nil, fmt.Errorf("Invalid Response Code: %v\nResponse: \n%v", resp.StatusCode, string(body))
}

// Take the raw response from the server and attempt to unmarshal it into the Wrapper type.
func unmarshalWrapper(data []byte) (*Wrapper, error) {
	var w Wrapper
	err := json.Unmarshal(data, &w)
	if err != nil {
		return nil, err
	}
	return &w, nil
}

// EncodeConfigFile will take an AdminServer instance and convert it to a TOML-formatted byte buffer.
// This TOML byte buffer can then be serialized to disk as a configuration file.
func (cfg AdminServer) EncodeConfigFile() *bytes.Buffer {
	var buf bytes.Buffer
	enc := toml.NewEncoder(&buf)
	err := enc.Encode(cfg)
	if err != nil {
		panic(fmt.Errorf("Unable to encode wlsrest configuration: %s \n", err))
	}
	return &buf
}
<commit_msg>whitespace removal<commit_after>package wls

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

	"github.com/BurntSushi/toml"
)
// See http://docs.oracle.com/cd/E23943_01/web.1111/e24682/toc.htm#RESTS149

// http(s)://host:port/management/tenant-monitoring/path

const (
	// MonitorPath is the REST resource path from the root / that points to where the RESTful Management API endpoint is located.  As of WLS 12.1.2,
	// this is assumed to be /management/tenant-monitoring
	MonitorPath string = "/management/tenant-monitoring"
)

// AdminServer contains the configurable details necessary to request resources from a particular AdminServer.
// ServerUrl format should be similar to the following: "http(s)://[serverhost]:[adminport]"
type AdminServer struct {
	AdminURL string
	Username string
	Password string
}

// Wrapper handles all responses sent back from a WLS Rest endpoint.  These responses are wrapped by a similar body and item or items tag.
// We simply wrap that so we can get to the meat of it in the underlying Server type
//
// Wrapper is composed of 3 pieces:
// - Body contains
//   - the result of the resource request, included as either a specific Item (Datasource, Server,
//     Cluster, or Application, or
//   - an array of []Item's of the same.
// - Messages contains any error-related messages related to the query.
type Wrapper struct {
	Body struct {
		Items json.RawMessage `json:"items,omitempty"`
		Item  json.RawMessage `json:"item,omitempty"`
	} `json:"body"`
	Messages []string `json:"messages,omitempty"`
}

// requestResource is a wrapper around an http.Client{} instance assuming the following:
// - the request is a GET
// - assumes a JSON Accept header
// - set Basic Authentication based on the *AdminServer passed in
//
// returns the *http.Response or an error
func requestResource(url string, e *AdminServer) (*http.Response, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Accept", "application/json")
	req.SetBasicAuth(e.Username, e.Password)
	return client.Do(req)
}

func requestAndUnmarshal(url string, e *AdminServer) (*Wrapper, error) {
	resp, err := request(url, e)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return unmarshalWrapper(data)
}

// Wrapper function for requestResource(), handling HTTP response codes before unmarshalling responses.
func request(url string, e *AdminServer) (*http.Response, error) {
	resp, err := requestResource(url, e)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return resp, nil
	}
	body, _ := ioutil.ReadAll(resp.Body)
	return nil, fmt.Errorf("Invalid Response Code: %v\nResponse: \n%v", resp.StatusCode, string(body))
}

// Take the raw response from the server and attempt to unmarshal it into the Wrapper type.
func unmarshalWrapper(data []byte) (*Wrapper, error) {
	var w Wrapper
	err := json.Unmarshal(data, &w)
	if err != nil {
		return nil, err
	}
	return &w, nil
}

// EncodeConfigFile will take an AdminServer instance and convert it to a TOML-formatted byte buffer.
// This TOML byte buffer can then be serialized to disk as a configuration file.
func (cfg AdminServer) EncodeConfigFile() *bytes.Buffer {
	var buf bytes.Buffer
	enc := toml.NewEncoder(&buf)
	err := enc.Encode(cfg)
	if err != nil {
		panic(fmt.Errorf("Unable to encode wlsrest configuration: %s \n", err))
	}
	return &buf
}
<|endoftext|>


<commit_before>//A workerpool that can get expanded & shrinked dynamically.
package workerpool

//License: See the LICENSE File.

import (
	"runtime"
	"time"
)

//Sample usage:
//	func main() {
//		jobChannel := make(chan workerpool.Job)
//
//		pool := workerpool.New(0, jobChannel)
//		pool.Run()
//
//		done := make(chan bool)
//		jobChannel <- func() {
//			log.Info("Job done!")
//			done <- true
//		}
//		<-done
//	}
type WorkerPool struct {
	workerPool chan chan Job
	JobChannel chan Job
	minWorkers int
}

//Starts the worker pool. Initial workers never timeout (well; they do; after a year of unemployment!) and never quit.
func (d *WorkerPool) Run() {
	var defaultConf WorkerConfig
	defaultConf.Registration.Timeout = time.Hour * 24 * 365

	for i := 0; i < d.minWorkers; i++ {
		worker := newWorker(d.workerPool, defaultConf)
		worker.Start()
	}

	go d.dispatch()
}

//Putting more 'Worker's into work. If there is'nt any job to do,
//they will simply get timed-out and worker pool will shrink to it's minimum size.
//Default behaviour is they will timeout on conf.Registration.Timeout in a sliding manner.
func (d *WorkerPool) GrowExtra(n int, conf WorkerConfig) {
	for i := 0; i < n; i++ {
		worker := newWorker(d.workerPool, conf)
		worker.Start()
	}
}

func (d *WorkerPool) dispatch() {
	for {
		select {
		case job, ok := <-d.JobChannel:
			if !ok {
				//it means this dispatcher has stopped
				return
			}

			//memory hungry version
			//go d.handleJob(job)

			d.handleJob(job)
		}
	}
}

func (d *WorkerPool) handleJob(j Job) {
	todo := <-d.workerPool
	todo <- j
}

//Creates a new worker pool. If minWorkers is 0 or negative, the default number of workers would be runtime.NumCPU().
func New(minWorkers int, jobChannel chan Job) *WorkerPool {
	if minWorkers <= 0 {
		minWorkers = runtime.NumCPU()
	}

	return &WorkerPool{
		workerPool: make(chan chan Job, minWorkers),
		JobChannel: jobChannel,
		minWorkers: minWorkers,
	}
}

type Job func()

//Configuration for extra workers.
type WorkerConfig struct {
	Registration struct {
		Timeout    time.Duration
		IsAbsolute bool
	}
	Quit chan bool
}

func NewWorkerConfig(timeout time.Duration, isAbsolute bool, quit chan bool) WorkerConfig {
	var conf WorkerConfig
	conf.Registration.Timeout = timeout
	conf.Registration.IsAbsolute = isAbsolute
	conf.Quit = quit

	return conf
}

type worker struct {
	workerPool  chan chan Job
	todoChannel chan Job
	config      WorkerConfig
}

func (w *worker) Start() {
	go w.startWorking()
}

func (w *worker) startWorking() {
	var absoluteTimeout <-chan time.Time
	if w.config.Registration.IsAbsolute {
		absoluteTimeout = time.After(w.config.Registration.Timeout)
	}

	for {
		//register this worker in the pool
		select {
		case w.workerPool <- w.todoChannel:
		case <-time.After(w.config.Registration.Timeout):
			//failed to register; means WorkerPool is full == there are
			//enough workers with not enough work!
			return
		case <-absoluteTimeout:
			return
		case <-w.config.Quit:
			return
		}

		select {
		case job, ok := <-w.todoChannel:
			if !ok {
				return
			}

			if job != nil {
				job()
			}
		case <-w.config.Quit:
			return
		}
	}
}

func newWorker(workerPool chan chan Job, conf WorkerConfig) *worker {
	return &worker{
		workerPool:  workerPool,
		todoChannel: make(chan Job),
		config:      conf,
	}
}
<commit_msg>fixing a typo<commit_after>//A workerpool that can get expanded & shrink dynamically.
package workerpool

//License: See the LICENSE File.

import (
	"runtime"
	"time"
)

//Sample usage:
//	func main() {
//		jobChannel := make(chan workerpool.Job)
//
//		pool := workerpool.New(0, jobChannel)
//		pool.Run()
//
//		done := make(chan bool)
//		jobChannel <- func() {
//			log.Info("Job done!")
//			done <- true
//		}
//		<-done
//	}
type WorkerPool struct {
	workerPool chan chan Job
	JobChannel chan Job
	minWorkers int
}

//Starts the worker pool. Initial workers never timeout (well; they do; after a year of unemployment!) and never quit.
func (d *WorkerPool) Run() {
	var defaultConf WorkerConfig
	defaultConf.Registration.Timeout = time.Hour * 24 * 365

	for i := 0; i < d.minWorkers; i++ {
		worker := newWorker(d.workerPool, defaultConf)
		worker.Start()
	}

	go d.dispatch()
}

//Putting more 'Worker's into work. If there is'nt any job to do,
//they will simply get timed-out and worker pool will shrink to it's minimum size.
//Default behaviour is they will timeout on conf.Registration.Timeout in a sliding manner.
func (d *WorkerPool) GrowExtra(n int, conf WorkerConfig) {
	for i := 0; i < n; i++ {
		worker := newWorker(d.workerPool, conf)
		worker.Start()
	}
}

func (d *WorkerPool) dispatch() {
	for {
		select {
		case job, ok := <-d.JobChannel:
			if !ok {
				//it means this dispatcher has stopped
				return
			}

			//memory hungry version
			//go d.handleJob(job)

			d.handleJob(job)
		}
	}
}

func (d *WorkerPool) handleJob(j Job) {
	todo := <-d.workerPool
	todo <- j
}

//Creates a new worker pool. If minWorkers is 0 or negative, the default number of workers would be runtime.NumCPU().
func New(minWorkers int, jobChannel chan Job) *WorkerPool {
	if minWorkers <= 0 {
		minWorkers = runtime.NumCPU()
	}

	return &WorkerPool{
		workerPool: make(chan chan Job, minWorkers),
		JobChannel: jobChannel,
		minWorkers: minWorkers,
	}
}

type Job func()

//Configuration for extra workers.
type WorkerConfig struct {
	Registration struct {
		Timeout    time.Duration
		IsAbsolute bool
	}
	Quit chan bool
}

func NewWorkerConfig(timeout time.Duration, isAbsolute bool, quit chan bool) WorkerConfig {
	var conf WorkerConfig
	conf.Registration.Timeout = timeout
	conf.Registration.IsAbsolute = isAbsolute
	conf.Quit = quit

	return conf
}

type worker struct {
	workerPool  chan chan Job
	todoChannel chan Job
	config      WorkerConfig
}

func (w *worker) Start() {
	go w.startWorking()
}

func (w *worker) startWorking() {
	var absoluteTimeout <-chan time.Time
	if w.config.Registration.IsAbsolute {
		absoluteTimeout = time.After(w.config.Registration.Timeout)
	}

	for {
		//register this worker in the pool
		select {
		case w.workerPool <- w.todoChannel:
		case <-time.After(w.config.Registration.Timeout):
			//failed to register; means WorkerPool is full == there are
			//enough workers with not enough work!
			return
		case <-absoluteTimeout:
			return
		case <-w.config.Quit:
			return
		}

		select {
		case job, ok := <-w.todoChannel:
			if !ok {
				return
			}

			if job != nil {
				job()
			}
		case <-w.config.Quit:
			return
		}
	}
}

func newWorker(workerPool chan chan Job, conf WorkerConfig) *worker {
	return &worker{
		workerPool:  workerPool,
		todoChannel: make(chan Job),
		config:      conf,
	}
}
<|endoftext|>


<commit_before>package cloudflare

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

	"github.com/pkg/errors"
)

// StorageNamespaceRequest provides parameters for creating and updating storage namespaces
type StorageNamespaceRequest struct {
	Title string
}

// StorageNamespaceResponse is the response received when creating storage namespaces
type StorageNamespaceResponse struct {
	Response
	ID, Title string
}

// StorageNamespace contains the unique identifier and title of a storage namespace
type StorageNamespace struct {
	ID, Title string
}

// ListStorageNamespacesResponse contains a slice of storage namespaces associated with an
// account, pagination information, and an embedded response struct
type ListStorageNamespacesResponse struct {
	Response
	Result     []StorageNamespace `json:"result"`
	ResultInfo `json:"result_info"`
}

// StorageKey is a key name used to identify a storage value
type StorageKey struct {
	Name string `json:"name"`
}

// ListStorageKeysResponse contains a slice of keys belonging to a storage namespace,
// paginatiion information, and an embedded response struct
type ListStorageKeysResponse struct {
	Response
	Result     []StorageKey `json:"result"`
	ResultInfo `json:"result_info"`
}

// CreateStorageNamespace creates a namespace under the given title.
// A 400 is returned if the account already owns a namespace with this title.
// A namespace must be explicitly deleted to be replaced.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-create-a-namespace
func (api *API) CreateStorageNamespace(ctx context.Context, req *StorageNamespaceRequest) (StorageNamespaceResponse, error) {
	uri := path.Join("/accounts", api.OrganizationID, "storage/kv/namespaces")
	res, err := api.makeRequestContext(ctx, "POST", uri, req)
	if err != nil {
		return StorageNamespaceResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := StorageNamespaceResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// ListStorageNamespaces lists storage namespaces
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-list-namespaces
func (api *API) ListStorageNamespaces(ctx context.Context) (ListStorageNamespacesResponse, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", api.OrganizationID)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return ListStorageNamespacesResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := ListStorageNamespacesResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// DeleteStorageNamespace deletes the namespace corresponding to the given ID
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-remove-a-namespace
func (api *API) DeleteStorageNamespace(ctx context.Context, namespace string) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "DELETE", uri, nil)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// UpdateStorageNamespace modifies a namespace's title
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-rename-a-namespace
func (api *API) UpdateStorageNamespace(ctx context.Context, namespace string, req *StorageNamespaceRequest) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "PUT", uri, req)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// CreateStorageKV writes a value identified by a key. Body should be the value to be stored.
// Existing values will be overwritten.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-write-key-value-pair
func (api *API) CreateStorageKV(ctx context.Context, namespace, key string, value io.Reader) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestWithAuthTypeAndHeaders(
		ctx, "PUT", uri, value, api.authType, http.Header{"Content-Type": []string{"binary/octet-stream"}},
	)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// ReadStorageKV returns the value associated with the given key in the given namespace
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair
func (api API) ReadStorageKV(ctx context.Context, namespace, key string) ([]byte, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return nil, errors.Wrap(err, errMakeRequestError)
	}
	return res, nil
}

// DeleteStorageKV deletes a key and value for a provided storage namespace
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-key-value-pair
func (api API) DeleteStorageKV(ctx context.Context, namespace, key string) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestContext(ctx, "DELETE", uri, nil)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}
	return result, err
}

// ListStorageKeys lists a namespace's keys
//
// API Reference: https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
func (api API) ListStorageKeys(ctx context.Context, namespace string) (ListStorageKeysResponse, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return ListStorageKeysResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := ListStorageKeysResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}
	return result, err
}
<commit_msg>Add explicit JSON tags.<commit_after>package cloudflare

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

	"github.com/pkg/errors"
)

// StorageNamespaceRequest provides parameters for creating and updating storage namespaces
type StorageNamespaceRequest struct {
	Title string
}

// StorageNamespaceResponse is the response received when creating storage namespaces
type StorageNamespaceResponse struct {
	Response
	ID, Title string
}

// StorageNamespace contains the unique identifier and title of a storage namespace
type StorageNamespace struct {
	ID string `json:"id"`
	Title string `json:"title"`
}

// ListStorageNamespacesResponse contains a slice of storage namespaces associated with an
// account, pagination information, and an embedded response struct
type ListStorageNamespacesResponse struct {
	Response
	Result     []StorageNamespace `json:"result"`
	ResultInfo `json:"result_info"`
}

// StorageKey is a key name used to identify a storage value
type StorageKey struct {
	Name string `json:"name"`
}

// ListStorageKeysResponse contains a slice of keys belonging to a storage namespace,
// paginatiion information, and an embedded response struct
type ListStorageKeysResponse struct {
	Response
	Result     []StorageKey `json:"result"`
	ResultInfo `json:"result_info"`
}

// CreateStorageNamespace creates a namespace under the given title.
// A 400 is returned if the account already owns a namespace with this title.
// A namespace must be explicitly deleted to be replaced.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-create-a-namespace
func (api *API) CreateStorageNamespace(ctx context.Context, req *StorageNamespaceRequest) (StorageNamespaceResponse, error) {
	uri := path.Join("/accounts", api.OrganizationID, "storage/kv/namespaces")
	res, err := api.makeRequestContext(ctx, "POST", uri, req)
	if err != nil {
		return StorageNamespaceResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := StorageNamespaceResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// ListStorageNamespaces lists storage namespaces
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-list-namespaces
func (api *API) ListStorageNamespaces(ctx context.Context) (ListStorageNamespacesResponse, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", api.OrganizationID)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return ListStorageNamespacesResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := ListStorageNamespacesResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// DeleteStorageNamespace deletes the namespace corresponding to the given ID
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-remove-a-namespace
func (api *API) DeleteStorageNamespace(ctx context.Context, namespace string) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "DELETE", uri, nil)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// UpdateStorageNamespace modifies a namespace's title
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-rename-a-namespace
func (api *API) UpdateStorageNamespace(ctx context.Context, namespace string, req *StorageNamespaceRequest) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "PUT", uri, req)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// CreateStorageKV writes a value identified by a key. Body should be the value to be stored.
// Existing values will be overwritten.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-write-key-value-pair
func (api *API) CreateStorageKV(ctx context.Context, namespace, key string, value io.Reader) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestWithAuthTypeAndHeaders(
		ctx, "PUT", uri, value, api.authType, http.Header{"Content-Type": []string{"binary/octet-stream"}},
	)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}

	return result, err
}

// ReadStorageKV returns the value associated with the given key in the given namespace
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair
func (api API) ReadStorageKV(ctx context.Context, namespace, key string) ([]byte, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return nil, errors.Wrap(err, errMakeRequestError)
	}
	return res, nil
}

// DeleteStorageKV deletes a key and value for a provided storage namespace
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-key-value-pair
func (api API) DeleteStorageKV(ctx context.Context, namespace, key string) (Response, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.OrganizationID, namespace, key)
	res, err := api.makeRequestContext(ctx, "DELETE", uri, nil)
	if err != nil {
		return Response{}, errors.Wrap(err, errMakeRequestError)
	}

	result := Response{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}
	return result, err
}

// ListStorageKeys lists a namespace's keys
//
// API Reference: https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
func (api API) ListStorageKeys(ctx context.Context, namespace string) (ListStorageKeysResponse, error) {
	uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys", api.OrganizationID, namespace)
	res, err := api.makeRequestContext(ctx, "GET", uri, nil)
	if err != nil {
		return ListStorageKeysResponse{}, errors.Wrap(err, errMakeRequestError)
	}

	result := ListStorageKeysResponse{}
	if err := json.Unmarshal(res, &result); err != nil {
		return result, errors.Wrap(err, errUnmarshalError)
	}
	return result, err
}
<|endoftext|>