<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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 audio provides audio players. This can be used with or without ebiten package.
//
// The stream format must be 16-bit little endian and 2 channels.
//
// An audio context has a sample rate you can set and all streams you want to play must have the same
// sample rate. However, decoders like audio/vorbis and audio/wav adjust sample rate,
// and you don't have to care about it as long as you use those decoders.
//
// An audio context can generate 'players' (instances of audio.Player),
// and you can play sound by calling Play function of players.
// When multiple players play, mixing is automatically done.
// Note that too many players may cause distortion.
package audio

import (
	"bytes"
	"errors"
	"io"
	"runtime"
	"sync"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio/internal/driver"
)

type players struct {
	players  map[*Player]struct{}
	seekings map[*Player]struct{}
	sync.RWMutex
}

const (
	channelNum     = 2
	bytesPerSample = 2

	// TODO: This assumes that channelNum is a power of 2.
	mask = ^(channelNum*bytesPerSample - 1)
)

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func (p *players) Read(b []byte) (int, error) {
	p.Lock()
	defer p.Unlock()

	if len(p.players) == 0 {
		l := len(b)
		l &= mask
		copy(b, make([]byte, l))
		return l, nil
	}
	closed := []*Player{}
	l := len(b)
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		if err := player.readToBuffer(l); err == io.EOF {
			closed = append(closed, player)
		} else if err != nil {
			return 0, err
		}
		l = min(player.bufferLength(), l)
	}
	l &= mask
	b16s := [][]int16{}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		b16s = append(b16s, player.bufferToInt16(l))
	}
	for i := 0; i < l/2; i++ {
		x := 0
		for _, b16 := range b16s {
			x += int(b16[i])
		}
		if x > (1<<15)-1 {
			x = (1 << 15) - 1
		}
		if x < -(1 << 15) {
			x = -(1 << 15)
		}
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		player.proceed(l)
	}
	for _, pl := range closed {
		delete(p.players, pl)
	}
	return l, nil
}

func (p *players) addPlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.players[player] = struct{}{}
}

func (p *players) removePlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.players, player)
}

func (p *players) addSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.seekings[player] = struct{}{}
}

func (p *players) removeSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.seekings, player)
}

func (p *players) hasPlayer(player *Player) bool {
	p.RLock()
	defer p.RUnlock()
	_, ok := p.players[player]
	return ok
}

func (p *players) hasSource(src ReadSeekCloser) bool {
	p.RLock()
	defer p.RUnlock()
	for player := range p.players {
		if player.src == src {
			return true
		}
	}
	return false
}

// TODO: Enable to specify the format like Mono8?

// A Context is a current state of audio.
//
// There should be at most one Context object.
// This means only one constant sample rate is valid in your one application.
//
// The typical usage with ebiten package is:
//
//    var audioContext *audio.Context
//
//    func update(screen *ebiten.Image) error {
//        // Update updates the audio stream by 1/60 [sec].
//        if err := audioContext.Update(); err != nil {
//            return err
//        }
//        // ...
//    }
//
//    func main() {
//        audioContext, err = audio.NewContext(sampleRate)
//        if err != nil {
//            panic(err)
//        }
//        ebiten.Run(run, update, 320, 240, 2, "Audio test")
//    }
//
// This is 'sync mode' in that game's (logical) time and audio time are synchronized.
// You can also call Update independently from the game loop as 'async mode'.
// In this case, audio goes on even when the game stops e.g. by diactivating the screen.
type Context struct {
	players      *players
	driver       *driver.Player
	sampleRate   int
	frames       int
	writtenBytes int
}

var (
	theContext     *Context
	theContextLock sync.Mutex
)

// NewContext creates a new audio context with the given sample rate (e.g. 44100).
func NewContext(sampleRate int) (*Context, error) {
	theContextLock.Lock()
	defer theContextLock.Unlock()
	if theContext != nil {
		return nil, errors.New("audio: context is already created")
	}
	c := &Context{
		sampleRate: sampleRate,
	}
	theContext = c
	c.players = &players{
		players:  map[*Player]struct{}{},
		seekings: map[*Player]struct{}{},
	}
	return c, nil

}

// Update proceeds the inner (logical) time of the context by 1/60 second.
//
// This is expected to be called in the game's updating function (sync mode)
// or an independent goroutine with timers (async mode).
// In sync mode, the game logical time syncs the audio logical time and
// you will find audio stops when the game stops e.g. when the window is deactivated.
// In async mode, the audio never stops even when the game stops.
func (c *Context) Update() error {
	// Initialize c.driver lazily to enable calling NewContext in an 'init' function.
	// Accessing driver functions requires the environment to be already initialized,
	// but if Ebiten is used for a shared library, the timing when init functions are called
	// is unexpectable.
	// e.g. a variable for JVM on Android might not be set.
	if c.driver == nil {
		// TODO: Rename this other than player
		p, err := driver.NewPlayer(c.sampleRate, channelNum, bytesPerSample)
		c.driver = p
		if err != nil {
			return err
		}
	}
	c.frames++
	bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / ebiten.FPS
	l := (c.frames * bytesPerFrame) - c.writtenBytes
	l &= mask
	c.writtenBytes += l
	buf := make([]byte, l)
	n, err := io.ReadFull(c.players, buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return c.driver.Close()
	}
	// TODO: Rename this to Enqueue
	err = c.driver.Proceed(buf)
	if err == io.EOF {
		return c.driver.Close()
	}
	if err != nil {
		return err
	}
	return nil
}

// SampleRate returns the sample rate.
// All audio source must have the same sample rate.
//
// This function is concurrent-safe.
func (c *Context) SampleRate() int {
	return c.sampleRate
}

// ReadSeekCloser is an io.ReadSeeker and io.Closer.
type ReadSeekCloser interface {
	io.ReadSeeker
	io.Closer
}

type nopCloser struct {
	io.ReadSeeker
}

func (*nopCloser) Close() error {
	return nil
}

// NopCloser creates ReadSeekCloser from io.ReadSeeker.
// The added Close function is empty and does nothing.
func NopCloser(r io.ReadSeeker) ReadSeekCloser {
	return &nopCloser{r}
}

// Player is an audio player which has one stream.
type Player struct {
	players    *players
	src        ReadSeekCloser
	buf        []byte
	sampleRate int
	pos        int64
	volume     float64
}

// NewPlayer creates a new player with the given stream.
//
// src's format must be linear PCM (16bits little endian, 2 channel stereo)
// without a header (e.g. RIFF header).
// The sample rate must be same as that of the audio context.
//
// Note that the given src can't be shared with other Players.
//
// This function is concurrent-safe.
func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
	if context.players.hasSource(src) {
		return nil, errors.New("audio: src cannot be shared with another Player")
	}
	p := &Player{
		players:    context.players,
		src:        src,
		sampleRate: context.sampleRate,
		buf:        []byte{},
		volume:     1,
	}
	// Get the current position of the source.
	pos, err := p.src.Seek(0, io.SeekCurrent)
	if err != nil {
		return nil, err
	}
	p.pos = pos
	runtime.SetFinalizer(p, (*Player).Close)
	return p, nil
}

type bytesReadSeekCloser struct {
	*bytes.Reader
}

func (b *bytesReadSeekCloser) Close() error {
	return nil
}

// NewPlayerFromBytes creates a new player with the given bytes.
//
// As opposed to NewPlayer, you don't have to care if src is already used by another player or not.
// src can be shared by multiple players.
//
// The format of src should be same as noted at NewPlayer.
//
// This function is concurrent-safe.
func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
	b := &bytesReadSeekCloser{bytes.NewReader(src)}
	return NewPlayer(context, b)
}

// Close closes the stream. Ths source stream passed by NewPlayer will also be closed.
//
// When closing, the stream owned by the player will also be closed by calling its Close.
//
// This function is concurrent-safe.
func (p *Player) Close() error {
	p.players.removePlayer(p)
	runtime.SetFinalizer(p, nil)
	return p.src.Close()
}

func (p *Player) readToBuffer(length int) error {
	bb := make([]byte, length)
	n, err := p.src.Read(bb)
	if 0 < n {
		p.buf = append(p.buf, bb[:n]...)
	}
	return err
}

func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
	r := make([]int16, lengthInBytes/2)
	for i := 0; i < lengthInBytes/2; i++ {
		r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
		r[i] = int16(float64(r[i]) * p.volume)
	}
	return r
}

func (p *Player) proceed(length int) {
	p.buf = p.buf[length:]
	p.pos += int64(length)
}

func (p *Player) bufferLength() int {
	return len(p.buf)
}

// Play plays the stream.
//
// This function is concurrent-safe.
func (p *Player) Play() error {
	p.players.addPlayer(p)
	return nil
}

// IsPlaying returns boolean indicating whether the player is playing.
//
// This function is concurrent-safe.
func (p *Player) IsPlaying() bool {
	return p.players.hasPlayer(p)
}

// Rewind rewinds the current position to the start.
//
// This function is concurrent-safe.
func (p *Player) Rewind() error {
	return p.Seek(0)
}

// Seek seeks the position with the given offset.
//
// This function is concurrent-safe.
func (p *Player) Seek(offset time.Duration) error {
	p.players.addSeeking(p)
	defer p.players.removeSeeking(p)
	o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
	o &= mask
	p.buf = []byte{}
	pos, err := p.src.Seek(o, io.SeekStart)
	if err != nil {
		return err
	}
	p.pos = pos
	return nil
}

// Pause pauses the playing.
//
// This function is concurrent-safe.
func (p *Player) Pause() error {
	p.players.removePlayer(p)
	return nil
}

// Current returns the current position.
//
// This function is concurrent-safe.
func (p *Player) Current() time.Duration {
	sample := p.pos / bytesPerSample / channelNum
	return time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
}

// Volume returns the current volume of this player [0-1].
func (p *Player) Volume() float64 {
	return p.volume
}

// SetVolume sets the volume of this player.
// volume must be in between 0 and 1. This function panics otherwise.
func (p *Player) SetVolume(volume float64) {
	// The condition must be true when volume is NaN.
	if !(0 <= volume && volume <= 1) {
		panic("audio: volume must be in between 0 and 1")
	}
	p.volume = volume
}
<commit_msg>audio: Remove NopCloser and Add BytesReadSeekCloser<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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 audio provides audio players. This can be used with or without ebiten package.
//
// The stream format must be 16-bit little endian and 2 channels.
//
// An audio context has a sample rate you can set and all streams you want to play must have the same
// sample rate. However, decoders like audio/vorbis and audio/wav adjust sample rate,
// and you don't have to care about it as long as you use those decoders.
//
// An audio context can generate 'players' (instances of audio.Player),
// and you can play sound by calling Play function of players.
// When multiple players play, mixing is automatically done.
// Note that too many players may cause distortion.
package audio

import (
	"bytes"
	"errors"
	"io"
	"runtime"
	"sync"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio/internal/driver"
)

type players struct {
	players  map[*Player]struct{}
	seekings map[*Player]struct{}
	sync.RWMutex
}

const (
	channelNum     = 2
	bytesPerSample = 2

	// TODO: This assumes that channelNum is a power of 2.
	mask = ^(channelNum*bytesPerSample - 1)
)

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func (p *players) Read(b []byte) (int, error) {
	p.Lock()
	defer p.Unlock()

	if len(p.players) == 0 {
		l := len(b)
		l &= mask
		copy(b, make([]byte, l))
		return l, nil
	}
	closed := []*Player{}
	l := len(b)
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		if err := player.readToBuffer(l); err == io.EOF {
			closed = append(closed, player)
		} else if err != nil {
			return 0, err
		}
		l = min(player.bufferLength(), l)
	}
	l &= mask
	b16s := [][]int16{}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		b16s = append(b16s, player.bufferToInt16(l))
	}
	for i := 0; i < l/2; i++ {
		x := 0
		for _, b16 := range b16s {
			x += int(b16[i])
		}
		if x > (1<<15)-1 {
			x = (1 << 15) - 1
		}
		if x < -(1 << 15) {
			x = -(1 << 15)
		}
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		player.proceed(l)
	}
	for _, pl := range closed {
		delete(p.players, pl)
	}
	return l, nil
}

func (p *players) addPlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.players[player] = struct{}{}
}

func (p *players) removePlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.players, player)
}

func (p *players) addSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.seekings[player] = struct{}{}
}

func (p *players) removeSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.seekings, player)
}

func (p *players) hasPlayer(player *Player) bool {
	p.RLock()
	defer p.RUnlock()
	_, ok := p.players[player]
	return ok
}

func (p *players) hasSource(src ReadSeekCloser) bool {
	p.RLock()
	defer p.RUnlock()
	for player := range p.players {
		if player.src == src {
			return true
		}
	}
	return false
}

// TODO: Enable to specify the format like Mono8?

// A Context is a current state of audio.
//
// There should be at most one Context object.
// This means only one constant sample rate is valid in your one application.
//
// The typical usage with ebiten package is:
//
//    var audioContext *audio.Context
//
//    func update(screen *ebiten.Image) error {
//        // Update updates the audio stream by 1/60 [sec].
//        if err := audioContext.Update(); err != nil {
//            return err
//        }
//        // ...
//    }
//
//    func main() {
//        audioContext, err = audio.NewContext(sampleRate)
//        if err != nil {
//            panic(err)
//        }
//        ebiten.Run(run, update, 320, 240, 2, "Audio test")
//    }
//
// This is 'sync mode' in that game's (logical) time and audio time are synchronized.
// You can also call Update independently from the game loop as 'async mode'.
// In this case, audio goes on even when the game stops e.g. by diactivating the screen.
type Context struct {
	players      *players
	driver       *driver.Player
	sampleRate   int
	frames       int
	writtenBytes int
}

var (
	theContext     *Context
	theContextLock sync.Mutex
)

// NewContext creates a new audio context with the given sample rate (e.g. 44100).
func NewContext(sampleRate int) (*Context, error) {
	theContextLock.Lock()
	defer theContextLock.Unlock()
	if theContext != nil {
		return nil, errors.New("audio: context is already created")
	}
	c := &Context{
		sampleRate: sampleRate,
	}
	theContext = c
	c.players = &players{
		players:  map[*Player]struct{}{},
		seekings: map[*Player]struct{}{},
	}
	return c, nil

}

// Update proceeds the inner (logical) time of the context by 1/60 second.
//
// This is expected to be called in the game's updating function (sync mode)
// or an independent goroutine with timers (async mode).
// In sync mode, the game logical time syncs the audio logical time and
// you will find audio stops when the game stops e.g. when the window is deactivated.
// In async mode, the audio never stops even when the game stops.
func (c *Context) Update() error {
	// Initialize c.driver lazily to enable calling NewContext in an 'init' function.
	// Accessing driver functions requires the environment to be already initialized,
	// but if Ebiten is used for a shared library, the timing when init functions are called
	// is unexpectable.
	// e.g. a variable for JVM on Android might not be set.
	if c.driver == nil {
		// TODO: Rename this other than player
		p, err := driver.NewPlayer(c.sampleRate, channelNum, bytesPerSample)
		c.driver = p
		if err != nil {
			return err
		}
	}
	c.frames++
	bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / ebiten.FPS
	l := (c.frames * bytesPerFrame) - c.writtenBytes
	l &= mask
	c.writtenBytes += l
	buf := make([]byte, l)
	n, err := io.ReadFull(c.players, buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return c.driver.Close()
	}
	// TODO: Rename this to Enqueue
	err = c.driver.Proceed(buf)
	if err == io.EOF {
		return c.driver.Close()
	}
	if err != nil {
		return err
	}
	return nil
}

// SampleRate returns the sample rate.
// All audio source must have the same sample rate.
//
// This function is concurrent-safe.
func (c *Context) SampleRate() int {
	return c.sampleRate
}

// ReadSeekCloser is an io.ReadSeeker and io.Closer.
type ReadSeekCloser interface {
	io.ReadSeeker
	io.Closer
}

type bytesReadSeekCloser struct {
	reader *bytes.Reader
}

func (b *bytesReadSeekCloser) Read(buf []uint8) (int, error) {
	return b.reader.Read(buf)
}

func (b *bytesReadSeekCloser) Seek(offset int64, whence int) (int64, error) {
	return b.reader.Seek(offset, whence)
}

func (b *bytesReadSeekCloser) Close() error {
	b.reader = nil
	return nil
}

// BytesReadSeekCloser creates ReadSeekCloser from bytes.
func BytesReadSeekCloser(b []uint8) ReadSeekCloser {
	return &bytesReadSeekCloser{bytes.NewReader(b)}
}

// Player is an audio player which has one stream.
type Player struct {
	players    *players
	src        ReadSeekCloser
	buf        []byte
	sampleRate int
	pos        int64
	volume     float64
}

// NewPlayer creates a new player with the given stream.
//
// src's format must be linear PCM (16bits little endian, 2 channel stereo)
// without a header (e.g. RIFF header).
// The sample rate must be same as that of the audio context.
//
// Note that the given src can't be shared with other Players.
//
// This function is concurrent-safe.
func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
	if context.players.hasSource(src) {
		return nil, errors.New("audio: src cannot be shared with another Player")
	}
	p := &Player{
		players:    context.players,
		src:        src,
		sampleRate: context.sampleRate,
		buf:        []byte{},
		volume:     1,
	}
	// Get the current position of the source.
	pos, err := p.src.Seek(0, io.SeekCurrent)
	if err != nil {
		return nil, err
	}
	p.pos = pos
	runtime.SetFinalizer(p, (*Player).Close)
	return p, nil
}

// NewPlayerFromBytes creates a new player with the given bytes.
//
// As opposed to NewPlayer, you don't have to care if src is already used by another player or not.
// src can be shared by multiple players.
//
// The format of src should be same as noted at NewPlayer.
//
// This function is concurrent-safe.
func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
	b := BytesReadSeekCloser(src)
	return NewPlayer(context, b)
}

// Close closes the stream. Ths source stream passed by NewPlayer will also be closed.
//
// When closing, the stream owned by the player will also be closed by calling its Close.
//
// This function is concurrent-safe.
func (p *Player) Close() error {
	p.players.removePlayer(p)
	runtime.SetFinalizer(p, nil)
	return p.src.Close()
}

func (p *Player) readToBuffer(length int) error {
	bb := make([]byte, length)
	n, err := p.src.Read(bb)
	if 0 < n {
		p.buf = append(p.buf, bb[:n]...)
	}
	return err
}

func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
	r := make([]int16, lengthInBytes/2)
	for i := 0; i < lengthInBytes/2; i++ {
		r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
		r[i] = int16(float64(r[i]) * p.volume)
	}
	return r
}

func (p *Player) proceed(length int) {
	p.buf = p.buf[length:]
	p.pos += int64(length)
}

func (p *Player) bufferLength() int {
	return len(p.buf)
}

// Play plays the stream.
//
// This function is concurrent-safe.
func (p *Player) Play() error {
	p.players.addPlayer(p)
	return nil
}

// IsPlaying returns boolean indicating whether the player is playing.
//
// This function is concurrent-safe.
func (p *Player) IsPlaying() bool {
	return p.players.hasPlayer(p)
}

// Rewind rewinds the current position to the start.
//
// This function is concurrent-safe.
func (p *Player) Rewind() error {
	return p.Seek(0)
}

// Seek seeks the position with the given offset.
//
// This function is concurrent-safe.
func (p *Player) Seek(offset time.Duration) error {
	p.players.addSeeking(p)
	defer p.players.removeSeeking(p)
	o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
	o &= mask
	p.buf = []byte{}
	pos, err := p.src.Seek(o, io.SeekStart)
	if err != nil {
		return err
	}
	p.pos = pos
	return nil
}

// Pause pauses the playing.
//
// This function is concurrent-safe.
func (p *Player) Pause() error {
	p.players.removePlayer(p)
	return nil
}

// Current returns the current position.
//
// This function is concurrent-safe.
func (p *Player) Current() time.Duration {
	sample := p.pos / bytesPerSample / channelNum
	return time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
}

// Volume returns the current volume of this player [0-1].
func (p *Player) Volume() float64 {
	return p.volume
}

// SetVolume sets the volume of this player.
// volume must be in between 0 and 1. This function panics otherwise.
func (p *Player) SetVolume(volume float64) {
	// The condition must be true when volume is NaN.
	if !(0 <= volume && volume <= 1) {
		panic("audio: volume must be in between 0 and 1")
	}
	p.volume = volume
}
<|endoftext|>


<commit_before>package lzma

import "errors"

// dictionary represents the dictionary for the LZ decompression. It is a ring
// buffer for decoding literals and matches as well as output. The readLen
// gives the number of bytes that can actually be read and full indicates that
// the dictionary is full.
type dictionary struct {
	buffer  []byte
	readLen int
	w       int
	full    bool
}

// reset clears the dictionary. It doesn't change the size of the dictionary.
func (d *dictionary) reset() {
	d.readLen = 0
	d.w = 0
	d.full = false
}

// init initalizes the dictionary to the given size
func (d *dictionary) init(size int) {
	d.buffer = make([]byte, size)
	d.reset()
}

// writeLen returns the number of bytes that can be written into the
// dictionary.
func (d *dictionary) writeLen() int {
	return len(d.buffer) - d.readLen
}

// maxDistance returns the maximum distance that is currently supported.
func (d *dictionary) maxDistance() int {
	if d.full {
		return len(d.buffer)
	}
	return d.w
}

// errDictionaryOverflow indicates that the dictionary will overflow for the
// current write.
var errDictionaryOverflow = errors.New("dictionary will overflow")

// errDistOutOfRange indicates that the distance is out of range.
var errDistOutOfRange = errors.New("distance out of range")

// errLengthOutOfRange indicates that the length is either too large or too
// small.
var errLengthOutOfRange = errors.New("length out of range")

// put puts a byte into the buffer. Note that it doesn't check whether writeLen
// is larger than 1. It assumes that the calling code has done it.
func (d *dictionary) put(b byte) {
	d.buffer[d.w] = b
	d.readLen++
	d.w++
	if d.w >= len(d.buffer) {
		d.full = true
		d.w = 0
	}
}

// putLiteral puts a single literal byte into the dictionary. It checks that
// there is actual space for doing it.
func (d *dictionary) putLiteral(lit byte) error {
	if d.writeLen() < 1 {
		return errDictionaryOverflow
	}
	d.put(lit)
	return nil
}

// get returns the byte at the given distance. Note that the last byte written
// has distance 1.
func (d *dictionary) get(distance int) byte {
	i := d.w - distance
	if i < 0 {
		i += len(d.buffer)
	}
	return d.buffer[i]
}

// copyMatch copies a match. The distance must be in the interval
// [0,maxDistance]. The length must be nonnegative.
func (d *dictionary) copyMatch(distance, length int) error {
	switch {
	case !(0 <= distance && distance <= d.maxDistance()):
		return errDistOutOfRange
	case length < 0:
		return errLengthOutOfRange
	case length > d.writeLen():
		return errDictionaryOverflow
	}
	// can be optimized using copy
	for ; length > 0; length-- {
		d.put(d.get(distance))
	}
	return nil
}

// errDictionaryUnderflow indicates that no bytes can be read from the
// dictionary. Note that the function simply copies data out of the buffer, it
// doesn't add any data to the dictionary.
var errDictionaryUnderflow = errors.New("dictionary underflow")

// Read can be used to access data in the dictionary.
func (d *dictionary) Read(p []byte) (n int, err error) {
	if d.readLen <= 0 {
		return 0, errDictionaryUnderflow
	}
	n = len(p)
	if n > d.readLen {
		n = d.readLen
	}
	for i := 0; i < n; i++ {
		p[i] = d.get(n - i)
	}
	d.readLen -= n
	return n, nil
}
<commit_msg>lzma: removed dictionary.go<commit_after><|endoftext|>


<commit_before>package shared

import (
	"time"
)

type ContainerState struct {
	Status     string                           `json:"status"`
	StatusCode StatusCode                       `json:"status_code"`
	Disk       map[string]ContainerStateDisk    `json:"disk"`
	Memory     ContainerStateMemory             `json:"memory"`
	Network    map[string]ContainerStateNetwork `json:"network"`
	Pid        int64                            `json:"pid"`
	Processes  int64                            `json:"processes"`
}

type ContainerStateDisk struct {
	Usage int64 `json:"usage"`
}

type ContainerStateMemory struct {
	Usage         int64 `json:"usage"`
	UsagePeak     int64 `json:"usage_peak"`
	SwapUsage     int64 `json:"swap_usage"`
	SwapUsagePeak int64 `json:"swap_usage_peak"`
}

type ContainerStateNetwork struct {
	Addresses []ContainerStateNetworkAddress `json:"addresses"`
	Counters  ContainerStateNetworkCounters  `json:"counters"`
	Hwaddr    string                         `json:"hwaddr"`
	HostName  string                         `json:"host_name"`
	Mtu       int                            `json:"mtu"`
	State     string                         `json:"state"`
	Type      string                         `json:"type"`
}

type ContainerStateNetworkAddress struct {
	Family  string `json:"family"`
	Address string `json:"address"`
	Netmask string `json:"netmask"`
	Scope   string `json:"scope"`
}

type ContainerStateNetworkCounters struct {
	BytesReceived   int64 `json:"bytes_received"`
	BytesSent       int64 `json:"bytes_sent"`
	PacketsReceived int64 `json:"packets_received"`
	PacketsSent     int64 `json:"packets_sent"`
}

type ContainerExecControl struct {
	Command string            `json:"command"`
	Args    map[string]string `json:"args"`
}

type SnapshotInfo struct {
	Architecture    string            `json:"architecture"`
	Config          map[string]string `json:"config"`
	CreationDate    time.Time         `json:"created_at"`
	Devices         Devices           `json:"devices"`
	Ephemeral       bool              `json:"ephemeral"`
	ExpandedConfig  map[string]string `json:"expanded_config"`
	ExpandedDevices Devices           `json:"expanded_devices"`
	Name            string            `json:"name"`
	Profiles        []string          `json:"profiles"`
	Stateful        bool              `json:"stateful"`
}

type ContainerInfo struct {
	Architecture    string            `json:"architecture"`
	Config          map[string]string `json:"config"`
	CreationDate    time.Time         `json:"created_at"`
	Devices         Devices           `json:"devices"`
	Ephemeral       bool              `json:"ephemeral"`
	ExpandedConfig  map[string]string `json:"expanded_config"`
	ExpandedDevices Devices           `json:"expanded_devices"`
	Name            string            `json:"name"`
	Profiles        []string          `json:"profiles"`
	Stateful        bool              `json:"stateful"`
	Status          string            `json:"status"`
	StatusCode      StatusCode        `json:"status_code"`
}

func (c ContainerInfo) IsActive() bool {
	switch c.StatusCode {
	case Stopped:
		return false
	case Error:
		return false
	default:
		return true
	}
}

/*
 * BriefContainerState contains a subset of the fields in
 * ContainerState, namely those which a user may update
 */
type BriefContainerInfo struct {
	Name      string            `json:"name"`
	Profiles  []string          `json:"profiles"`
	Config    map[string]string `json:"config"`
	Devices   Devices           `json:"devices"`
	Ephemeral bool              `json:"ephemeral"`
}

func (c *ContainerInfo) Brief() BriefContainerInfo {
	retstate := BriefContainerInfo{Name: c.Name,
		Profiles:  c.Profiles,
		Config:    c.Config,
		Devices:   c.Devices,
		Ephemeral: c.Ephemeral}
	return retstate
}

func (c *ContainerInfo) BriefExpanded() BriefContainerInfo {
	retstate := BriefContainerInfo{Name: c.Name,
		Profiles:  c.Profiles,
		Config:    c.ExpandedConfig,
		Devices:   c.ExpandedDevices,
		Ephemeral: c.Ephemeral}
	return retstate
}

type ContainerAction string

const (
	Stop     ContainerAction = "stop"
	Start    ContainerAction = "start"
	Restart  ContainerAction = "restart"
	Freeze   ContainerAction = "freeze"
	Unfreeze ContainerAction = "unfreeze"
)

type ProfileConfig struct {
	Name        string            `json:"name"`
	Config      map[string]string `json:"config"`
	Description string            `json:"description"`
	Devices     Devices           `json:"devices"`
}
<commit_msg>Add LastUsedDate to ContainerInfo and SnapshotInfo structs<commit_after>package shared

import (
	"time"
)

type ContainerState struct {
	Status     string                           `json:"status"`
	StatusCode StatusCode                       `json:"status_code"`
	Disk       map[string]ContainerStateDisk    `json:"disk"`
	Memory     ContainerStateMemory             `json:"memory"`
	Network    map[string]ContainerStateNetwork `json:"network"`
	Pid        int64                            `json:"pid"`
	Processes  int64                            `json:"processes"`
}

type ContainerStateDisk struct {
	Usage int64 `json:"usage"`
}

type ContainerStateMemory struct {
	Usage         int64 `json:"usage"`
	UsagePeak     int64 `json:"usage_peak"`
	SwapUsage     int64 `json:"swap_usage"`
	SwapUsagePeak int64 `json:"swap_usage_peak"`
}

type ContainerStateNetwork struct {
	Addresses []ContainerStateNetworkAddress `json:"addresses"`
	Counters  ContainerStateNetworkCounters  `json:"counters"`
	Hwaddr    string                         `json:"hwaddr"`
	HostName  string                         `json:"host_name"`
	Mtu       int                            `json:"mtu"`
	State     string                         `json:"state"`
	Type      string                         `json:"type"`
}

type ContainerStateNetworkAddress struct {
	Family  string `json:"family"`
	Address string `json:"address"`
	Netmask string `json:"netmask"`
	Scope   string `json:"scope"`
}

type ContainerStateNetworkCounters struct {
	BytesReceived   int64 `json:"bytes_received"`
	BytesSent       int64 `json:"bytes_sent"`
	PacketsReceived int64 `json:"packets_received"`
	PacketsSent     int64 `json:"packets_sent"`
}

type ContainerExecControl struct {
	Command string            `json:"command"`
	Args    map[string]string `json:"args"`
}

type SnapshotInfo struct {
	Architecture    string            `json:"architecture"`
	Config          map[string]string `json:"config"`
	CreationDate    time.Time         `json:"created_at"`
	Devices         Devices           `json:"devices"`
	Ephemeral       bool              `json:"ephemeral"`
	ExpandedConfig  map[string]string `json:"expanded_config"`
	ExpandedDevices Devices           `json:"expanded_devices"`
	LastUsedDate    time.Time         `json:"last_used_at"`
	Name            string            `json:"name"`
	Profiles        []string          `json:"profiles"`
	Stateful        bool              `json:"stateful"`
}

type ContainerInfo struct {
	Architecture    string            `json:"architecture"`
	Config          map[string]string `json:"config"`
	CreationDate    time.Time         `json:"created_at"`
	Devices         Devices           `json:"devices"`
	Ephemeral       bool              `json:"ephemeral"`
	ExpandedConfig  map[string]string `json:"expanded_config"`
	ExpandedDevices Devices           `json:"expanded_devices"`
	LastUsedDate    time.Time         `json:"last_used_at"`
	Name            string            `json:"name"`
	Profiles        []string          `json:"profiles"`
	Stateful        bool              `json:"stateful"`
	Status          string            `json:"status"`
	StatusCode      StatusCode        `json:"status_code"`
}

func (c ContainerInfo) IsActive() bool {
	switch c.StatusCode {
	case Stopped:
		return false
	case Error:
		return false
	default:
		return true
	}
}

/*
 * BriefContainerState contains a subset of the fields in
 * ContainerState, namely those which a user may update
 */
type BriefContainerInfo struct {
	Name      string            `json:"name"`
	Profiles  []string          `json:"profiles"`
	Config    map[string]string `json:"config"`
	Devices   Devices           `json:"devices"`
	Ephemeral bool              `json:"ephemeral"`
}

func (c *ContainerInfo) Brief() BriefContainerInfo {
	retstate := BriefContainerInfo{Name: c.Name,
		Profiles:  c.Profiles,
		Config:    c.Config,
		Devices:   c.Devices,
		Ephemeral: c.Ephemeral}
	return retstate
}

func (c *ContainerInfo) BriefExpanded() BriefContainerInfo {
	retstate := BriefContainerInfo{Name: c.Name,
		Profiles:  c.Profiles,
		Config:    c.ExpandedConfig,
		Devices:   c.ExpandedDevices,
		Ephemeral: c.Ephemeral}
	return retstate
}

type ContainerAction string

const (
	Stop     ContainerAction = "stop"
	Start    ContainerAction = "start"
	Restart  ContainerAction = "restart"
	Freeze   ContainerAction = "freeze"
	Unfreeze ContainerAction = "unfreeze"
)

type ProfileConfig struct {
	Name        string            `json:"name"`
	Config      map[string]string `json:"config"`
	Description string            `json:"description"`
	Devices     Devices           `json:"devices"`
}
<|endoftext|>


<commit_before>package dal

import (
	"errors"
	"strings"
	"time"
)

import (
	"github.com/jmoiron/sqlx"
)

// Purchase is the primary dal for an item purchased.
type Purchase struct {
	ID         uint64    `json:"id"`
	Name       string    `json:"name"`
	Cost       float64   `json:"cost"`
	TimeBought time.Time `json:"time_bought" db:"time_bought"`
}

// ValidatePurchase validates a purchase before database insertion
func ValidatePurchase(purchase *Purchase) (ok bool, errs []error) {
	errs = make([]error, 0)

	if strings.TrimSpace(purchase.Name) == "" {
		errs = append(errs, errors.New("Purchase must have a name."))
	}

	if purchase.Cost <= 0.0 {
		errs = append(errs, errors.New("Purchase must have a valid cost."))
	}

	if !purchase.TimeBought.Before(time.Now()) {
		errs = append(errs, errors.New("Purchase must have been made in the past."))
	}

	return len(errs) == 0, errs
}

// AddPurchase adds a new a purchase to the database.
func AddPurchase(db *sqlx.DB, purchase *Purchase) error {
	_, err := db.NamedExec(
		"INSERT INTO purchase (name, cost, time_bought) VALUES (:name, :cost, :time_bought)",
		map[string]interface{}{
			"name":        purchase.Name,
			"cost":        purchase.Cost,
			"time_bought": purchase.TimeBought,
		})
	return err
}

// GetPurchases lists all purchases from the database.
func GetPurchases(db *sqlx.DB) ([]Purchase, error) {
	purchases := []Purchase{}
	err := db.Select(&purchases, "SELECT * FROM purchase ORDER BY time_bought DESC")
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

func getPurchasesAfterDate(db *sqlx.DB, date time.Time) ([]Purchase, error) {
	purchases := []Purchase{}
	err := db.Select(&purchases,
		"SELECT * FROM purchase WHERE time_bought > ? ORDER BY time_bought DESC",
		date.Unix())
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

// GetPurchasesAfterMarker lists all purchases from the database made after the
// last marker date, the marker date one month before the current marker date.
func GetPurchasesAfterMarker(db *sqlx.DB) ([]Purchase, error) {
	marker := currentMarkerDay()
	purchases, err := getPurchasesAfterDate(db, marker)
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

// GetPurchase retrieves a purchase by its ID.
func GetPurchase(db *sqlx.DB, byID uint64) (*Purchase, error) {
	purchase := Purchase{}
	err := db.Get(&purchase, "SELECT * FROM purchase WHERE id=?", byID)
	if err != nil {
		return nil, err
	}
	return &purchase, nil
}

// DeletePurchase removes a purchase from the database.
func DeletePurchase(db *sqlx.DB, byID uint64) error {
	_, err := db.NamedExec(
		"DELETE FROM purchase where id=(:id)",
		map[string]interface{}{
			"id": byID,
		})
	return err
}
<commit_msg>re name<commit_after>package dal

import (
	"errors"
	"strings"
	"time"
)

import (
	"github.com/jmoiron/sqlx"
)

// Purchase is the primary dal for an item purchased.
type Purchase struct {
	ID         uint64    `json:"id"`
	Name       string    `json:"name"`
	Cost       float64   `json:"cost"`
	TimeBought time.Time `json:"time_bought" db:"time_bought"`
}

// ValidatePurchase validates a purchase before database insertion
func ValidatePurchase(purchase *Purchase) (ok bool, errs []error) {
	errs = make([]error, 0)

	if strings.TrimSpace(purchase.Name) == "" {
		errs = append(errs, errors.New("Purchase must have a name."))
	}

	if purchase.Cost <= 0.0 {
		errs = append(errs, errors.New("Purchase must have a valid cost."))
	}

	if !purchase.TimeBought.Before(time.Now()) {
		errs = append(errs, errors.New("Purchase must have been made in the past."))
	}

	return len(errs) == 0, errs
}

// AddPurchase adds a new a purchase to the database.
func AddPurchase(db *sqlx.DB, purchase *Purchase) error {
	_, err := db.NamedExec(
		"INSERT INTO purchase (name, cost, time_bought) VALUES (:name, :cost, :time_bought)",
		map[string]interface{}{
			"name":        purchase.Name,
			"cost":        purchase.Cost,
			"time_bought": purchase.TimeBought,
		})
	return err
}

// GetPurchases lists all purchases from the database.
func GetPurchases(db *sqlx.DB) ([]Purchase, error) {
	purchases := []Purchase{}
	err := db.Select(&purchases, "SELECT * FROM purchase ORDER BY time_bought DESC")
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

func getPurchasesAfterDate(db *sqlx.DB, date time.Time) ([]Purchase, error) {
	purchases := []Purchase{}
	err := db.Select(&purchases,
		"SELECT * FROM purchase WHERE time_bought > ? ORDER BY time_bought DESC",
		date.Unix())
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

// GetPurchasesAfterLastMarker lists all purchases from the database made after
// the last marker date, the one one month before the current marker date.
func GetPurchasesAfterLastMarker(db *sqlx.DB) ([]Purchase, error) {
	marker := currentMarkerDay()
	purchases, err := getPurchasesAfterDate(db, marker)
	if err != nil {
		return nil, err
	}
	return purchases, nil
}

// GetPurchase retrieves a purchase by its ID.
func GetPurchase(db *sqlx.DB, byID uint64) (*Purchase, error) {
	purchase := Purchase{}
	err := db.Get(&purchase, "SELECT * FROM purchase WHERE id=?", byID)
	if err != nil {
		return nil, err
	}
	return &purchase, nil
}

// DeletePurchase removes a purchase from the database.
func DeletePurchase(db *sqlx.DB, byID uint64) error {
	_, err := db.NamedExec(
		"DELETE FROM purchase where id=(:id)",
		map[string]interface{}{
			"id": byID,
		})
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan string)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			inFile, _ := os.Open("canales_list.txt")
			defer inFile.Close()
			scanner := bufio.NewScanner(inFile)
			scanner.Split(bufio.ScanLines)

			for scanner.Scan() {
				time.Sleep(time.Second * 1)
				messages = []string{}
				fmt.Println(scanner.Text())
				msgOut <- fmt.Sprintf("# %s\n", scanner.Text())
				_, _, errs := gorequest.New().Get(fmt.Sprintf("%s%s", *remoteService, scanner.Text())).End()
				if errs != nil {
					log.Fatalf("log failed: %v", errs)
				}
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		f, err := os.OpenFile("/all.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgs {
			// fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		f, err := os.OpenFile("/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgOut {
			fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' {
				if strings.Contains(string(msg.Content), "$1") {
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
					if sepIdx == -1 {
						sepIdx = len(msg.Content) - 4
					}

					temp = string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))
					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
				} else {
					temp = ""
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 0, 1, 0, 0}))
					if sepIdx == -1 || sepIdx+5 > len(msg.Content) {
						sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
						if sepIdx == -1 || sepIdx+4 > len(msg.Content) {
							sepIdx = len(msg.Content) - 4
						} else {
							sepIdx = len(msg.Content) - 1
						}
					}
					if sepIdx == -1 {
						sepIdx = len(msg.Content)
					}
					if selectIdx == -1 {
						selectIdx = 0
					}

					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
					messages = append(messages, string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00")))
				}
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 && temp != "" {
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					fmt.Printf("first string ends ----->%#v\n", p)
					newMsg = newMsg[p+1:]
					fmt.Printf("0 newMsg   ----->%#v\n", newMsg)

					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					fmt.Printf("second string ends ---->%#v\n", p)
					newMsg = newMsg[p+1:]
					fmt.Printf("1 newMsg   ----->%#v\n", newMsg)

					t := newMsg.Int16()
					fmt.Printf("vars types numbers ---->%#v\n", t)
					for i := 0; i < t; i++ {
						t = newMsg.Int16()
						fmt.Printf("22 newMsg   ----->%#v\n", newMsg)
					}

					totalVar := newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					for i := 0; i < totalVar; i++ {
						fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
						varLen := newMsg.Int32()
						// aa := newMsg.Next(4)
						// fmt.Printf("aa   -----> %#v\n", aa)
						// fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						// varLen := int(binary.BigEndian.Uint32(aa))
						fmt.Printf("varLen ----->%v\n", varLen)
						fmt.Printf("newMsg   ----->%#v\n", newMsg)
						vars[i] = string(newMsg.Next(varLen))
						fmt.Printf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					}
					// fmt.Printf("2 newMsg   ----->%#v\n", newMsg)

					// idxPdo := strings.Index(string(msg.Content), "pdo_stmt_")
					//
					// if idxPdo != -1 {
					// 	var newMsg proxy.ReadBuf
					// 	// B type allways ends with 0100
					// 	fmt.Printf("msg.Content   ----->%#v\n", msg.Content)
					// 	newMsg = msg.Content[idxPdo+22 : len(msg.Content)-4]
					// 	fmt.Printf("1 newMsg   ----->%#v\n", newMsg)
					// 	totalVar := newMsg.Int16()
					//
					// 	vars := make(map[int]string)
					// 	var varsIdx []int
					// 	for i := 0; i < totalVar; i++ {
					// 		fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
					// 		// varLen := newMsg.Int32()
					// 		aa := newMsg.Next(4)
					// 		fmt.Printf("aa   -----> %#v\n", aa)
					// 		fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
					// 		varLen := int(binary.BigEndian.Uint32(aa))
					// 		fmt.Printf("varLen ----->%v\n", varLen)
					// 		fmt.Printf("newMsg   ----->%#v\n", newMsg)
					// 		vars[i] = string(newMsg.Next(varLen))
					// 		fmt.Printf("vars   ----->%#v\n", vars)
					// 		varsIdx = append(varsIdx, i)
					// 		fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					// 	}
					// 	sort.Sort(sort.Reverse(sort.IntSlice(varsIdx)))
					// 	for _, k := range varsIdx {
					// 		messages = append(messages, strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(newMsg[k+1])), -1))
					// 	}
					// } else {
					// 	messages = append(messages, string(msg.Content[29:len(msg.Content)-4]))
					// }

				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
			fmt.Printf("---------->%#v\n", messages)
			for k, v := range messages {
				msgOut <- fmt.Sprintf("%d. %s\n", k+1, v)
			}
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<commit_msg>Update<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	msgOut := make(chan string)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			inFile, _ := os.Open("canales_list.txt")
			defer inFile.Close()
			scanner := bufio.NewScanner(inFile)
			scanner.Split(bufio.ScanLines)

			for scanner.Scan() {
				time.Sleep(time.Second * 1)
				messages = []string{}
				fmt.Println(scanner.Text())
				msgOut <- fmt.Sprintf("# %s\n", scanner.Text())
				_, _, errs := gorequest.New().Get(fmt.Sprintf("%s%s", *remoteService, scanner.Text())).End()
				if errs != nil {
					log.Fatalf("log failed: %v", errs)
				}
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		f, err := os.OpenFile("/all.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgs {
			// fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		f, err := os.OpenFile("/report.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		for msg := range msgOut {
			fmt.Println(msg)
			_, err := f.WriteString(fmt.Sprintf("%s\n", msg))
			if err != nil {
				log.Fatalf("log failed: %v", err)
			}
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' {
				if strings.Contains(string(msg.Content), "$1") {
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
					if sepIdx == -1 {
						sepIdx = len(msg.Content) - 4
					}

					temp = string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00"))
					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
				} else {
					temp = ""
					selectIdx := strings.Index(string(msg.Content), string([]byte{83, 69, 76, 69, 67, 84, 32}))
					if selectIdx == -1 {
						selectIdx = 0
					}
					sepIdx := strings.Index(string(msg.Content), string([]byte{0, 0, 1, 0, 0}))
					if sepIdx == -1 || sepIdx+5 > len(msg.Content) {
						sepIdx := strings.Index(string(msg.Content), string([]byte{0, 1, 0, 0}))
						if sepIdx == -1 || sepIdx+4 > len(msg.Content) {
							sepIdx = len(msg.Content) - 4
						} else {
							sepIdx = len(msg.Content) - 1
						}
					}
					if sepIdx == -1 {
						sepIdx = len(msg.Content)
					}
					if selectIdx == -1 {
						selectIdx = 0
					}

					fmt.Printf("SEP index ----->%v\n", sepIdx)
					fmt.Printf("SEP len   ----->%v\n", len(msg.Content))
					fmt.Printf("SEP CONT  ----->%v\n", msg.Content)
					messages = append(messages, string(bytes.Trim(msg.Content[selectIdx:sepIdx], "\x00")))
				}
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 && temp != "" {
					var newMsg proxy.ReadBuf
					newMsg = msg.Content

					// The name of the destination portal (an empty string selects the unnamed portal).
					p := bytes.Index(newMsg, []byte{0})
					// remove first string
					fmt.Printf("first string ends ----->%#v\n", p)
					newMsg = newMsg[p+1:]
					fmt.Printf("0 newMsg   ----->%#v\n", newMsg)

					// The name of the source prepared statement (an empty string selects the unnamed prepared statement).
					p = bytes.Index(newMsg, []byte{0})
					// remove second string
					fmt.Printf("second string ends ---->%#v\n", p)
					newMsg = newMsg[p+1:]
					fmt.Printf("1 newMsg   ----->%#v\n", newMsg)

					t := newMsg.Int16()
					fmt.Printf("vars types numbers ---->%#v\n", t)
					for i := 0; i < t; i++ {
						t = newMsg.Int16()
						fmt.Printf("22 newMsg   ----->%#v\n", newMsg)
					}

					totalVar := newMsg.Int16()
					vars := make(map[int]string)
					var varsIdx []int
					for i := 0; i < totalVar; i++ {
						fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
						varLen := newMsg.Int32()
						// aa := newMsg.Next(4)
						// fmt.Printf("aa   -----> %#v\n", aa)
						// fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
						// varLen := int(binary.BigEndian.Uint32(aa))
						fmt.Printf("varLen ----->%v\n", varLen)
						fmt.Printf("newMsg   ----->%#v\n", newMsg)
						if varLen > len(newMsg) {
							varLen = len(newMsg) - 4
						}
						vars[i] = string(newMsg.Next(varLen))
						fmt.Printf("vars   ----->%#v\n", vars)
						varsIdx = append(varsIdx, i)
						fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					}
					// fmt.Printf("2 newMsg   ----->%#v\n", newMsg)

					// idxPdo := strings.Index(string(msg.Content), "pdo_stmt_")
					//
					// if idxPdo != -1 {
					// 	var newMsg proxy.ReadBuf
					// 	// B type allways ends with 0100
					// 	fmt.Printf("msg.Content   ----->%#v\n", msg.Content)
					// 	newMsg = msg.Content[idxPdo+22 : len(msg.Content)-4]
					// 	fmt.Printf("1 newMsg   ----->%#v\n", newMsg)
					// 	totalVar := newMsg.Int16()
					//
					// 	vars := make(map[int]string)
					// 	var varsIdx []int
					// 	for i := 0; i < totalVar; i++ {
					// 		fmt.Printf("2 newMsg   ----->%#v\n", newMsg)
					// 		// varLen := newMsg.Int32()
					// 		aa := newMsg.Next(4)
					// 		fmt.Printf("aa   -----> %#v\n", aa)
					// 		fmt.Printf("aa bits ----->%8b\n", aa[len(aa)-1])
					// 		varLen := int(binary.BigEndian.Uint32(aa))
					// 		fmt.Printf("varLen ----->%v\n", varLen)
					// 		fmt.Printf("newMsg   ----->%#v\n", newMsg)
					// 		vars[i] = string(newMsg.Next(varLen))
					// 		fmt.Printf("vars   ----->%#v\n", vars)
					// 		varsIdx = append(varsIdx, i)
					// 		fmt.Printf("varIdx  ----->%#v\n", varsIdx)
					// 	}
					// 	sort.Sort(sort.Reverse(sort.IntSlice(varsIdx)))
					// 	for _, k := range varsIdx {
					// 		messages = append(messages, strings.Replace(temp, fmt.Sprintf("$%d", k+1), fmt.Sprintf("'%s'", string(newMsg[k+1])), -1))
					// 	}
					// } else {
					// 	messages = append(messages, string(msg.Content[29:len(msg.Content)-4]))
					// }

				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
			fmt.Printf("---------->%#v\n", messages)
			for k, v := range messages {
				msgOut <- fmt.Sprintf("%d. %s\n", k+1, v)
			}
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<|endoftext|>


<commit_before>package v1

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
    testutils "github.com/nebtex/menshend/pkg/utils/test"
    "net/http"
    "net/http/httptest"
    "github.com/emicklei/go-restful"
    "io/ioutil"
    "encoding/json"
    "os"
    vault "github.com/hashicorp/vault/api"
    mutils "github.com/nebtex/menshend/pkg/utils"
)

func listServices(c C, path string) []ClientServiceResource {
    testutils.CleanVault()
    testutils.PopulateVault()
    httpReq, err := http.NewRequest("GET", path, nil)
    httpReq.Header.Set("Content-Type", "application/json")
    c.So(err, ShouldBeNil)
    httpReq.Header.Add("X-Vault-Token", "myroot")
    httpWriter := httptest.NewRecorder()
    wsContainer := restful.NewContainer()
    s := ClientServiceResource{}
    s.Register(wsContainer)
    wsContainer.ServeHTTP(httpWriter, httpReq)
    jsres, err := ioutil.ReadAll(httpWriter.Body)
    c.So(err, ShouldBeNil)
    ret := []ClientServiceResource{}
    err = json.Unmarshal(jsres, &ret)
    c.So(err, ShouldBeNil)
    return ret
}

func Test_ListClientService(t *testing.T) {
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))
    Convey("get by role", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?subdomain=gitlab.&role=ml-team")
        So(len(ret), ShouldEqual, 1)
    })
    Convey("get by role", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?role=ml-team")
        So(len(ret), ShouldEqual, 5)
    })
    Convey("get by subdomain", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?subdomain=redis.")
        So(len(ret), ShouldEqual, 2)
    })
    Convey("get  all the services", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices")
        So(len(ret), ShouldEqual, 8)
    })
}

<commit_msg>fix travis tests<commit_after>package v1

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
    testutils "github.com/nebtex/menshend/pkg/utils/test"
    "net/http"
    "net/http/httptest"
    "github.com/emicklei/go-restful"
    "io/ioutil"
    "encoding/json"
    "os"
    vault "github.com/hashicorp/vault/api"
    mutils "github.com/nebtex/menshend/pkg/utils"
)

func listServices(c C, path string) []ClientServiceResource {
    testutils.CleanVault()
    testutils.PopulateVault()
    httpReq, err := http.NewRequest("GET", path, nil)
    httpReq.Header.Set("Content-Type", "application/json")
    c.So(err, ShouldBeNil)
    httpReq.Header.Add("X-Vault-Token", "myroot")
    httpWriter := httptest.NewRecorder()
    wsContainer := restful.NewContainer()
    s := ClientServiceResource{}
    s.Register(wsContainer)
    wsContainer.ServeHTTP(httpWriter, httpReq)
    jsres, err := ioutil.ReadAll(httpWriter.Body)
    c.So(err, ShouldBeNil)
    ret := []ClientServiceResource{}
    err = json.Unmarshal(jsres, &ret)
    c.So(err, ShouldBeNil)
    return ret
}

func Test_ListClientService(t *testing.T) {
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))
    testutils.CleanVault()

    testutils.PopulateVault()

    Convey("get by role", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?subdomain=gitlab.&role=ml-team")
        So(len(ret), ShouldEqual, 1)
    })
    Convey("get by role", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?role=ml-team")
        So(len(ret), ShouldEqual, 5)
    })
    Convey("get by subdomain", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices?subdomain=redis.")
        So(len(ret), ShouldEqual, 2)
    })
    Convey("get  all the services", t, func(c C) {
        ret:=listServices(c, "/v1/clientServices")
        So(len(ret), ShouldEqual, 8)
    })
}

<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package aws

import (
	"sync"

	"k8s.io/klog"

	"k8s.io/apimachinery/pkg/util/sets"
	awscredentialprovider "k8s.io/kubernetes/pkg/credentialprovider/aws"
)

// wellKnownRegions is the complete list of regions known to the AWS cloudprovider
// and credentialprovider.
var wellKnownRegions = [...]string{
	// from `aws ec2 describe-regions --region us-east-1 --query Regions[].RegionName | sort`
	"ap-northeast-1",
	"ap-northeast-2",
	"ap-northeast-3",
	"ap-south-1",
	"ap-southeast-1",
	"ap-southeast-2",
	"ca-central-1",
	"eu-central-1",
	"eu-west-1",
	"eu-west-2",
	"eu-west-3",
	"sa-east-1",
	"us-east-1",
	"us-east-2",
	"us-west-1",
	"us-west-2",

	// these are not registered in many / most accounts
	"cn-north-1",
	"cn-northwest-1",
	"us-gov-west-1",
}

// awsRegionsMutex protects awsRegions
var awsRegionsMutex sync.Mutex

// awsRegions is a set of recognized regions
var awsRegions sets.String

// recognizeRegion is called for each AWS region we know about.
// It currently registers a credential provider for that region.
// There are two paths to discovering a region:
//  * we hard-code some well-known regions
//  * if a region is discovered from instance metadata, we add that
func recognizeRegion(region string) {
	awsRegionsMutex.Lock()
	defer awsRegionsMutex.Unlock()

	if awsRegions == nil {
		awsRegions = sets.NewString()
	}

	if awsRegions.Has(region) {
		klog.V(6).Infof("found AWS region %q again - ignoring", region)
		return
	}

	klog.V(4).Infof("found AWS region %q", region)

	awscredentialprovider.RegisterCredentialsProvider(region)

	awsRegions.Insert(region)
}

// recognizeWellKnownRegions calls RecognizeRegion on each WellKnownRegion
func recognizeWellKnownRegions() {
	for _, region := range wellKnownRegions {
		recognizeRegion(region)
	}
}

// isRegionValid checks if the region is in the set of known regions
func isRegionValid(region string) bool {
	awsRegionsMutex.Lock()
	defer awsRegionsMutex.Unlock()

	return awsRegions.Has(region)
}
<commit_msg>Remove aws cred provider dep on cloud provider<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package aws

import (
	"sync"

	"k8s.io/klog"

	"k8s.io/apimachinery/pkg/util/sets"
)

// wellKnownRegions is the complete list of regions known to the AWS cloudprovider
// and credentialprovider.
var wellKnownRegions = [...]string{
	// from `aws ec2 describe-regions --region us-east-1 --query Regions[].RegionName | sort`
	"ap-northeast-1",
	"ap-northeast-2",
	"ap-northeast-3",
	"ap-south-1",
	"ap-southeast-1",
	"ap-southeast-2",
	"ca-central-1",
	"eu-central-1",
	"eu-west-1",
	"eu-west-2",
	"eu-west-3",
	"sa-east-1",
	"us-east-1",
	"us-east-2",
	"us-west-1",
	"us-west-2",

	// these are not registered in many / most accounts
	"cn-north-1",
	"cn-northwest-1",
	"us-gov-west-1",
}

// awsRegionsMutex protects awsRegions
var awsRegionsMutex sync.Mutex

// awsRegions is a set of recognized regions
var awsRegions sets.String

// recognizeRegion is called for each AWS region we know about.
// It currently registers a credential provider for that region.
// There are two paths to discovering a region:
//  * we hard-code some well-known regions
//  * if a region is discovered from instance metadata, we add that
func recognizeRegion(region string) {
	awsRegionsMutex.Lock()
	defer awsRegionsMutex.Unlock()

	if awsRegions == nil {
		awsRegions = sets.NewString()
	}

	if awsRegions.Has(region) {
		klog.V(6).Infof("found AWS region %q again - ignoring", region)
		return
	}

	klog.V(4).Infof("found AWS region %q", region)

	awsRegions.Insert(region)
}

// recognizeWellKnownRegions calls RecognizeRegion on each WellKnownRegion
func recognizeWellKnownRegions() {
	for _, region := range wellKnownRegions {
		recognizeRegion(region)
	}
}

// isRegionValid checks if the region is in the set of known regions
func isRegionValid(region string) bool {
	awsRegionsMutex.Lock()
	defer awsRegionsMutex.Unlock()

	return awsRegions.Has(region)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

import (
	"fmt"
	"strings"
	"time"

	"github.com/spf13/pflag"

	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/wait"
	genericoptions "k8s.io/apiserver/pkg/server/options"
	versionedinformers "k8s.io/client-go/informers"
	"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
	authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
)

// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
type BuiltInAuthorizationOptions struct {
	Modes                       []string
	PolicyFile                  string
	WebhookConfigFile           string
	WebhookVersion              string
	WebhookCacheAuthorizedTTL   time.Duration
	WebhookCacheUnauthorizedTTL time.Duration
	// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
	// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
	// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
	WebhookRetryBackoff *wait.Backoff
}

// NewBuiltInAuthorizationOptions create a BuiltInAuthorizationOptions with default value
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
	return &BuiltInAuthorizationOptions{
		Modes:                       []string{authzmodes.ModeAlwaysAllow},
		WebhookVersion:              "v1beta1",
		WebhookCacheAuthorizedTTL:   5 * time.Minute,
		WebhookCacheUnauthorizedTTL: 30 * time.Second,
		WebhookRetryBackoff:         genericoptions.DefaultAuthWebhookRetryBackoff(),
	}
}

// Validate checks invalid config combination
func (o *BuiltInAuthorizationOptions) Validate() []error {
	if o == nil {
		return nil
	}
	var allErrors []error

	if len(o.Modes) == 0 {
		allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
	}

	modes := sets.NewString(o.Modes...)
	for _, mode := range o.Modes {
		if !authzmodes.IsValidAuthorizationMode(mode) {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode %q is not a valid mode", mode))
		}
		if mode == authzmodes.ModeABAC && o.PolicyFile == "" {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode ABAC's authorization policy file not passed"))
		}
		if mode == authzmodes.ModeWebhook && o.WebhookConfigFile == "" {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode Webhook's authorization config file not passed"))
		}
	}

	if o.PolicyFile != "" && !modes.Has(authzmodes.ModeABAC) {
		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-policy-file without mode ABAC"))
	}

	if o.WebhookConfigFile != "" && !modes.Has(authzmodes.ModeWebhook) {
		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-webhook-config-file without mode Webhook"))
	}

	if len(o.Modes) != len(modes.List()) {
		allErrors = append(allErrors, fmt.Errorf("authorization-mode %q has mode specified more than once", o.Modes))
	}

	if o.WebhookRetryBackoff != nil && o.WebhookRetryBackoff.Steps <= 0 {
		allErrors = append(allErrors, fmt.Errorf("number of webhook retry attempts must be greater than 0, but is: %d", o.WebhookRetryBackoff.Steps))
	}

	return allErrors
}

// AddFlags returns flags of authorization for a API Server
func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringSliceVar(&o.Modes, "authorization-mode", o.Modes, ""+
		"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
		strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")

	fs.StringVar(&o.PolicyFile, "authorization-policy-file", o.PolicyFile, ""+
		"File with authorization policy in json line by line format, used with --authorization-mode=ABAC, on the secure port.")

	fs.StringVar(&o.WebhookConfigFile, "authorization-webhook-config-file", o.WebhookConfigFile, ""+
		"File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "+
		"The API server will query the remote service to determine access on the API server's secure port.")

	fs.StringVar(&o.WebhookVersion, "authorization-webhook-version", o.WebhookVersion, ""+
		"The API version of the authorization.k8s.io SubjectAccessReview to send to and expect from the webhook.")

	fs.DurationVar(&o.WebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl",
		o.WebhookCacheAuthorizedTTL,
		"The duration to cache 'authorized' responses from the webhook authorizer.")

	fs.DurationVar(&o.WebhookCacheUnauthorizedTTL,
		"authorization-webhook-cache-unauthorized-ttl", o.WebhookCacheUnauthorizedTTL,
		"The duration to cache 'unauthorized' responses from the webhook authorizer.")
}

// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.Config {
	return authorizer.Config{
		AuthorizationModes:          o.Modes,
		PolicyFile:                  o.PolicyFile,
		WebhookConfigFile:           o.WebhookConfigFile,
		WebhookVersion:              o.WebhookVersion,
		WebhookCacheAuthorizedTTL:   o.WebhookCacheAuthorizedTTL,
		WebhookCacheUnauthorizedTTL: o.WebhookCacheUnauthorizedTTL,
		VersionedInformerFactory:    versionedInformerFactory,
		WebhookRetryBackoff:         o.WebhookRetryBackoff,
	}
}
<commit_msg>cleanup: use sets.Len() insead of len(sets.List())<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

import (
	"fmt"
	"strings"
	"time"

	"github.com/spf13/pflag"

	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/wait"
	genericoptions "k8s.io/apiserver/pkg/server/options"
	versionedinformers "k8s.io/client-go/informers"
	"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
	authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
)

// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
type BuiltInAuthorizationOptions struct {
	Modes                       []string
	PolicyFile                  string
	WebhookConfigFile           string
	WebhookVersion              string
	WebhookCacheAuthorizedTTL   time.Duration
	WebhookCacheUnauthorizedTTL time.Duration
	// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
	// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
	// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
	WebhookRetryBackoff *wait.Backoff
}

// NewBuiltInAuthorizationOptions create a BuiltInAuthorizationOptions with default value
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
	return &BuiltInAuthorizationOptions{
		Modes:                       []string{authzmodes.ModeAlwaysAllow},
		WebhookVersion:              "v1beta1",
		WebhookCacheAuthorizedTTL:   5 * time.Minute,
		WebhookCacheUnauthorizedTTL: 30 * time.Second,
		WebhookRetryBackoff:         genericoptions.DefaultAuthWebhookRetryBackoff(),
	}
}

// Validate checks invalid config combination
func (o *BuiltInAuthorizationOptions) Validate() []error {
	if o == nil {
		return nil
	}
	var allErrors []error

	if len(o.Modes) == 0 {
		allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
	}

	modes := sets.NewString(o.Modes...)
	for _, mode := range o.Modes {
		if !authzmodes.IsValidAuthorizationMode(mode) {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode %q is not a valid mode", mode))
		}
		if mode == authzmodes.ModeABAC && o.PolicyFile == "" {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode ABAC's authorization policy file not passed"))
		}
		if mode == authzmodes.ModeWebhook && o.WebhookConfigFile == "" {
			allErrors = append(allErrors, fmt.Errorf("authorization-mode Webhook's authorization config file not passed"))
		}
	}

	if o.PolicyFile != "" && !modes.Has(authzmodes.ModeABAC) {
		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-policy-file without mode ABAC"))
	}

	if o.WebhookConfigFile != "" && !modes.Has(authzmodes.ModeWebhook) {
		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-webhook-config-file without mode Webhook"))
	}

	if len(o.Modes) != modes.Len() {
		allErrors = append(allErrors, fmt.Errorf("authorization-mode %q has mode specified more than once", o.Modes))
	}

	if o.WebhookRetryBackoff != nil && o.WebhookRetryBackoff.Steps <= 0 {
		allErrors = append(allErrors, fmt.Errorf("number of webhook retry attempts must be greater than 0, but is: %d", o.WebhookRetryBackoff.Steps))
	}

	return allErrors
}

// AddFlags returns flags of authorization for a API Server
func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringSliceVar(&o.Modes, "authorization-mode", o.Modes, ""+
		"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
		strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")

	fs.StringVar(&o.PolicyFile, "authorization-policy-file", o.PolicyFile, ""+
		"File with authorization policy in json line by line format, used with --authorization-mode=ABAC, on the secure port.")

	fs.StringVar(&o.WebhookConfigFile, "authorization-webhook-config-file", o.WebhookConfigFile, ""+
		"File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "+
		"The API server will query the remote service to determine access on the API server's secure port.")

	fs.StringVar(&o.WebhookVersion, "authorization-webhook-version", o.WebhookVersion, ""+
		"The API version of the authorization.k8s.io SubjectAccessReview to send to and expect from the webhook.")

	fs.DurationVar(&o.WebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl",
		o.WebhookCacheAuthorizedTTL,
		"The duration to cache 'authorized' responses from the webhook authorizer.")

	fs.DurationVar(&o.WebhookCacheUnauthorizedTTL,
		"authorization-webhook-cache-unauthorized-ttl", o.WebhookCacheUnauthorizedTTL,
		"The duration to cache 'unauthorized' responses from the webhook authorizer.")
}

// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.Config {
	return authorizer.Config{
		AuthorizationModes:          o.Modes,
		PolicyFile:                  o.PolicyFile,
		WebhookConfigFile:           o.WebhookConfigFile,
		WebhookVersion:              o.WebhookVersion,
		WebhookCacheAuthorizedTTL:   o.WebhookCacheAuthorizedTTL,
		WebhookCacheUnauthorizedTTL: o.WebhookCacheUnauthorizedTTL,
		VersionedInformerFactory:    versionedInformerFactory,
		WebhookRetryBackoff:         o.WebhookRetryBackoff,
	}
}
<|endoftext|>


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

package installer

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/fsouza/go-dockerclient"
	"github.com/tsuru/tsuru-client/tsuru/admin"
	tclient "github.com/tsuru/tsuru-client/tsuru/client"
	"github.com/tsuru/tsuru/cmd"
)

var defaultTsuruAPIPort = 8080

type ComponentsConfig struct {
	InstallDashboard bool   `yaml:"install-dashboard,omitempty"`
	TargetName       string `yaml:"-"`
	RootUserEmail    string `yaml:"-"`
	RootUserPassword string `yaml:"-"`
	Tsuru            tsuruComponent
}

type tsuruComponent struct {
	Config map[string]interface{}
}

type TsuruAPI struct{}

type iaasConfig struct {
	Dockermachine iaasConfigInternal `yaml:"dockermachine,omitempty"`
}

type iaasConfigInternal struct {
	CaPath              string           `yaml:"ca-path,omitempty"`
	InsecureRegistry    string           `yaml:"insecure-registry,omitempty"`
	DockerStorageDriver string           `yaml:"docker-storage-driver,omitempty"`
	DockerInstallURL    string           `yaml:"docker-install-url,omitempty"`
	DockerFlags         string           `yaml:"docker-flags,omitempty"`
	Driver              iaasConfigDriver `yaml:"driver,omitempty"`
}

type iaasConfigDriver struct {
	Name    string                 `yaml:"name,omitempty"`
	Options map[string]interface{} `yaml:"options,omitempty"`
}

func (c *TsuruAPI) setupRootUser(cluster ServiceCluster, email, password string) error {
	cmd := []string{"tsurud", "root-user-create", email}
	passwordConfirmation := strings.NewReader(fmt.Sprintf("%s\n%s\n", password, password))
	startOpts := docker.StartExecOptions{
		InputStream:  passwordConfirmation,
		Detach:       false,
		OutputStream: os.Stdout,
		ErrorStream:  os.Stderr,
		RawTerminal:  true,
	}
	return cluster.ServiceExec("tsuru_tsuru", cmd, startOpts)
}

type Bootstraper interface {
	Bootstrap(opts BoostrapOptions) error
}

type BoostrapOptions struct {
	Login            string
	Password         string
	Target           string
	TargetName       string
	NodesToRegister  []string
	NodesToCreate    int
	NodesParams      map[string][]interface{}
	InstallDashboard bool
}

type TsuruBoostraper struct {
	manager *cmd.Manager
	client  *cmd.Client
	context cmd.Context
}

func (s *TsuruBoostraper) Bootstrap(opts BoostrapOptions) error {
	manager := cmd.BuildBaseManager("setup-client", "0.0.0", "", nil)
	for _, c := range cmd.ExtraCmds() {
		manager.Register(c)
	}
	s.manager = manager
	s.client = cmd.NewClient(&http.Client{}, nil, s.manager)
	s.context = cmd.Context{
		Args:   []string{opts.TargetName, opts.Target},
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	s.context.RawOutput()
	err := s.addTarget()
	if err != nil {
		return err
	}
	err = s.login(opts.Login, opts.Password)
	if err != nil {
		return err
	}
	err = s.addPool("theonepool")
	if err != nil {
		return err
	}
	err = s.registerNodes("theonepool", opts.NodesToRegister)
	if err != nil {
		return err
	}
	err = s.createNodes("theonepool", opts.NodesToCreate, opts.NodesParams)
	if err != nil {
		return err
	}
	if opts.InstallDashboard {
		err = s.addPlatform("python")
		if err != nil {
			return err
		}
		err = s.addTeam("admin")
		if err != nil {
			return err
		}
		err = s.installDashboard()
	}
	return err
}

func (s *TsuruBoostraper) addTarget() error {
	fmt.Fprintln(os.Stdout, "adding target")
	targetadd := s.manager.Commands["target-add"]
	t, _ := targetadd.(cmd.FlaggedCommand)
	err := t.Flags().Parse(true, []string{"-s"})
	if err != nil {
		return err
	}
	err = t.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to add tsuru target: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) login(login, password string) error {
	fmt.Fprintf(os.Stdout, "log in with default user: %s ", login)
	logincmd := s.manager.Commands["login"]
	s.context.Args = []string{login}
	s.context.Stdin = strings.NewReader(fmt.Sprintf("%s\n", password))
	err := logincmd.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to login to tsuru: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) addPool(pool string) error {
	s.context.Args = []string{pool}
	s.context.Stdin = nil
	fmt.Fprintln(os.Stdout, "adding pool")
	poolAdd := admin.AddPoolToSchedulerCmd{}
	err := poolAdd.Flags().Parse(true, []string{"-d", "-p"})
	if err != nil {
		return err
	}
	err = poolAdd.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to add pool: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) registerNodes(pool string, nodes []string) error {
	nodeAdd := admin.AddNodeCmd{}
	err := nodeAdd.Flags().Parse(true, []string{"--register"})
	if err != nil {
		return err
	}
	for _, n := range nodes {
		fmt.Printf("adding node %s\n", n)
		s.context.Args = []string{"docker", fmt.Sprintf("address=%s", n), fmt.Sprintf("pool=%s", pool)}
		err = nodeAdd.Run(&s.context, s.client)
		if err != nil {
			return fmt.Errorf("failed to register node: %s", err)
		}
	}
	return nil
}

func (s *TsuruBoostraper) createNodes(pool string, nodes int, nodesParams map[string][]interface{}) error {
	nodeAdd := admin.AddNodeCmd{}
	for i := 0; i < nodes; i++ {
		fmt.Printf("creating node %d/%d...\n", i+1, nodes)
		s.context.Args = []string{"docker", "iaas=dockermachine", fmt.Sprintf("pool=%s", pool)}
		for k, v := range nodesParams {
			idx := i % len(v)
			s.context.Args = append(s.context.Args, fmt.Sprintf("%s=%s", k, v[idx]))
		}
		err := nodeAdd.Run(&s.context, s.client)
		if err != nil {
			return fmt.Errorf("failed to create node: %s", err)
		}
	}
	return nil
}

func (s *TsuruBoostraper) addPlatform(platform string) error {
	fmt.Fprintln(os.Stdout, "adding platform")
	platformAdd := admin.PlatformAdd{}
	s.context.Args = []string{platform}
	err := mcnutils.WaitFor(func() bool {
		return platformAdd.Run(&s.context, s.client) == nil
	})
	if err != nil {
		return fmt.Errorf("failed to add platform: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) addTeam(team string) error {
	s.context.Args = []string{team}
	fmt.Fprintln(os.Stdout, "adding team")
	teamCreate := tclient.TeamCreate{}
	err := teamCreate.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to create admin team: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) installDashboard() error {
	fmt.Fprintln(os.Stdout, "adding dashboard")
	s.context.Args = []string{"tsuru-dashboard", "python"}
	createDashboard := tclient.AppCreate{}
	err := createDashboard.Flags().Parse(true, []string{"-t", "admin"})
	if err != nil {
		return err
	}
	err = createDashboard.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to create dashboard app: %s", err)
	}
	s.context.Args = []string{}
	fmt.Fprintln(os.Stdout, "deploying dashboard")
	deployDashboard := tclient.AppDeploy{}
	deployFlags := []string{"-a", "tsuru-dashboard", "-i", "tsuru/dashboard"}
	err = deployDashboard.Flags().Parse(true, deployFlags)
	if err != nil {
		return err
	}
	err = deployDashboard.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to deploy dashboard app: %s", err)
	}
	return nil
}

func (c *TsuruAPI) Uninstall(installation string) error {
	manager := cmd.BuildBaseManager("uninstall-client", "0.0.0", "", nil)
	for _, c := range cmd.ExtraCmds() {
		manager.Register(c)
	}
	fmt.Fprint(os.Stdout, "removing target\n")
	client := cmd.NewClient(&http.Client{}, nil, manager)
	context := cmd.Context{
		Args:   []string{installation},
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	targetrm := manager.Commands["target-remove"]
	return targetrm.Run(&context, client)
}
<commit_msg>installer: enable setting debug mode on iaas<commit_after>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package installer

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/fsouza/go-dockerclient"
	"github.com/tsuru/tsuru-client/tsuru/admin"
	tclient "github.com/tsuru/tsuru-client/tsuru/client"
	"github.com/tsuru/tsuru/cmd"
)

var defaultTsuruAPIPort = 8080

type ComponentsConfig struct {
	InstallDashboard bool   `yaml:"install-dashboard,omitempty"`
	TargetName       string `yaml:"-"`
	RootUserEmail    string `yaml:"-"`
	RootUserPassword string `yaml:"-"`
	Tsuru            tsuruComponent
}

type tsuruComponent struct {
	Config map[string]interface{}
}

type TsuruAPI struct{}

type iaasConfig struct {
	Dockermachine iaasConfigInternal `yaml:"dockermachine,omitempty"`
}

type iaasConfigInternal struct {
	CaPath              string           `yaml:"ca-path,omitempty"`
	InsecureRegistry    string           `yaml:"insecure-registry,omitempty"`
	DockerStorageDriver string           `yaml:"docker-storage-driver,omitempty"`
	DockerInstallURL    string           `yaml:"docker-install-url,omitempty"`
	DockerFlags         string           `yaml:"docker-flags,omitempty"`
	Driver              iaasConfigDriver `yaml:"driver,omitempty"`
	Debug               bool             `yaml:"debug,omitempty"`
}

type iaasConfigDriver struct {
	Name    string                 `yaml:"name,omitempty"`
	Options map[string]interface{} `yaml:"options,omitempty"`
}

func (c *TsuruAPI) setupRootUser(cluster ServiceCluster, email, password string) error {
	cmd := []string{"tsurud", "root-user-create", email}
	passwordConfirmation := strings.NewReader(fmt.Sprintf("%s\n%s\n", password, password))
	startOpts := docker.StartExecOptions{
		InputStream:  passwordConfirmation,
		Detach:       false,
		OutputStream: os.Stdout,
		ErrorStream:  os.Stderr,
		RawTerminal:  true,
	}
	return cluster.ServiceExec("tsuru_tsuru", cmd, startOpts)
}

type Bootstraper interface {
	Bootstrap(opts BoostrapOptions) error
}

type BoostrapOptions struct {
	Login            string
	Password         string
	Target           string
	TargetName       string
	NodesToRegister  []string
	NodesToCreate    int
	NodesParams      map[string][]interface{}
	InstallDashboard bool
}

type TsuruBoostraper struct {
	manager *cmd.Manager
	client  *cmd.Client
	context cmd.Context
}

func (s *TsuruBoostraper) Bootstrap(opts BoostrapOptions) error {
	manager := cmd.BuildBaseManager("setup-client", "0.0.0", "", nil)
	for _, c := range cmd.ExtraCmds() {
		manager.Register(c)
	}
	s.manager = manager
	s.client = cmd.NewClient(&http.Client{}, nil, s.manager)
	s.context = cmd.Context{
		Args:   []string{opts.TargetName, opts.Target},
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	s.context.RawOutput()
	err := s.addTarget()
	if err != nil {
		return err
	}
	err = s.login(opts.Login, opts.Password)
	if err != nil {
		return err
	}
	err = s.addPool("theonepool")
	if err != nil {
		return err
	}
	err = s.registerNodes("theonepool", opts.NodesToRegister)
	if err != nil {
		return err
	}
	err = s.createNodes("theonepool", opts.NodesToCreate, opts.NodesParams)
	if err != nil {
		return err
	}
	if opts.InstallDashboard {
		err = s.addPlatform("python")
		if err != nil {
			return err
		}
		err = s.addTeam("admin")
		if err != nil {
			return err
		}
		err = s.installDashboard()
	}
	return err
}

func (s *TsuruBoostraper) addTarget() error {
	fmt.Fprintln(os.Stdout, "adding target")
	targetadd := s.manager.Commands["target-add"]
	t, _ := targetadd.(cmd.FlaggedCommand)
	err := t.Flags().Parse(true, []string{"-s"})
	if err != nil {
		return err
	}
	err = t.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to add tsuru target: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) login(login, password string) error {
	fmt.Fprintf(os.Stdout, "log in with default user: %s ", login)
	logincmd := s.manager.Commands["login"]
	s.context.Args = []string{login}
	s.context.Stdin = strings.NewReader(fmt.Sprintf("%s\n", password))
	err := logincmd.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to login to tsuru: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) addPool(pool string) error {
	s.context.Args = []string{pool}
	s.context.Stdin = nil
	fmt.Fprintln(os.Stdout, "adding pool")
	poolAdd := admin.AddPoolToSchedulerCmd{}
	err := poolAdd.Flags().Parse(true, []string{"-d", "-p"})
	if err != nil {
		return err
	}
	err = poolAdd.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to add pool: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) registerNodes(pool string, nodes []string) error {
	nodeAdd := admin.AddNodeCmd{}
	err := nodeAdd.Flags().Parse(true, []string{"--register"})
	if err != nil {
		return err
	}
	for _, n := range nodes {
		fmt.Printf("adding node %s\n", n)
		s.context.Args = []string{"docker", fmt.Sprintf("address=%s", n), fmt.Sprintf("pool=%s", pool)}
		err = nodeAdd.Run(&s.context, s.client)
		if err != nil {
			return fmt.Errorf("failed to register node: %s", err)
		}
	}
	return nil
}

func (s *TsuruBoostraper) createNodes(pool string, nodes int, nodesParams map[string][]interface{}) error {
	nodeAdd := admin.AddNodeCmd{}
	for i := 0; i < nodes; i++ {
		fmt.Printf("creating node %d/%d...\n", i+1, nodes)
		s.context.Args = []string{"docker", "iaas=dockermachine", fmt.Sprintf("pool=%s", pool)}
		for k, v := range nodesParams {
			idx := i % len(v)
			s.context.Args = append(s.context.Args, fmt.Sprintf("%s=%s", k, v[idx]))
		}
		err := nodeAdd.Run(&s.context, s.client)
		if err != nil {
			return fmt.Errorf("failed to create node: %s", err)
		}
	}
	return nil
}

func (s *TsuruBoostraper) addPlatform(platform string) error {
	fmt.Fprintln(os.Stdout, "adding platform")
	platformAdd := admin.PlatformAdd{}
	s.context.Args = []string{platform}
	err := mcnutils.WaitFor(func() bool {
		return platformAdd.Run(&s.context, s.client) == nil
	})
	if err != nil {
		return fmt.Errorf("failed to add platform: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) addTeam(team string) error {
	s.context.Args = []string{team}
	fmt.Fprintln(os.Stdout, "adding team")
	teamCreate := tclient.TeamCreate{}
	err := teamCreate.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to create admin team: %s", err)
	}
	return nil
}

func (s *TsuruBoostraper) installDashboard() error {
	fmt.Fprintln(os.Stdout, "adding dashboard")
	s.context.Args = []string{"tsuru-dashboard", "python"}
	createDashboard := tclient.AppCreate{}
	err := createDashboard.Flags().Parse(true, []string{"-t", "admin"})
	if err != nil {
		return err
	}
	err = createDashboard.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to create dashboard app: %s", err)
	}
	s.context.Args = []string{}
	fmt.Fprintln(os.Stdout, "deploying dashboard")
	deployDashboard := tclient.AppDeploy{}
	deployFlags := []string{"-a", "tsuru-dashboard", "-i", "tsuru/dashboard"}
	err = deployDashboard.Flags().Parse(true, deployFlags)
	if err != nil {
		return err
	}
	err = deployDashboard.Run(&s.context, s.client)
	if err != nil {
		return fmt.Errorf("failed to deploy dashboard app: %s", err)
	}
	return nil
}

func (c *TsuruAPI) Uninstall(installation string) error {
	manager := cmd.BuildBaseManager("uninstall-client", "0.0.0", "", nil)
	for _, c := range cmd.ExtraCmds() {
		manager.Register(c)
	}
	fmt.Fprint(os.Stdout, "removing target\n")
	client := cmd.NewClient(&http.Client{}, nil, manager)
	context := cmd.Context{
		Args:   []string{installation},
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	targetrm := manager.Commands["target-remove"]
	return targetrm.Run(&context, client)
}
<|endoftext|>