<commit_before>package fsutil

import (
	"errors"
	"github.com/Symantec/Dominator/lib/log"
	"hash"
	"io"
	"os"
	"time"
)

var (
	ErrorChecksumMismatch = errors.New("checksum mismatch")
)

// CopyToFile will create a new file, write length bytes from reader to the
// file and then atomically renames the file to destFilename. If there are any
// errors, then destFilename is unchanged.
func CopyToFile(destFilename string, perm os.FileMode, reader io.Reader,
	length uint64) error {
	return copyToFile(destFilename, perm, reader, length)
}

// ForceLink creates newname as a hard link to the oldname file. It first
// attempts to link using os.Link. If the first attempt fails due to
// a permission error, it blindly calls MakeMutable and then retries. If the
// first attempt fails due to newname existing, it blindly removes it and then
// retries.
func ForceLink(oldname, newname string) error {
	return forceLink(oldname, newname)
}

// ForceRemove removes the named file or directory. It first attempts to remove
// using os.Remove and that fails, it blindly calls MakeMutable and then
// retries.
func ForceRemove(name string) error {
	return forceRemove(name)
}

// ForceRemoveAll removes path and any children it contains. It first attempts
// to remove using os.RemoveAll and that fails, it blindly calls MakeMutable and
// then retries.
func ForceRemoveAll(path string) error {
	return forceRemoveAll(path)
}

// ForceRename renames (moves) a file. It first attempts to rename using
// os.Rename and if that fails due to a permission error, it blindly calls
// MakeMutable and then retries. If it fails because newpath is a directory, it
// calls ForceRemoveAll(newpath) and tries again.
func ForceRename(oldpath, newpath string) error {
	return forceRename(oldpath, newpath)
}

// LoadLines will open a file and read lines from it. Comment lines (i.e. lines
// beginning with '#') are skipped.
func LoadLines(filename string) ([]string, error) {
	return loadLines(filename)
}

// MakeMutable attempts to remove the "immutable" and "append-only" ext2
// file-system attributes for one or more files. It is equivalent to calling the
// command-line programme "chattr -ai pathname...".
func MakeMutable(pathname ...string) error {
	return makeMutable(pathname...)
}

// WaitFile waits for the file given by pathname to become available to read and
// yields a io.ReadCloser when available, or an error if the timeout is
// exceeded or an error (other than file not existing) is encountered. A
// negative timeout indicates to wait forever. The io.ReadCloser must be closed
// after use.
func WaitFile(pathname string, timeout time.Duration) (io.ReadCloser, error) {
	return waitFile(pathname, timeout)
}

// WatchFile watches the file given by pathname and yields a new io.ReadCloser
// when a new inode is found and it is a regular file. The io.ReadCloser must
// be closed after use.
// Any errors are logged to the logger if it is not nil.
func WatchFile(pathname string, logger log.Logger) <-chan io.ReadCloser {
	return watchFile(pathname, logger)
}

// WatchFileStop stops all file watching and cleans up resources that would
// otherwise persist across syscall.Exec.
func WatchFileStop() {
	watchFileStop()
}

type ChecksumReader struct {
	checksummer hash.Hash
	reader      io.Reader
}

func NewChecksumReader(reader io.Reader) *ChecksumReader {
	return newChecksumReader(reader)
}

func (r *ChecksumReader) Read(p []byte) (int, error) {
	return r.read(p)
}

func (r *ChecksumReader) ReadByte() (byte, error) {
	return r.readByte()
}

func (r *ChecksumReader) VerifyChecksum() error {
	return r.verifyChecksum()
}

type ChecksumWriter struct {
	checksummer hash.Hash
	writer      io.Writer
}

func NewChecksumWriter(writer io.Writer) *ChecksumWriter {
	return newChecksumWriter(writer)
}

func (w *ChecksumWriter) Write(p []byte) (int, error) {
	return w.write(p)
}

func (w *ChecksumWriter) WriteChecksum() error {
	return w.writeChecksum()
}

type RenamingWriter struct {
	*os.File
	filename string
	abort    bool
}

func CreateRenamingWriter(filename string, perm os.FileMode) (
	*RenamingWriter, error) {
	return createRenamingWriter(filename, perm)
}

func (w *RenamingWriter) Close() error {
	return w.close()
}

func (w *RenamingWriter) Write(p []byte) (int, error) {
	return w.write(p)
}
<commit_msg>Add panic detection in lib/fsutil.RenamingWriter.Close().<commit_after>package fsutil

import (
	"errors"
	"github.com/Symantec/Dominator/lib/log"
	"hash"
	"io"
	"os"
	"time"
)

var (
	ErrorChecksumMismatch = errors.New("checksum mismatch")
)

// CopyToFile will create a new file, write length bytes from reader to the
// file and then atomically renames the file to destFilename. If there are any
// errors, then destFilename is unchanged.
func CopyToFile(destFilename string, perm os.FileMode, reader io.Reader,
	length uint64) error {
	return copyToFile(destFilename, perm, reader, length)
}

// ForceLink creates newname as a hard link to the oldname file. It first
// attempts to link using os.Link. If the first attempt fails due to
// a permission error, it blindly calls MakeMutable and then retries. If the
// first attempt fails due to newname existing, it blindly removes it and then
// retries.
func ForceLink(oldname, newname string) error {
	return forceLink(oldname, newname)
}

// ForceRemove removes the named file or directory. It first attempts to remove
// using os.Remove and that fails, it blindly calls MakeMutable and then
// retries.
func ForceRemove(name string) error {
	return forceRemove(name)
}

// ForceRemoveAll removes path and any children it contains. It first attempts
// to remove using os.RemoveAll and that fails, it blindly calls MakeMutable and
// then retries.
func ForceRemoveAll(path string) error {
	return forceRemoveAll(path)
}

// ForceRename renames (moves) a file. It first attempts to rename using
// os.Rename and if that fails due to a permission error, it blindly calls
// MakeMutable and then retries. If it fails because newpath is a directory, it
// calls ForceRemoveAll(newpath) and tries again.
func ForceRename(oldpath, newpath string) error {
	return forceRename(oldpath, newpath)
}

// LoadLines will open a file and read lines from it. Comment lines (i.e. lines
// beginning with '#') are skipped.
func LoadLines(filename string) ([]string, error) {
	return loadLines(filename)
}

// MakeMutable attempts to remove the "immutable" and "append-only" ext2
// file-system attributes for one or more files. It is equivalent to calling the
// command-line programme "chattr -ai pathname...".
func MakeMutable(pathname ...string) error {
	return makeMutable(pathname...)
}

// WaitFile waits for the file given by pathname to become available to read and
// yields a io.ReadCloser when available, or an error if the timeout is
// exceeded or an error (other than file not existing) is encountered. A
// negative timeout indicates to wait forever. The io.ReadCloser must be closed
// after use.
func WaitFile(pathname string, timeout time.Duration) (io.ReadCloser, error) {
	return waitFile(pathname, timeout)
}

// WatchFile watches the file given by pathname and yields a new io.ReadCloser
// when a new inode is found and it is a regular file. The io.ReadCloser must
// be closed after use.
// Any errors are logged to the logger if it is not nil.
func WatchFile(pathname string, logger log.Logger) <-chan io.ReadCloser {
	return watchFile(pathname, logger)
}

// WatchFileStop stops all file watching and cleans up resources that would
// otherwise persist across syscall.Exec.
func WatchFileStop() {
	watchFileStop()
}

type ChecksumReader struct {
	checksummer hash.Hash
	reader      io.Reader
}

func NewChecksumReader(reader io.Reader) *ChecksumReader {
	return newChecksumReader(reader)
}

func (r *ChecksumReader) Read(p []byte) (int, error) {
	return r.read(p)
}

func (r *ChecksumReader) ReadByte() (byte, error) {
	return r.readByte()
}

func (r *ChecksumReader) VerifyChecksum() error {
	return r.verifyChecksum()
}

type ChecksumWriter struct {
	checksummer hash.Hash
	writer      io.Writer
}

func NewChecksumWriter(writer io.Writer) *ChecksumWriter {
	return newChecksumWriter(writer)
}

func (w *ChecksumWriter) Write(p []byte) (int, error) {
	return w.write(p)
}

func (w *ChecksumWriter) WriteChecksum() error {
	return w.writeChecksum()
}

type RenamingWriter struct {
	*os.File
	filename string
	abort    bool
}

func CreateRenamingWriter(filename string, perm os.FileMode) (
	*RenamingWriter, error) {
	return createRenamingWriter(filename, perm)
}

func (w *RenamingWriter) Close() error {
	if err := recover(); err != nil {
		w.abort = true
		w.close()
		panic(err)
	}
	return w.close()
}

func (w *RenamingWriter) Write(p []byte) (int, error) {
	return w.write(p)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/johnsiilver/boutique/example/chatterbox/client"
	"github.com/johnsiilver/boutique/example/chatterbox/client/chatterbox/cli/ui"
)

var (
	comm atomic.Value // string
)

func main() {
	flag.Parse()
	errors := []error{}

	comm.Store("")

	defer func() {
		for _, err := range errors {
			fmt.Println(err)
		}
		if len(errors) > 0 {
			os.Exit(1)
		}
	}()

	if len(os.Args) != 2 {
		fmt.Println("usage error: chatterbox <server:port> <user name> <channel>")
		fmt.Println("got: ", strings.Join(os.Args, " "))
		return
	}

	server := os.Args[1]

	// Connection to server setup.
	c, err := client.New(server)
	if err != nil {
		errors = append(errors, fmt.Errorf("error connecting to server: %s", err))
		return
	}

	wg := &sync.WaitGroup{}
	stop := make(chan struct{})

	// Create our UI.
	term, display, input := ui.New(stop)
	if err := term.Start(); err != nil {
		errors = append(errors, fmt.Errorf("Error: problem initing the terminal UI: %s", err))
		return
	}
	defer term.Stop()

	wg.Add(1)
	go inputRouter(c, display, input, stop)
	go fromServer(c, wg, display, stop)

	// We will wait until the ui.Input() gets a /quit.
	wg.Wait()
}

func subscribe(c *client.ChatterBox, channel string, user string, displays ui.Displays) error {
	if comm.Load().(string) != "" {
		if err := c.Drop(); err != nil {
			return fmt.Errorf("could not drop from existing channel %s", comm.Load().(string))
		}
	}
	// Must subscribe before doing anything else.
	users, err := c.Subscribe(channel, user)
	if err != nil {
		return fmt.Errorf("could not subscribe to channel %s: %s", channel, err)
	}
	comm.Store(channel)
	comm.Store(user)

	displays.Users <- users
	return nil
}

func inputRouter(c *client.ChatterBox, displays ui.Displays, inputs ui.Inputs, stop chan struct{}) {
	defer close(stop)
	for {
		select {
		case msg := <-inputs.Msgs:
			if comm.Load().(string) == "" {
				displays.Msgs <- fmt.Sprintf("not subscribed to channel")
			} else if err := c.SendText(msg); err != nil {
				// TODO(johnsiilver): This isn't going to work, because the UI is going to die.
				// Add a channel for after UI messages.  Or maybe don't kill the UI?
				displays.Msgs <- fmt.Sprintf("Error: %s, lost connection to server. Please quit", err)
				return
			}
		case cmd := <-inputs.Cmds:
			switch cmd.Name {
			case "quit":
				displays.Msgs <- fmt.Sprintf("quiting...")
				return
			case "subscribe":
				displays.Msgs <- fmt.Sprintf("setting comm to %s, user to %s", cmd.Args[0], cmd.Args[1]) // debug, remove
				if err := subscribe(c, cmd.Args[0], cmd.Args[1], displays); err != nil {
					displays.Msgs <- fmt.Sprintf("Subscribe error: %s", err)
					return
				}
				cmd.Resp <- fmt.Sprintf("Subscribed to channel: %s as user %s", cmd.Args[0], cmd.Args[1])
			}
		}
	}
}

func fromServer(c *client.ChatterBox, wg *sync.WaitGroup, displays ui.Displays, stop <-chan struct{}) {
	defer wg.Done()

	for {
		select {
		case <-stop:
			return
		case m := <-c.Messages:
			displays.Msgs <- fmt.Sprintf("%s: %s", m.User, strings.TrimSpace(m.Text.Text))
		case e := <-c.ServerErrors:
			displays.Msgs <- fmt.Sprintf("Server Error: %s", e)
		case u := <-c.UserUpdates:
			displays.Users <- u
		}
	}
}
<commit_msg>Detect when client/server connection is dead<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/johnsiilver/boutique/example/chatterbox/client"
	"github.com/johnsiilver/boutique/example/chatterbox/client/chatterbox/cli/ui"
)

var (
	comm   atomic.Value // string
	errors []error
)

func main() {
	flag.Parse()

	comm.Store("")

	defer func() {
		for _, err := range errors {
			fmt.Println(err)
		}
		if len(errors) > 0 {
			os.Exit(1)
		}
	}()

	if len(os.Args) != 2 {
		fmt.Println("usage error: chatterbox <server:port> <user name> <channel>")
		fmt.Println("got: ", strings.Join(os.Args, " "))
		return
	}

	server := os.Args[1]

	// Connection to server setup.
	c, err := client.New(server)
	if err != nil {
		errors = append(errors, fmt.Errorf("error connecting to server: %s", err))
		return
	}

	wg := &sync.WaitGroup{}
	stop := make(chan struct{})

	// Create our UI.
	term, display, input := ui.New(stop)
	if err := term.Start(); err != nil {
		errors = append(errors, fmt.Errorf("Error: problem initing the terminal UI: %s", err))
		return
	}
	defer term.Stop()

	wg.Add(1)
	go inputRouter(c, display, input, stop)
	go fromServer(c, wg, display, stop)

	// We will wait until the ui.Input() gets a /quit.
	wg.Wait()
}

func subscribe(c *client.ChatterBox, channel string, user string, displays ui.Displays) error {
	if comm.Load().(string) != "" {
		if err := c.Drop(); err != nil {
			return fmt.Errorf("could not drop from existing channel %s", comm.Load().(string))
		}
	}
	// Must subscribe before doing anything else.
	users, err := c.Subscribe(channel, user)
	if err != nil {
		return fmt.Errorf("could not subscribe to channel %s: %s", channel, err)
	}
	comm.Store(channel)
	comm.Store(user)

	displays.Users <- users
	return nil
}

func inputRouter(c *client.ChatterBox, displays ui.Displays, inputs ui.Inputs, stop chan struct{}) {
	defer close(stop)
	for {
		select {
		case msg := <-inputs.Msgs:
			if comm.Load().(string) == "" {
				displays.Msgs <- fmt.Sprintf("not subscribed to channel")
			} else if err := c.SendText(msg); err != nil {
				// TODO(johnsiilver): This isn't going to work, because the UI is going to die.
				// Add a channel for after UI messages.  Or maybe don't kill the UI?
				displays.Msgs <- fmt.Sprintf("Error: %s, lost connection to server. Please quit", err)
				return
			}
		case cmd := <-inputs.Cmds:
			switch cmd.Name {
			case "quit":
				displays.Msgs <- fmt.Sprintf("quiting...")
				return
			case "subscribe":
				displays.Msgs <- fmt.Sprintf("setting comm to %s, user to %s", cmd.Args[0], cmd.Args[1]) // debug, remove
				if err := subscribe(c, cmd.Args[0], cmd.Args[1], displays); err != nil {
					displays.Msgs <- fmt.Sprintf("Subscribe error: %s", err)
					return
				}
				cmd.Resp <- fmt.Sprintf("Subscribed to channel: %s as user %s", cmd.Args[0], cmd.Args[1])
			}
		}
	}
}

func fromServer(c *client.ChatterBox, wg *sync.WaitGroup, displays ui.Displays, stop <-chan struct{}) {
	defer wg.Done()

	for {
		select {
		case <-stop:
			return
		case m := <-c.Messages:
			displays.Msgs <- fmt.Sprintf("%s: %s", m.User, strings.TrimSpace(m.Text.Text))
		case e := <-c.ServerErrors:
			displays.Msgs <- fmt.Sprintf("Server Error: %s", e)
		case u := <-c.UserUpdates:
			displays.Users <- u
		case <-c.Done:
			errors = append(errors, fmt.Errorf("connection broken with server"))
			return
		}
	}
}
<|endoftext|>


<commit_before>package acra

import (
	"bytes"
	"encoding/binary"
	"fmt"
	. "github.com/cossacklabs/acra/utils"
	"github.com/cossacklabs/themis/gothemis/cell"
	"github.com/cossacklabs/themis/gothemis/keys"
	"github.com/cossacklabs/themis/gothemis/message"
	"io"
	"log"
)

type BinaryDecryptor struct {
	current_index    uint8
	is_with_zone     bool
	key_block_buffer [KEY_BLOCK_LENGTH]byte
	length_buf       [DATA_LENGTH_SIZE]byte
	buf              []byte
	key_store        KeyStore
	zone_matcher     *ZoneIdMatcher
	poison_key       []byte
	callback_storage *PoisonCallbackStorage
}

func NewBinaryDecryptor() Decryptor { return &BinaryDecryptor{} }

/* not implemented Decryptor interface */
func (decryptor *BinaryDecryptor) MatchBeginTag(char byte) bool {
	if char == TAG_BEGIN[decryptor.current_index] {
		decryptor.current_index++
		return true
	}
	return false
}
func (decryptor *BinaryDecryptor) IsMatched() bool {
	return len(TAG_BEGIN) == int(decryptor.current_index)
}
func (decryptor *BinaryDecryptor) Reset() {
	decryptor.current_index = 0
}
func (decryptor *BinaryDecryptor) GetMatched() []byte {
	return TAG_BEGIN[:decryptor.current_index]
}
func (decryptor *BinaryDecryptor) ReadSymmetricKey(private_key *keys.PrivateKey, reader io.Reader) ([]byte, []byte, error) {
	n, err := io.ReadFull(reader, decryptor.key_block_buffer[:])
	if err != nil {
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return nil, decryptor.key_block_buffer[:n], FAKE_ACRA_STRUCT
		} else {
			return nil, decryptor.key_block_buffer[:n], err
		}
	}
	pubkey := &keys.PublicKey{Value: decryptor.key_block_buffer[:PUBLIC_KEY_LENGTH]}

	smessage := message.New(private_key, pubkey)
	symmetric_key, err := smessage.Unwrap(decryptor.key_block_buffer[PUBLIC_KEY_LENGTH:])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage("can't unwrap scell data", err))
		return nil, decryptor.key_block_buffer[:n], FAKE_ACRA_STRUCT
	}
	return symmetric_key, decryptor.key_block_buffer[:n], nil
}

func (decryptor *BinaryDecryptor) readDataLength(reader io.Reader) (uint64, []byte, error) {
	var length uint64
	len_count, err := io.ReadFull(reader, decryptor.length_buf[:])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage("can't read data length", err))
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return 0, []byte{}, FAKE_ACRA_STRUCT
		} else {
			return 0, []byte{}, err
		}
	}
	if len_count != len(decryptor.length_buf) {
		log.Printf("Warning: incorrect length count, %v!=%v\n", len_count, len(decryptor.length_buf))
		return 0, decryptor.length_buf[:len_count], FAKE_ACRA_STRUCT
	}
	// convert from little endian
	binary.Read(bytes.NewReader(decryptor.length_buf[:]), binary.LittleEndian, &length)
	return length, decryptor.length_buf[:], nil
}

func (decryptor *BinaryDecryptor) checkBuf(buf *[]byte, length int) {
	if buf == nil || len(*buf) < length {
		*buf = make([]byte, length)
	}
}

func (decryptor *BinaryDecryptor) readScellData(length int, reader io.Reader) ([]byte, []byte, error) {
	decryptor.checkBuf(&decryptor.buf, int(length))
	n, err := io.ReadFull(reader, decryptor.buf[:length])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage(fmt.Sprintf("can't read scell data with passed length=%v", length), err))
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return nil, decryptor.buf[:n], FAKE_ACRA_STRUCT
		} else {
			return nil, decryptor.buf[:n], err
		}
	}
	if n != int(length) {
		log.Printf("Warning: %v\n", ErrorMessage("can't decode hex data", err))
		return nil, decryptor.buf[:n], FAKE_ACRA_STRUCT
	}
	return decryptor.buf[:length], decryptor.buf[:length], nil
}

func (decryptor *BinaryDecryptor) ReadData(symmetric_key, zone_id []byte, reader io.Reader) ([]byte, error) {
	length, raw_length_data, err := decryptor.readDataLength(reader)
	if err != nil {
		return raw_length_data, err
	}
	data, raw_data, err := decryptor.readScellData(int(length), reader)
	if err != nil {
		return append(raw_length_data, raw_data...), err
	}

	scell := cell.New(symmetric_key, cell.CELL_MODE_SEAL)
	decrypted, err := scell.Unprotect(data, nil, zone_id)
	data = nil
	// fill zero symmetric_key
	FillSlice(byte(0), symmetric_key)
	if err != nil {
		return append(raw_length_data, raw_data...), FAKE_ACRA_STRUCT
	}
	return decrypted, nil
}

func (decryptor *BinaryDecryptor) SetKeyStore(store KeyStore) {
	decryptor.key_store = store
}

func (decryptor *BinaryDecryptor) GetPrivateKey() (*keys.PrivateKey, error) {
	return decryptor.key_store.GetKey(decryptor.GetMatchedZoneId())
}

func (decryptor *BinaryDecryptor) GetPoisonCallbackStorage() *PoisonCallbackStorage {
	return decryptor.callback_storage
}

func (decryptor *BinaryDecryptor) SetPoisonCallbackStorage(storage *PoisonCallbackStorage) {
	decryptor.callback_storage = storage
}

func (decryptor *BinaryDecryptor) SetPoisonKey(key []byte) {
	decryptor.poison_key = key
}

func (decryptor *BinaryDecryptor) GetPoisonKey() []byte {
	return decryptor.poison_key
}

func (decryptor *BinaryDecryptor) SetZoneMatcher(zone_matcher *ZoneIdMatcher) {
	decryptor.zone_matcher = zone_matcher
}

func (decryptor *BinaryDecryptor) GetMatchedZoneId() []byte {
	if decryptor.IsWithZone() {
		return decryptor.zone_matcher.GetZoneId()
	} else {
		return []byte{}
	}
}

func (decryptor *BinaryDecryptor) ResetZoneMatch() {
	decryptor.zone_matcher.Reset()
}

func (decryptor *BinaryDecryptor) IsMatchedZone() bool {
	return decryptor.zone_matcher.IsMatched() && decryptor.key_store.HasKey(decryptor.zone_matcher.GetZoneId())
}

func (decryptor *BinaryDecryptor) MatchZone(b byte) bool {
	return decryptor.zone_matcher.Match(b)
}

func (decryptor *BinaryDecryptor) IsWithZone() bool {
	return decryptor.is_with_zone
}

func (decryptor *BinaryDecryptor) SetWithZone(b bool) {
	decryptor.is_with_zone = b
}

/* end not implemented Decryptor interface */
<commit_msg>fix cgo error<commit_after>package acra

import (
	"bytes"
	"encoding/binary"
	"fmt"
	. "github.com/cossacklabs/acra/utils"
	"github.com/cossacklabs/themis/gothemis/cell"
	"github.com/cossacklabs/themis/gothemis/keys"
	"github.com/cossacklabs/themis/gothemis/message"
	"io"
	"log"
)

type BinaryDecryptor struct {
	current_index    uint8
	is_with_zone     bool
	key_block_buffer []byte
	length_buf       [DATA_LENGTH_SIZE]byte
	buf              []byte
	key_store        KeyStore
	zone_matcher     *ZoneIdMatcher
	poison_key       []byte
	callback_storage *PoisonCallbackStorage
}

func NewBinaryDecryptor() Decryptor {
	return &BinaryDecryptor{key_block_buffer: make([]byte, KEY_BLOCK_LENGTH)}
}

/* not implemented Decryptor interface */
func (decryptor *BinaryDecryptor) MatchBeginTag(char byte) bool {
	if char == TAG_BEGIN[decryptor.current_index] {
		decryptor.current_index++
		return true
	}
	return false
}
func (decryptor *BinaryDecryptor) IsMatched() bool {
	return len(TAG_BEGIN) == int(decryptor.current_index)
}
func (decryptor *BinaryDecryptor) Reset() {
	decryptor.current_index = 0
}
func (decryptor *BinaryDecryptor) GetMatched() []byte {
	return TAG_BEGIN[:decryptor.current_index]
}
func (decryptor *BinaryDecryptor) ReadSymmetricKey(private_key *keys.PrivateKey, reader io.Reader) ([]byte, []byte, error) {
	n, err := io.ReadFull(reader, decryptor.key_block_buffer[:])
	if err != nil {
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return nil, decryptor.key_block_buffer[:n], FAKE_ACRA_STRUCT
		} else {
			return nil, decryptor.key_block_buffer[:n], err
		}
	}
	pubkey := &keys.PublicKey{Value: decryptor.key_block_buffer[:PUBLIC_KEY_LENGTH]}

	smessage := message.New(private_key, pubkey)
	symmetric_key, err := smessage.Unwrap(decryptor.key_block_buffer[PUBLIC_KEY_LENGTH:])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage("can't unwrap scell data", err))
		return nil, decryptor.key_block_buffer[:n], FAKE_ACRA_STRUCT
	}
	return symmetric_key, decryptor.key_block_buffer[:n], nil
}

func (decryptor *BinaryDecryptor) readDataLength(reader io.Reader) (uint64, []byte, error) {
	var length uint64
	len_count, err := io.ReadFull(reader, decryptor.length_buf[:])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage("can't read data length", err))
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return 0, []byte{}, FAKE_ACRA_STRUCT
		} else {
			return 0, []byte{}, err
		}
	}
	if len_count != len(decryptor.length_buf) {
		log.Printf("Warning: incorrect length count, %v!=%v\n", len_count, len(decryptor.length_buf))
		return 0, decryptor.length_buf[:len_count], FAKE_ACRA_STRUCT
	}
	// convert from little endian
	binary.Read(bytes.NewReader(decryptor.length_buf[:]), binary.LittleEndian, &length)
	return length, decryptor.length_buf[:], nil
}

func (decryptor *BinaryDecryptor) checkBuf(buf *[]byte, length int) {
	if buf == nil || len(*buf) < length {
		*buf = make([]byte, length)
	}
}

func (decryptor *BinaryDecryptor) readScellData(length int, reader io.Reader) ([]byte, []byte, error) {
	decryptor.checkBuf(&decryptor.buf, int(length))
	n, err := io.ReadFull(reader, decryptor.buf[:length])
	if err != nil {
		log.Printf("Warning: %v\n", ErrorMessage(fmt.Sprintf("can't read scell data with passed length=%v", length), err))
		if err == io.ErrUnexpectedEOF || err == io.EOF {
			return nil, decryptor.buf[:n], FAKE_ACRA_STRUCT
		} else {
			return nil, decryptor.buf[:n], err
		}
	}
	if n != int(length) {
		log.Printf("Warning: %v\n", ErrorMessage("can't decode hex data", err))
		return nil, decryptor.buf[:n], FAKE_ACRA_STRUCT
	}
	return decryptor.buf[:length], decryptor.buf[:length], nil
}

func (decryptor *BinaryDecryptor) ReadData(symmetric_key, zone_id []byte, reader io.Reader) ([]byte, error) {
	length, raw_length_data, err := decryptor.readDataLength(reader)
	if err != nil {
		return raw_length_data, err
	}
	data, raw_data, err := decryptor.readScellData(int(length), reader)
	if err != nil {
		return append(raw_length_data, raw_data...), err
	}

	scell := cell.New(symmetric_key, cell.CELL_MODE_SEAL)
	decrypted, err := scell.Unprotect(data, nil, zone_id)
	data = nil
	// fill zero symmetric_key
	FillSlice(byte(0), symmetric_key)
	if err != nil {
		return append(raw_length_data, raw_data...), FAKE_ACRA_STRUCT
	}
	return decrypted, nil
}

func (decryptor *BinaryDecryptor) SetKeyStore(store KeyStore) {
	decryptor.key_store = store
}

func (decryptor *BinaryDecryptor) GetPrivateKey() (*keys.PrivateKey, error) {
	return decryptor.key_store.GetKey(decryptor.GetMatchedZoneId())
}

func (decryptor *BinaryDecryptor) GetPoisonCallbackStorage() *PoisonCallbackStorage {
	return decryptor.callback_storage
}

func (decryptor *BinaryDecryptor) SetPoisonCallbackStorage(storage *PoisonCallbackStorage) {
	decryptor.callback_storage = storage
}

func (decryptor *BinaryDecryptor) SetPoisonKey(key []byte) {
	decryptor.poison_key = key
}

func (decryptor *BinaryDecryptor) GetPoisonKey() []byte {
	return decryptor.poison_key
}

func (decryptor *BinaryDecryptor) SetZoneMatcher(zone_matcher *ZoneIdMatcher) {
	decryptor.zone_matcher = zone_matcher
}

func (decryptor *BinaryDecryptor) GetMatchedZoneId() []byte {
	if decryptor.IsWithZone() {
		return decryptor.zone_matcher.GetZoneId()
	} else {
		return []byte{}
	}
}

func (decryptor *BinaryDecryptor) ResetZoneMatch() {
	decryptor.zone_matcher.Reset()
}

func (decryptor *BinaryDecryptor) IsMatchedZone() bool {
	return decryptor.zone_matcher.IsMatched() && decryptor.key_store.HasKey(decryptor.zone_matcher.GetZoneId())
}

func (decryptor *BinaryDecryptor) MatchZone(b byte) bool {
	return decryptor.zone_matcher.Match(b)
}

func (decryptor *BinaryDecryptor) IsWithZone() bool {
	return decryptor.is_with_zone
}

func (decryptor *BinaryDecryptor) SetWithZone(b bool) {
	decryptor.is_with_zone = b
}

/* end not implemented Decryptor interface */
<|endoftext|>


<commit_before>package blockchain

import (
	"time"
)

// pruningIntervalInMinutes is the interval in which to prune the blockchain's
// nodes and restore memory to the garbage collector.
const pruningIntervalInMinutes = 5

// chainPruner is used to occasionally prune the blockchain of old nodes that
// can be freed to the garbage collector.
type chainPruner struct {
	chain         *BlockChain
	lastPruneTime time.Time
}

// newChainPruner returns a new chain pruner.
func newChainPruner(chain *BlockChain) *chainPruner {
	return &chainPruner{
		chain:         chain,
		lastPruneTime: time.Now(),
	}
}

// pruneChainIfNeeded checks the current time versus the time of the last pruning.
// If the blockchain hasn't been pruned in this time, it initiates a new pruning.
//
// pruneChainIfNeeded must be called with the chainLock held for writes.
func (c *chainPruner) pruneChainIfNeeded() {
	now := time.Now()
	duration := now.Sub(c.lastPruneTime)
	if duration < time.Minute*pruningIntervalInMinutes {
		return
	}

	c.lastPruneTime = now
	c.chain.pruneStakeNodes()
}
<commit_msg>blockchain: Set pruning interval to tgt block time.<commit_after>package blockchain

import (
	"time"
)

// chainPruner is used to occasionally prune the blockchain of old nodes that
// can be freed to the garbage collector.
type chainPruner struct {
	chain           *BlockChain
	lastPruneTime   time.Time
	pruningInterval time.Duration
}

// newChainPruner returns a new chain pruner.
func newChainPruner(chain *BlockChain) *chainPruner {
	return &chainPruner{
		chain:           chain,
		lastPruneTime:   time.Now(),
		pruningInterval: chain.chainParams.TargetTimePerBlock,
	}
}

// pruneChainIfNeeded checks the current time versus the time of the last pruning.
// If the blockchain hasn't been pruned in this time, it initiates a new pruning.
//
// pruneChainIfNeeded must be called with the chainLock held for writes.
func (c *chainPruner) pruneChainIfNeeded() {
	now := time.Now()
	duration := now.Sub(c.lastPruneTime)
	if duration < c.pruningInterval {
		return
	}

	c.lastPruneTime = now
	c.chain.pruneStakeNodes()
}
<|endoftext|>


<commit_before>/*
 *	Copyright (c) 2014 Michael Wendland
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a
 *	copy of this software and associated documentation files (the "Software"),
 *	to deal in the Software without restriction, including without limitation
 *	the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *	and/or sell copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 *	IN THE SOFTWARE.
 *
 *	Authors:
 *		Michael Wendland <michael@michiwend.com>
 */

package gomusicbrainz

type Artist struct {
	Id          string `xml:"id,attr"`
	Type        string `xml:"type,attr"`
	Name        string `xml:"name"`
	SortName    string `xml:"sort-name"`
	CountryCode string `xml:"country"`

	Lifespan struct {
		Ended bool `xml:"ended"`
		//	Begin time.Time `xml:"begin"`
		//	End   time.Time `xml:"end"`
	} `xml:"life-span"`

	Aliases []struct {
		Name     string `xml:",chardata"`
		SortName string `xml:"sort-name,attr"`
	} `xml:"alias-list"`
}

type ArtistSearchRequest struct {
	ArtistList struct {
		Count   int      `xml:"count,attr"`
		Offset  int      `xml:"offset,attr"`
		Artists []Artist `xml:"artist"`
	} `xml:"artist-list"`
}
<commit_msg>BrainzTime type to unmarshal time fields<commit_after>/*
 *	Copyright (c) 2014 Michael Wendland
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a
 *	copy of this software and associated documentation files (the "Software"),
 *	to deal in the Software without restriction, including without limitation
 *	the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *	and/or sell copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 *	IN THE SOFTWARE.
 *
 *	Authors:
 *		Michael Wendland <michael@michiwend.com>
 */

package gomusicbrainz

import (
	"encoding/xml"
	"strings"
	"time"
)

type BrainzTime struct {
	time.Time
}

func (t *BrainzTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var v string
	var p time.Time
	var err error
	d.DecodeElement(&v, &start)

	switch strings.Count(v, "-") {
	case 0:
		p, err = time.Parse("2006", v)
	case 1:
		p, err = time.Parse("2006-01", v)
	case 2:
		p, err = time.Parse("2006-01-02", v)
	}

	// TODO handle empty fields

	if err != nil {
		return err
	}
	*t = BrainzTime{p}
	return nil
}

type Artist struct {
	Id          string `xml:"id,attr"`
	Type        string `xml:"type,attr"`
	Name        string `xml:"name"`
	SortName    string `xml:"sort-name"`
	CountryCode string `xml:"country"` //ISO_3166-1_alpha-2

	Lifespan struct {
		Ended bool       `xml:"ended"`
		Begin BrainzTime `xml:"begin"`
		End   BrainzTime `xml:"end"`
	} `xml:"life-span"`

	Aliases []struct {
		Name     string `xml:",chardata"`
		SortName string `xml:"sort-name,attr"`
	} `xml:"alias-list"`
}

type ArtistSearchRequest struct {
	ArtistList struct {
		Count   int      `xml:"count,attr"`
		Offset  int      `xml:"offset,attr"`
		Artists []Artist `xml:"artist"`
	} `xml:"artist-list"`
}
<|endoftext|>


<commit_before>//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config

package vagrant

import (
	"context"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/common/bootcommand"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config Config
	runner multistep.Runner
}

type Config struct {
	common.PackerConfig    `mapstructure:",squash"`
	common.HTTPConfig      `mapstructure:",squash"`
	common.ISOConfig       `mapstructure:",squash"`
	common.FloppyConfig    `mapstructure:",squash"`
	bootcommand.BootConfig `mapstructure:",squash"`

	Comm communicator.Config `mapstructure:",squash"`
	// The directory to create that will contain your output box. We always
	// create this directory and run from inside of it to prevent Vagrant init
	// collisions. If unset, it will be set to packer- plus your buildname.
	OutputDir string `mapstructure:"output_dir" required:"false"`
	// URL of the vagrant box to use, or the name of the vagrant box.
	// hashicorp/precise64, ./mylocalbox.box and https://example.com/my-box.box
	// are all valid source boxes. If your source is a .box file, whether
	// locally or from a URL like the latter example above, you will also need
	// to provide a box_name. This option is required, unless you set
	// global_id. You may only set one or the other, not both.
	SourceBox string `mapstructure:"source_path" required:"true"`
	// the global id of a Vagrant box already added to Vagrant on your system.
	// You can find the global id of your Vagrant boxes using the command
	// vagrant global-status; your global_id will be a 7-digit number and
	// letter comination that you'll find in the leftmost column of the
	// global-status output.  If you choose to use global_id instead of
	// source_box, Packer will skip the Vagrant initialize and add steps, and
	// simply launch the box directly using the global id.
	GlobalID string `mapstructure:"global_id" required:"true"`
	// The checksum for the .box file. The type of the checksum is specified
	// with checksum_type, documented below.
	Checksum string `mapstructure:"checksum" required:"false"`
	// The type of the checksum specified in checksum. Valid values are none,
	// md5, sha1, sha256, or sha512. Although the checksum will not be verified
	// when checksum_type is set to "none", this is not recommended since OVA
	// files can be very large and corruption does happen from time to time.
	ChecksumType string `mapstructure:"checksum_type" required:"false"`
	// if your source_box is a boxfile that we need to add to Vagrant, this is
	// the name to give it. If left blank, will default to "packer_" plus your
	// buildname.
	BoxName string `mapstructure:"box_name" required:"false"`
	// If true, Vagrant will automatically insert a keypair to use for SSH,
	// replacing Vagrant's default insecure key inside the machine if detected.
	// By default, Packer sets this to false.
	InsertKey bool `mapstructure:"insert_key" required:"false"`
	// The vagrant provider.
	// This parameter is required when source_path have more than one provider,
	// or when using vagrant-cloud post-processor. Defaults to unset.
	Provider string `mapstructure:"provider" required:"false"`

	Communicator string `mapstructure:"communicator"`

	// Options for the "vagrant init" command

	// What vagrantfile to use
	VagrantfileTpl string `mapstructure:"vagrantfile_template"`
	// Whether to halt, suspend, or destroy the box when the build has
	// completed. Defaults to "halt"
	TeardownMethod string `mapstructure:"teardown_method" required:"false"`
	// What box version to use when initializing Vagrant.
	BoxVersion string `mapstructure:"box_version" required:"false"`
	// a path to a golang template for a vagrantfile. Our default template can
	// be found here. The template variables available to you are
	// `{{ .BoxName }}`, `{{ .SyncedFolder }}`, and `{{.InsertKey}}`, which
	// correspond to the Packer options box_name, synced_folder, and insert_key.
	Template string `mapstructure:"template" required:"false"`

	SyncedFolder string `mapstructure:"synced_folder"`
	// Don't call "vagrant add" to add the box to your local environment; this
	// is necessary if you want to launch a box that is already added to your
	// vagrant environment.
	SkipAdd bool `mapstructure:"skip_add" required:"false"`
	// Equivalent to setting the
	// --cacert
	// option in vagrant add; defaults to unset.
	AddCACert string `mapstructure:"add_cacert" required:"false"`
	// Equivalent to setting the
	// --capath option
	// in vagrant add; defaults to unset.
	AddCAPath string `mapstructure:"add_capath" required:"false"`
	// Equivalent to setting the
	// --cert option in
	// vagrant add; defaults to unset.
	AddCert string `mapstructure:"add_cert" required:"false"`
	// Equivalent to setting the
	// --clean flag in
	// vagrant add; defaults to unset.
	AddClean bool `mapstructure:"add_clean" required:"false"`
	// Equivalent to setting the
	// --force flag in
	// vagrant add; defaults to unset.
	AddForce bool `mapstructure:"add_force" required:"false"`
	// Equivalent to setting the
	// --insecure flag in
	// vagrant add; defaults to unset.
	AddInsecure bool `mapstructure:"add_insecure" required:"false"`
	// if true, Packer will not call vagrant package to
	// package your base box into its own standalone .box file.
	SkipPackage       bool   `mapstructure:"skip_package" required:"false"`
	OutputVagrantfile string `mapstructure:"output_vagrantfile"`
	// Equivalent to setting the
	// [`--include`](https://www.vagrantup.com/docs/cli/package.html#include-x-y-z) option
	// in `vagrant package`; defaults to unset
	PackageInclude []string `mapstructure:"package_include"`

	ctx interpolate.Context
}

func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }

func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
	err := config.Decode(&b.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &b.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, nil, err
	}

	// Accumulate any errors and warnings
	var errs *packer.MultiError
	warnings := make([]string, 0)

	if b.config.OutputDir == "" {
		b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName)
	}

	if b.config.Comm.SSHTimeout == 0 {
		b.config.Comm.SSHTimeout = 10 * time.Minute
	}

	if b.config.Comm.Type != "ssh" {
		errs = packer.MultiErrorAppend(errs,
			fmt.Errorf(`The Vagrant builder currently only supports the ssh communicator"`))
	}
	// The box isn't a namespace like you'd pull from vagrant cloud
	if b.config.BoxName == "" {
		b.config.BoxName = fmt.Sprintf("packer_%s", b.config.PackerBuildName)
	}

	if b.config.SourceBox == "" {
		if b.config.GlobalID == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required unless you have set global_id"))
		}
	} else {
		if b.config.GlobalID != "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("You may either set global_id or source_path but not both"))
		}
		if strings.HasSuffix(b.config.SourceBox, ".box") {
			if _, err := os.Stat(b.config.SourceBox); err != nil {
				packer.MultiErrorAppend(errs,
					fmt.Errorf("Source box '%s' needs to exist at time of config validation! %v", b.config.SourceBox, err))
			}
		}
	}

	if b.config.OutputVagrantfile != "" {
		b.config.OutputVagrantfile, err = filepath.Abs(b.config.OutputVagrantfile)
		if err != nil {
			packer.MultiErrorAppend(errs,
				fmt.Errorf("unable to determine absolute path for output vagrantfile: %s", err))
		}
	}

	if len(b.config.PackageInclude) > 0 {
		include := []string{}
		for _, rawFile := range b.config.PackageInclude {
			inclFile, err := filepath.Abs(rawFile)
			if err != nil {
				packer.MultiErrorAppend(errs,
					fmt.Errorf("unable to determine absolute path for file to be included: %s", rawFile))
			}
			include = append(include, inclFile)
		}
		b.config.PackageInclude = include
	}

	if b.config.TeardownMethod == "" {
		// If we're using a box that's already opened on the system, don't
		// automatically destroy it. If we open the box ourselves, then go ahead
		// and kill it by default.
		if b.config.GlobalID != "" {
			b.config.TeardownMethod = "halt"
		} else {
			b.config.TeardownMethod = "destroy"
		}
	} else {
		matches := false
		for _, name := range []string{"halt", "suspend", "destroy"} {
			if strings.ToLower(b.config.TeardownMethod) == name {
				matches = true
			}
		}
		if !matches {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf(`TeardownMethod must be "halt", "suspend", or "destroy"`))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, warnings, errs
	}

	return nil, warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	// Create the driver that we'll use to communicate with VirtualBox
	VagrantCWD, err := filepath.Abs(b.config.OutputDir)
	if err != nil {
		return nil, err
	}
	driver, err := NewDriver(VagrantCWD)
	if err != nil {
		return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err)
	}

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("config", &b.config)
	state.Put("debug", b.config.PackerDebug)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{}
	// Download if source box isn't from vagrant cloud.
	if strings.HasSuffix(b.config.SourceBox, ".box") {
		steps = append(steps, &common.StepDownload{
			Checksum:     b.config.Checksum,
			ChecksumType: b.config.ChecksumType,
			Description:  "Box",
			Extension:    "box",
			ResultKey:    "box_path",
			Url:          []string{b.config.SourceBox},
		})
	}
	steps = append(steps,
		&common.StepOutputDir{
			Force: b.config.PackerForce,
			Path:  b.config.OutputDir,
		},
		&StepCreateVagrantfile{
			Template:     b.config.Template,
			SyncedFolder: b.config.SyncedFolder,
			SourceBox:    b.config.SourceBox,
			BoxName:      b.config.BoxName,
			OutputDir:    b.config.OutputDir,
			GlobalID:     b.config.GlobalID,
			InsertKey:    b.config.InsertKey,
		},
		&StepAddBox{
			BoxVersion:   b.config.BoxVersion,
			CACert:       b.config.AddCACert,
			CAPath:       b.config.AddCAPath,
			DownloadCert: b.config.AddCert,
			Clean:        b.config.AddClean,
			Force:        b.config.AddForce,
			Insecure:     b.config.AddInsecure,
			Provider:     b.config.Provider,
			SourceBox:    b.config.SourceBox,
			BoxName:      b.config.BoxName,
			GlobalID:     b.config.GlobalID,
			SkipAdd:      b.config.SkipAdd,
		},
		&StepUp{
			TeardownMethod: b.config.TeardownMethod,
			Provider:       b.config.Provider,
			GlobalID:       b.config.GlobalID,
		},
		&StepSSHConfig{
			b.config.GlobalID,
		},
		&communicator.StepConnect{
			Config:    &b.config.Comm,
			Host:      CommHost(),
			SSHConfig: b.config.Comm.SSHConfigFunc(),
		},
		new(common.StepProvision),
		&StepPackage{
			SkipPackage: b.config.SkipPackage,
			Include:     b.config.PackageInclude,
			Vagrantfile: b.config.OutputVagrantfile,
			GlobalID:    b.config.GlobalID,
		})

	// Run the steps.
	b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
	b.runner.Run(ctx, state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
	return NewArtifact(b.config.Provider, b.config.OutputDir, generatedData), nil
}

// Cancel.
<commit_msg>linting<commit_after>//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config

package vagrant

import (
	"context"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/hashicorp/packer/common"
	"github.com/hashicorp/packer/common/bootcommand"
	"github.com/hashicorp/packer/helper/communicator"
	"github.com/hashicorp/packer/helper/config"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config Config
	runner multistep.Runner
}

type Config struct {
	common.PackerConfig    `mapstructure:",squash"`
	common.HTTPConfig      `mapstructure:",squash"`
	common.ISOConfig       `mapstructure:",squash"`
	common.FloppyConfig    `mapstructure:",squash"`
	bootcommand.BootConfig `mapstructure:",squash"`

	Comm communicator.Config `mapstructure:",squash"`
	// The directory to create that will contain your output box. We always
	// create this directory and run from inside of it to prevent Vagrant init
	// collisions. If unset, it will be set to packer- plus your buildname.
	OutputDir string `mapstructure:"output_dir" required:"false"`
	// URL of the vagrant box to use, or the name of the vagrant box.
	// hashicorp/precise64, ./mylocalbox.box and https://example.com/my-box.box
	// are all valid source boxes. If your source is a .box file, whether
	// locally or from a URL like the latter example above, you will also need
	// to provide a box_name. This option is required, unless you set
	// global_id. You may only set one or the other, not both.
	SourceBox string `mapstructure:"source_path" required:"true"`
	// the global id of a Vagrant box already added to Vagrant on your system.
	// You can find the global id of your Vagrant boxes using the command
	// vagrant global-status; your global_id will be a 7-digit number and
	// letter comination that you'll find in the leftmost column of the
	// global-status output.  If you choose to use global_id instead of
	// source_box, Packer will skip the Vagrant initialize and add steps, and
	// simply launch the box directly using the global id.
	GlobalID string `mapstructure:"global_id" required:"true"`
	// The checksum for the .box file. The type of the checksum is specified
	// with checksum_type, documented below.
	Checksum string `mapstructure:"checksum" required:"false"`
	// The type of the checksum specified in checksum. Valid values are none,
	// md5, sha1, sha256, or sha512. Although the checksum will not be verified
	// when checksum_type is set to "none", this is not recommended since OVA
	// files can be very large and corruption does happen from time to time.
	ChecksumType string `mapstructure:"checksum_type" required:"false"`
	// if your source_box is a boxfile that we need to add to Vagrant, this is
	// the name to give it. If left blank, will default to "packer_" plus your
	// buildname.
	BoxName string `mapstructure:"box_name" required:"false"`
	// If true, Vagrant will automatically insert a keypair to use for SSH,
	// replacing Vagrant's default insecure key inside the machine if detected.
	// By default, Packer sets this to false.
	InsertKey bool `mapstructure:"insert_key" required:"false"`
	// The vagrant provider.
	// This parameter is required when source_path have more than one provider,
	// or when using vagrant-cloud post-processor. Defaults to unset.
	Provider string `mapstructure:"provider" required:"false"`

	Communicator string `mapstructure:"communicator"`

	// Options for the "vagrant init" command

	// What vagrantfile to use
	VagrantfileTpl string `mapstructure:"vagrantfile_template"`
	// Whether to halt, suspend, or destroy the box when the build has
	// completed. Defaults to "halt"
	TeardownMethod string `mapstructure:"teardown_method" required:"false"`
	// What box version to use when initializing Vagrant.
	BoxVersion string `mapstructure:"box_version" required:"false"`
	// a path to a golang template for a vagrantfile. Our default template can
	// be found here. The template variables available to you are
	// `{{ .BoxName }}`, `{{ .SyncedFolder }}`, and `{{.InsertKey}}`, which
	// correspond to the Packer options box_name, synced_folder, and insert_key.
	Template string `mapstructure:"template" required:"false"`

	SyncedFolder string `mapstructure:"synced_folder"`
	// Don't call "vagrant add" to add the box to your local environment; this
	// is necessary if you want to launch a box that is already added to your
	// vagrant environment.
	SkipAdd bool `mapstructure:"skip_add" required:"false"`
	// Equivalent to setting the
	// --cacert
	// option in vagrant add; defaults to unset.
	AddCACert string `mapstructure:"add_cacert" required:"false"`
	// Equivalent to setting the
	// --capath option
	// in vagrant add; defaults to unset.
	AddCAPath string `mapstructure:"add_capath" required:"false"`
	// Equivalent to setting the
	// --cert option in
	// vagrant add; defaults to unset.
	AddCert string `mapstructure:"add_cert" required:"false"`
	// Equivalent to setting the
	// --clean flag in
	// vagrant add; defaults to unset.
	AddClean bool `mapstructure:"add_clean" required:"false"`
	// Equivalent to setting the
	// --force flag in
	// vagrant add; defaults to unset.
	AddForce bool `mapstructure:"add_force" required:"false"`
	// Equivalent to setting the
	// --insecure flag in
	// vagrant add; defaults to unset.
	AddInsecure bool `mapstructure:"add_insecure" required:"false"`
	// if true, Packer will not call vagrant package to
	// package your base box into its own standalone .box file.
	SkipPackage       bool   `mapstructure:"skip_package" required:"false"`
	OutputVagrantfile string `mapstructure:"output_vagrantfile"`
	// Equivalent to setting the
	// [`--include`](https://www.vagrantup.com/docs/cli/package.html#include-x-y-z) option
	// in `vagrant package`; defaults to unset
	PackageInclude []string `mapstructure:"package_include"`

	ctx interpolate.Context
}

func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }

func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
	err := config.Decode(&b.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &b.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"boot_command",
			},
		},
	}, raws...)
	if err != nil {
		return nil, nil, err
	}

	// Accumulate any errors and warnings
	var errs *packer.MultiError
	warnings := make([]string, 0)

	if b.config.OutputDir == "" {
		b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName)
	}

	if b.config.Comm.SSHTimeout == 0 {
		b.config.Comm.SSHTimeout = 10 * time.Minute
	}

	if b.config.Comm.Type != "ssh" {
		errs = packer.MultiErrorAppend(errs,
			fmt.Errorf(`The Vagrant builder currently only supports the ssh communicator"`))
	}
	// The box isn't a namespace like you'd pull from vagrant cloud
	if b.config.BoxName == "" {
		b.config.BoxName = fmt.Sprintf("packer_%s", b.config.PackerBuildName)
	}

	if b.config.SourceBox == "" {
		if b.config.GlobalID == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required unless you have set global_id"))
		}
	} else {
		if b.config.GlobalID != "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("You may either set global_id or source_path but not both"))
		}
		if strings.HasSuffix(b.config.SourceBox, ".box") {
			if _, err := os.Stat(b.config.SourceBox); err != nil {
				errs = packer.MultiErrorAppend(errs,
					fmt.Errorf("Source box '%s' needs to exist at time of config validation! %v", b.config.SourceBox, err))
			}
		}
	}

	if b.config.OutputVagrantfile != "" {
		b.config.OutputVagrantfile, err = filepath.Abs(b.config.OutputVagrantfile)
		if err != nil {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("unable to determine absolute path for output vagrantfile: %s", err))
		}
	}

	if len(b.config.PackageInclude) > 0 {
		include := []string{}
		for _, rawFile := range b.config.PackageInclude {
			inclFile, err := filepath.Abs(rawFile)
			if err != nil {
				errs = packer.MultiErrorAppend(errs,
					fmt.Errorf("unable to determine absolute path for file to be included: %s", rawFile))
			}
			include = append(include, inclFile)
		}
		b.config.PackageInclude = include
	}

	if b.config.TeardownMethod == "" {
		// If we're using a box that's already opened on the system, don't
		// automatically destroy it. If we open the box ourselves, then go ahead
		// and kill it by default.
		if b.config.GlobalID != "" {
			b.config.TeardownMethod = "halt"
		} else {
			b.config.TeardownMethod = "destroy"
		}
	} else {
		matches := false
		for _, name := range []string{"halt", "suspend", "destroy"} {
			if strings.ToLower(b.config.TeardownMethod) == name {
				matches = true
			}
		}
		if !matches {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf(`TeardownMethod must be "halt", "suspend", or "destroy"`))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return nil, warnings, errs
	}

	return nil, warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	// Create the driver that we'll use to communicate with VirtualBox
	VagrantCWD, err := filepath.Abs(b.config.OutputDir)
	if err != nil {
		return nil, err
	}
	driver, err := NewDriver(VagrantCWD)
	if err != nil {
		return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err)
	}

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("config", &b.config)
	state.Put("debug", b.config.PackerDebug)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{}
	// Download if source box isn't from vagrant cloud.
	if strings.HasSuffix(b.config.SourceBox, ".box") {
		steps = append(steps, &common.StepDownload{
			Checksum:     b.config.Checksum,
			ChecksumType: b.config.ChecksumType,
			Description:  "Box",
			Extension:    "box",
			ResultKey:    "box_path",
			Url:          []string{b.config.SourceBox},
		})
	}
	steps = append(steps,
		&common.StepOutputDir{
			Force: b.config.PackerForce,
			Path:  b.config.OutputDir,
		},
		&StepCreateVagrantfile{
			Template:     b.config.Template,
			SyncedFolder: b.config.SyncedFolder,
			SourceBox:    b.config.SourceBox,
			BoxName:      b.config.BoxName,
			OutputDir:    b.config.OutputDir,
			GlobalID:     b.config.GlobalID,
			InsertKey:    b.config.InsertKey,
		},
		&StepAddBox{
			BoxVersion:   b.config.BoxVersion,
			CACert:       b.config.AddCACert,
			CAPath:       b.config.AddCAPath,
			DownloadCert: b.config.AddCert,
			Clean:        b.config.AddClean,
			Force:        b.config.AddForce,
			Insecure:     b.config.AddInsecure,
			Provider:     b.config.Provider,
			SourceBox:    b.config.SourceBox,
			BoxName:      b.config.BoxName,
			GlobalID:     b.config.GlobalID,
			SkipAdd:      b.config.SkipAdd,
		},
		&StepUp{
			TeardownMethod: b.config.TeardownMethod,
			Provider:       b.config.Provider,
			GlobalID:       b.config.GlobalID,
		},
		&StepSSHConfig{
			b.config.GlobalID,
		},
		&communicator.StepConnect{
			Config:    &b.config.Comm,
			Host:      CommHost(),
			SSHConfig: b.config.Comm.SSHConfigFunc(),
		},
		new(common.StepProvision),
		&StepPackage{
			SkipPackage: b.config.SkipPackage,
			Include:     b.config.PackageInclude,
			Vagrantfile: b.config.OutputVagrantfile,
			GlobalID:    b.config.GlobalID,
		})

	// Run the steps.
	b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
	b.runner.Run(ctx, state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
	return NewArtifact(b.config.Provider, b.config.OutputDir, generatedData), nil
}

// Cancel.
<|endoftext|>


<commit_before>package remotedialer

import (
	"context"
	"net/http"
	"strings"
	"time"

	"github.com/gorilla/websocket"
	"github.com/pkg/errors"
	"github.com/rancher/norman/pkg/remotedialer"
	"github.com/rancher/rancher/pkg/rkenodeconfigclient"
	"github.com/rancher/rancher/pkg/rkeworker"
	"github.com/sirupsen/logrus"
	"golang.org/x/sync/errgroup"
)

type ConnectingStatus int

const (
	ConnectingStatusStopped ConnectingStatus = iota
	ConnectingStatusRetry
	ConnectionStatusLost
	ConnectingStatusFailed
)

func ClientConnectWhileWindows(ctx context.Context, wsURL string, headers http.Header, dialer *websocket.Dialer, auth remotedialer.ConnectAuthorizer, blockingOnConnect func(context.Context) error) ConnectingStatus {
	if err := connectToProxyWhileWindows(ctx, wsURL, headers, auth, dialer, blockingOnConnect); err != nil {
		if err == rkeworker.ErrHyperKubePSScriptAgentRetry {
			return ConnectingStatusRetry
		}

		if e, ok := err.(*rkenodeconfigclient.ErrNodeOrClusterNotFound); ok {
			logrus.Warnf("Proxy lost: it seems lost the registered %s: %v", e.ErrorOccursType(), e)
			return ConnectionStatusLost
		}

		logrus.Warnf("Proxy failed: %v", err)
		return ConnectingStatusFailed
	}

	logrus.Debugln("Proxy stopped")
	return ConnectingStatusStopped
}

func connectToProxyWhileWindows(rootContext context.Context, proxyURL string, headers http.Header, auth remotedialer.ConnectAuthorizer, dialer *websocket.Dialer, blockingOnConnect func(context.Context) error) error {
	if dialer == nil {
		dialer = &websocket.Dialer{}
	}

	eg, ctx := errgroup.WithContext(rootContext)

	if blockingOnConnect != nil {
		eg.Go(func() error {
			return blockingOnConnect(ctx)
		})
	}

	eg.Go(func() error {
		connectRetryLimit := 10

		var err error
		for err == nil {
			err = func() error {
				ws, _, err := dialer.Dial(proxyURL, headers)
				if err != nil {
					return err
				}
				defer ws.Close()

				session := remotedialer.NewClientSession(auth, ws)
				_, err = session.ServeWhileWindows(ctx)
				session.Close()
				return err
			}()

			if err != nil {
				if connectRetryLimit < 1 {
					return errors.Wrap(err, "dialer retry timeout")
				}

				errMsg := err.Error()
				if err == websocket.ErrBadHandshake ||
					strings.HasSuffix(errMsg, "An existing connection was forcibly closed by the remote host.") ||
					strings.HasSuffix(errMsg, "An established connection was aborted by the software in your host machine.") ||
					strings.HasSuffix(errMsg, "A socket operation was attempted to an unreachable network.") {

					logrus.Debugf("Proxy dialer retry to %d times", connectRetryLimit)
					connectRetryLimit--
					time.Sleep(6 * time.Second)
					err = nil
				}
			}
		}

		return err
	})

	return eg.Wait()
}
<commit_msg>Configure HandshakeTimeout in websocket.Dialer<commit_after>package remotedialer

import (
	"context"
	"net/http"
	"strings"
	"time"

	"github.com/gorilla/websocket"
	"github.com/pkg/errors"
	"github.com/rancher/norman/pkg/remotedialer"
	"github.com/rancher/rancher/pkg/rkenodeconfigclient"
	"github.com/rancher/rancher/pkg/rkeworker"
	"github.com/sirupsen/logrus"
	"golang.org/x/sync/errgroup"
)

type ConnectingStatus int

const (
	ConnectingStatusStopped ConnectingStatus = iota
	ConnectingStatusRetry
	ConnectionStatusLost
	ConnectingStatusFailed
)

func ClientConnectWhileWindows(ctx context.Context, wsURL string, headers http.Header, dialer *websocket.Dialer, auth remotedialer.ConnectAuthorizer, blockingOnConnect func(context.Context) error) ConnectingStatus {
	if err := connectToProxyWhileWindows(ctx, wsURL, headers, auth, dialer, blockingOnConnect); err != nil {
		if err == rkeworker.ErrHyperKubePSScriptAgentRetry {
			return ConnectingStatusRetry
		}

		if e, ok := err.(*rkenodeconfigclient.ErrNodeOrClusterNotFound); ok {
			logrus.Warnf("Proxy lost: it seems lost the registered %s: %v", e.ErrorOccursType(), e)
			return ConnectionStatusLost
		}

		logrus.Warnf("Proxy failed: %v", err)
		return ConnectingStatusFailed
	}

	logrus.Debugln("Proxy stopped")
	return ConnectingStatusStopped
}

func connectToProxyWhileWindows(rootContext context.Context, proxyURL string, headers http.Header, auth remotedialer.ConnectAuthorizer, dialer *websocket.Dialer, blockingOnConnect func(context.Context) error) error {
	if dialer == nil {
		dialer = &websocket.Dialer{HandshakeTimeout: 10 * time.Second}
	}

	eg, ctx := errgroup.WithContext(rootContext)

	if blockingOnConnect != nil {
		eg.Go(func() error {
			return blockingOnConnect(ctx)
		})
	}

	eg.Go(func() error {
		connectRetryLimit := 10

		var err error
		for err == nil {
			err = func() error {
				ws, _, err := dialer.Dial(proxyURL, headers)
				if err != nil {
					return err
				}
				defer ws.Close()

				session := remotedialer.NewClientSession(auth, ws)
				_, err = session.ServeWhileWindows(ctx)
				session.Close()
				return err
			}()

			if err != nil {
				if connectRetryLimit < 1 {
					return errors.Wrap(err, "dialer retry timeout")
				}

				errMsg := err.Error()
				if err == websocket.ErrBadHandshake ||
					strings.HasSuffix(errMsg, "An existing connection was forcibly closed by the remote host.") ||
					strings.HasSuffix(errMsg, "An established connection was aborted by the software in your host machine.") ||
					strings.HasSuffix(errMsg, "A socket operation was attempted to an unreachable network.") {

					logrus.Debugf("Proxy dialer retry to %d times", connectRetryLimit)
					connectRetryLimit--
					time.Sleep(6 * time.Second)
					err = nil
				}
			}
		}

		return err
	})

	return eg.Wait()
}
<|endoftext|>


<commit_before>package content

import (
	"text/template"
)

const (
	// BootkubeSystemdContents is a service for running bootkube on the bootstrap
	// nodes
	BootkubeSystemdContents = `
[Unit]
Description=Bootstrap a Kubernetes cluster
Wants=kubelet.service
After=kubelet.service

[Service]
WorkingDirectory=/opt/tectonic
RemainAfterExit=true
ExecStart=/usr/local/bin/bootkube.sh

Restart=on-failure
RestartSec=5s
`
)

var (
	// BootkubeShFileTemplate is a script file for running bootkube on the
	// bootstrap nodes.
	BootkubeShFileTemplate = template.Must(template.New("bootkube.sh").Parse(`#!/usr/bin/env bash
set -e

mkdir --parents /etc/kubernetes/{manifests,bootstrap-configs,bootstrap-manifests}

MACHINE_CONFIG_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-operator)
MACHINE_CONFIG_CONTROLLER_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-controller)
MACHINE_CONFIG_SERVER_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-server)
MACHINE_CONFIG_DAEMON_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-daemon)

KUBE_APISERVER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-apiserver-operator)
KUBE_CONTROLLER_MANAGER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-controller-manager-operator)
KUBE_SCHEDULER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-scheduler-operator)

OPENSHIFT_HYPERSHIFT_IMAGE=$(podman run --rm {{.ReleaseImage}} image hypershift)
OPENSHIFT_HYPERKUBE_IMAGE=$(podman run --rm {{.ReleaseImage}} image hyperkube)

if [ ! -d cvo-bootstrap ]
then
	echo "Rendering Cluster Version Operator Manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"{{.ReleaseImage}}" \
		render \
			--output-dir=/assets/cvo-bootstrap \
			--release-image="{{.ReleaseImage}}"

	cp --recursive cvo-bootstrap/manifests .
fi

mkdir --parents ./{bootstrap-manifests,manifests}

if [ ! -d kube-apiserver-bootstrap ]
then
	echo "Rendering Kubernetes API server core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_APISERVER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-apiserver-operator render \
		--manifest-etcd-serving-ca=etcd-client-ca.crt \
		--manifest-etcd-server-urls={{.EtcdCluster}} \
		--manifest-image=${OPENSHIFT_HYPERSHIFT_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-apiserver-bootstrap \
		--config-output-file=/assets/kube-apiserver-bootstrap/config \
		--config-override-files=/assets/bootkube-config-overrides/kube-apiserver-config-overrides.yaml \
		--disable-phase-2

	cp kube-apiserver-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-apiserver-config.yaml
	cp kube-apiserver-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-apiserver-bootstrap/manifests/* manifests/
fi

if [ ! -d kube-controller-manager-bootstrap ]
then
	echo "Rendering Kubernetes Controller Manager core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_CONTROLLER_MANAGER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-controller-manager-operator render \
		--manifest-image=${OPENSHIFT_HYPERKUBE_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-controller-manager-bootstrap \
		--config-output-file=/assets/kube-controller-manager-bootstrap/config \
		--config-override-files=/assets/bootkube-config-overrides/kube-controller-manager-config-overrides.yaml

	cp kube-controller-manager-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-controller-manager-config.yaml
	cp kube-controller-manager-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-controller-manager-bootstrap/manifests/* manifests/
fi

if [ ! -d kube-scheduler-bootstrap ]
then
	echo "Rendering Kubernetes Scheduler core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_SCHEDULER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-scheduler-operator render \
		--manifest-image=${OPENSHIFT_HYPERKUBE_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-scheduler-bootstrap \
		--config-output-file=/assets/kube-scheduler-bootstrap/config

	cp kube-scheduler-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-scheduler-config.yaml
	cp kube-scheduler-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-scheduler-bootstrap/manifests/* manifests/
fi

# TODO: Remove this when checkpointer, kube-proxy and kube-dns are properly rendered by corresponding operators.
echo "Installing temporary bootstrap manifests..."
cp pod-checkpointer-operator-bootstrap/* manifests/
cp kube-proxy-operator-bootstrap/* manifests/
cp kube-dns-operator-bootstrap/* manifests/

if [ ! -d mco-bootstrap ]
then
	echo "Rendering MCO manifests..."

	# shellcheck disable=SC2154
	podman run \
		--user 0 \
		--volume "$PWD:/assets:z" \
		"${MACHINE_CONFIG_OPERATOR_IMAGE}" \
		bootstrap \
			--etcd-ca=/assets/tls/etcd-client-ca.crt \
			--root-ca=/assets/tls/root-ca.crt \
			--config-file=/assets/manifests/cluster-config.yaml \
			--dest-dir=/assets/mco-bootstrap \
			--machine-config-controller-image=${MACHINE_CONFIG_CONTROLLER_IMAGE} \
			--machine-config-server-image=${MACHINE_CONFIG_SERVER_IMAGE} \
			--machine-config-daemon-image=${MACHINE_CONFIG_DAEMON_IMAGE} \

	# Bootstrap MachineConfigController uses /etc/mcc/bootstrap/manifests/ dir to
	# 1. read the controller config rendered by MachineConfigOperator
	# 2. read the default MachineConfigPools rendered by MachineConfigOperator
	# 3. read any additional MachineConfigs that are needed for the default MachineConfigPools.
	mkdir --parents /etc/mcc/bootstrap/manifests /etc/kubernetes/manifests/
	cp mco-bootstrap/manifests/* /etc/mcc/bootstrap/manifests/
	cp mco-bootstrap/machineconfigoperator-bootstrap-pod.yaml /etc/kubernetes/manifests/

	# /etc/ssl/mcs/tls.{crt, key} are locations for MachineConfigServer's tls assets.
	mkdir --parents /etc/ssl/mcs/
	cp tls/machine-config-server.crt /etc/ssl/mcs/tls.crt
	cp tls/machine-config-server.key /etc/ssl/mcs/tls.key
fi

# We originally wanted to run the etcd cert signer as
# a static pod, but kubelet could't remove static pod
# when API server is not up, so we have to run this as
# podman container.
# See https://github.com/kubernetes/kubernetes/issues/43292

echo "Starting etcd certificate signer..."

trap "podman rm --force etcd-signer" ERR

# shellcheck disable=SC2154
podman run \
	--name etcd-signer \
	--detach \
	--volume /opt/tectonic/tls:/opt/tectonic/tls:ro,z \
	--network host \
	"{{.EtcdCertSignerImage}}" \
	serve \
	--cacrt=/opt/tectonic/tls/etcd-client-ca.crt \
	--cakey=/opt/tectonic/tls/etcd-client-ca.key \
	--servcrt=/opt/tectonic/tls/apiserver.crt \
	--servkey=/opt/tectonic/tls/apiserver.key \
	--address=0.0.0.0:6443 \
	--csrdir=/tmp \
	--peercertdur=26280h \
	--servercertdur=26280h

echo "Waiting for etcd cluster..."

# Wait for the etcd cluster to come up.
# shellcheck disable=SC2154,SC2086
until podman run \
		--rm \
		--network host \
		--name etcdctl \
		--env ETCDCTL_API=3 \
		--volume /opt/tectonic/tls:/opt/tectonic/tls:ro,z \
		"{{.EtcdctlImage}}" \
		/usr/local/bin/etcdctl \
		--dial-timeout=10m \
		--cacert=/opt/tectonic/tls/etcd-client-ca.crt \
		--cert=/opt/tectonic/tls/etcd-client.crt \
		--key=/opt/tectonic/tls/etcd-client.key \
		--endpoints={{.EtcdCluster}} \
		endpoint health
do
	echo "etcdctl failed. Retrying in 5 seconds..."
	sleep 5
done

echo "etcd cluster up. Killing etcd certificate signer..."

podman rm --force etcd-signer
rm --force /etc/kubernetes/manifests/machineconfigoperator-bootstrap-pod.yaml

echo "Starting bootkube..."

# shellcheck disable=SC2154
podman run \
	--rm \
	--volume "$PWD:/assets:z" \
	--volume /etc/kubernetes:/etc/kubernetes:z \
	--network=host \
	--entrypoint=/bootkube \
	"{{.BootkubeImage}}" \
	start --asset-dir=/assets --required-pods kube-system/pod-checkpointer,openshift-kube-apiserver/openshift-kube-apiserver,kube-system/kube-scheduler,kube-system/kube-controller-manager

# Workaround for https://github.com/opencontainers/runc/pull/1807
touch /opt/tectonic/.bootkube.done
`))
)

var (
	// BootkubeConfigOverrides contains the configuration override files passed to the render commands of the components.
	// These are supposed to be customized by the installer where the config differs from the operator render default.
	BootkubeConfigOverrides = []*template.Template{
		KubeApiserverConfigOverridesTemplate,
		KubeControllerManagerConfigOverridesTemplate,
	}
)

var (
	// KubeApiserverConfigOverridesTemplate are overrides that the installer passes to the default config of the
	// kube-apiserver rendered by the cluster-kube-apiserver-operator.
	KubeApiserverConfigOverridesTemplate = template.Must(template.New("kube-apiserver-config-overrides.yaml").Parse(`
apiVersion: kubecontrolplane.config.openshift.io/v1
kind: KubeAPIServerConfig
kubeletClientInfo:
  ca: "" # kubelet uses self-signed serving certs. TODO: fix kubelet pki
`))

	// KubeControllerManagerConfigOverridesTemplate are overrides that the installer passes to the default config of the
	// kube-controller-manager rendered by the cluster-kube-controller-manager-operator.
	KubeControllerManagerConfigOverridesTemplate = template.Must(template.New("kube-controller-manager-config-overrides.yaml").Parse(`
apiVersion: kubecontrolplane.config.openshift.io/v1
kind: KubeControllerManagerConfig
`))
)
<commit_msg>bootkube: launch CVO on bootstrap node<commit_after>package content

import (
	"text/template"
)

const (
	// BootkubeSystemdContents is a service for running bootkube on the bootstrap
	// nodes
	BootkubeSystemdContents = `
[Unit]
Description=Bootstrap a Kubernetes cluster
Wants=kubelet.service
After=kubelet.service

[Service]
WorkingDirectory=/opt/tectonic
RemainAfterExit=true
ExecStart=/usr/local/bin/bootkube.sh

Restart=on-failure
RestartSec=5s
`
)

var (
	// BootkubeShFileTemplate is a script file for running bootkube on the
	// bootstrap nodes.
	BootkubeShFileTemplate = template.Must(template.New("bootkube.sh").Parse(`#!/usr/bin/env bash
set -e

mkdir --parents /etc/kubernetes/{manifests,bootstrap-configs,bootstrap-manifests}

MACHINE_CONFIG_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-operator)
MACHINE_CONFIG_CONTROLLER_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-controller)
MACHINE_CONFIG_SERVER_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-server)
MACHINE_CONFIG_DAEMON_IMAGE=$(podman run --rm {{.ReleaseImage}} image machine-config-daemon)

KUBE_APISERVER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-apiserver-operator)
KUBE_CONTROLLER_MANAGER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-controller-manager-operator)
KUBE_SCHEDULER_OPERATOR_IMAGE=$(podman run --rm {{.ReleaseImage}} image cluster-kube-scheduler-operator)

OPENSHIFT_HYPERSHIFT_IMAGE=$(podman run --rm {{.ReleaseImage}} image hypershift)
OPENSHIFT_HYPERKUBE_IMAGE=$(podman run --rm {{.ReleaseImage}} image hyperkube)

mkdir --parents ./{bootstrap-manifests,manifests}

if [ ! -d cvo-bootstrap ]
then
	echo "Rendering Cluster Version Operator Manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"{{.ReleaseImage}}" \
		render \
			--output-dir=/assets/cvo-bootstrap \
			--release-image="{{.ReleaseImage}}"

	cp cvo-bootstrap/bootstrap/* bootstrap-manifests/
	cp cvo-bootstrap/manifests/* manifests/
fi

if [ ! -d kube-apiserver-bootstrap ]
then
	echo "Rendering Kubernetes API server core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_APISERVER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-apiserver-operator render \
		--manifest-etcd-serving-ca=etcd-client-ca.crt \
		--manifest-etcd-server-urls={{.EtcdCluster}} \
		--manifest-image=${OPENSHIFT_HYPERSHIFT_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-apiserver-bootstrap \
		--config-output-file=/assets/kube-apiserver-bootstrap/config \
		--config-override-files=/assets/bootkube-config-overrides/kube-apiserver-config-overrides.yaml \
		--disable-phase-2

	cp kube-apiserver-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-apiserver-config.yaml
	cp kube-apiserver-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-apiserver-bootstrap/manifests/* manifests/
fi

if [ ! -d kube-controller-manager-bootstrap ]
then
	echo "Rendering Kubernetes Controller Manager core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_CONTROLLER_MANAGER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-controller-manager-operator render \
		--manifest-image=${OPENSHIFT_HYPERKUBE_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-controller-manager-bootstrap \
		--config-output-file=/assets/kube-controller-manager-bootstrap/config \
		--config-override-files=/assets/bootkube-config-overrides/kube-controller-manager-config-overrides.yaml

	cp kube-controller-manager-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-controller-manager-config.yaml
	cp kube-controller-manager-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-controller-manager-bootstrap/manifests/* manifests/
fi

if [ ! -d kube-scheduler-bootstrap ]
then
	echo "Rendering Kubernetes Scheduler core manifests..."

	# shellcheck disable=SC2154
	podman run \
		--volume "$PWD:/assets:z" \
		"${KUBE_SCHEDULER_OPERATOR_IMAGE}" \
		/usr/bin/cluster-kube-scheduler-operator render \
		--manifest-image=${OPENSHIFT_HYPERKUBE_IMAGE} \
		--asset-input-dir=/assets/tls \
		--asset-output-dir=/assets/kube-scheduler-bootstrap \
		--config-output-file=/assets/kube-scheduler-bootstrap/config

	cp kube-scheduler-bootstrap/config /etc/kubernetes/bootstrap-configs/kube-scheduler-config.yaml
	cp kube-scheduler-bootstrap/bootstrap-manifests/* bootstrap-manifests/
	cp kube-scheduler-bootstrap/manifests/* manifests/
fi

# TODO: Remove this when checkpointer, kube-proxy and kube-dns are properly rendered by corresponding operators.
echo "Installing temporary bootstrap manifests..."
cp pod-checkpointer-operator-bootstrap/* manifests/
cp kube-proxy-operator-bootstrap/* manifests/
cp kube-dns-operator-bootstrap/* manifests/

if [ ! -d mco-bootstrap ]
then
	echo "Rendering MCO manifests..."

	# shellcheck disable=SC2154
	podman run \
		--user 0 \
		--volume "$PWD:/assets:z" \
		"${MACHINE_CONFIG_OPERATOR_IMAGE}" \
		bootstrap \
			--etcd-ca=/assets/tls/etcd-client-ca.crt \
			--root-ca=/assets/tls/root-ca.crt \
			--config-file=/assets/manifests/cluster-config.yaml \
			--dest-dir=/assets/mco-bootstrap \
			--machine-config-controller-image=${MACHINE_CONFIG_CONTROLLER_IMAGE} \
			--machine-config-server-image=${MACHINE_CONFIG_SERVER_IMAGE} \
			--machine-config-daemon-image=${MACHINE_CONFIG_DAEMON_IMAGE} \

	# Bootstrap MachineConfigController uses /etc/mcc/bootstrap/manifests/ dir to
	# 1. read the controller config rendered by MachineConfigOperator
	# 2. read the default MachineConfigPools rendered by MachineConfigOperator
	# 3. read any additional MachineConfigs that are needed for the default MachineConfigPools.
	mkdir --parents /etc/mcc/bootstrap/manifests /etc/kubernetes/manifests/
	cp mco-bootstrap/manifests/* /etc/mcc/bootstrap/manifests/
	cp mco-bootstrap/machineconfigoperator-bootstrap-pod.yaml /etc/kubernetes/manifests/

	# /etc/ssl/mcs/tls.{crt, key} are locations for MachineConfigServer's tls assets.
	mkdir --parents /etc/ssl/mcs/
	cp tls/machine-config-server.crt /etc/ssl/mcs/tls.crt
	cp tls/machine-config-server.key /etc/ssl/mcs/tls.key
fi

# We originally wanted to run the etcd cert signer as
# a static pod, but kubelet could't remove static pod
# when API server is not up, so we have to run this as
# podman container.
# See https://github.com/kubernetes/kubernetes/issues/43292

echo "Starting etcd certificate signer..."

trap "podman rm --force etcd-signer" ERR

# shellcheck disable=SC2154
podman run \
	--name etcd-signer \
	--detach \
	--volume /opt/tectonic/tls:/opt/tectonic/tls:ro,z \
	--network host \
	"{{.EtcdCertSignerImage}}" \
	serve \
	--cacrt=/opt/tectonic/tls/etcd-client-ca.crt \
	--cakey=/opt/tectonic/tls/etcd-client-ca.key \
	--servcrt=/opt/tectonic/tls/apiserver.crt \
	--servkey=/opt/tectonic/tls/apiserver.key \
	--address=0.0.0.0:6443 \
	--csrdir=/tmp \
	--peercertdur=26280h \
	--servercertdur=26280h

echo "Waiting for etcd cluster..."

# Wait for the etcd cluster to come up.
# shellcheck disable=SC2154,SC2086
until podman run \
		--rm \
		--network host \
		--name etcdctl \
		--env ETCDCTL_API=3 \
		--volume /opt/tectonic/tls:/opt/tectonic/tls:ro,z \
		"{{.EtcdctlImage}}" \
		/usr/local/bin/etcdctl \
		--dial-timeout=10m \
		--cacert=/opt/tectonic/tls/etcd-client-ca.crt \
		--cert=/opt/tectonic/tls/etcd-client.crt \
		--key=/opt/tectonic/tls/etcd-client.key \
		--endpoints={{.EtcdCluster}} \
		endpoint health
do
	echo "etcdctl failed. Retrying in 5 seconds..."
	sleep 5
done

echo "etcd cluster up. Killing etcd certificate signer..."

podman rm --force etcd-signer
rm --force /etc/kubernetes/manifests/machineconfigoperator-bootstrap-pod.yaml

echo "Starting bootkube..."

# shellcheck disable=SC2154
podman run \
	--rm \
	--volume "$PWD:/assets:z" \
	--volume /etc/kubernetes:/etc/kubernetes:z \
	--network=host \
	--entrypoint=/bootkube \
	"{{.BootkubeImage}}" \
	start --asset-dir=/assets --required-pods kube-system/pod-checkpointer,openshift-kube-apiserver/openshift-kube-apiserver,kube-system/kube-scheduler,kube-system/kube-controller-manager,openshift-cluster-version/cluster-version-operator

# Workaround for https://github.com/opencontainers/runc/pull/1807
touch /opt/tectonic/.bootkube.done
`))
)

var (
	// BootkubeConfigOverrides contains the configuration override files passed to the render commands of the components.
	// These are supposed to be customized by the installer where the config differs from the operator render default.
	BootkubeConfigOverrides = []*template.Template{
		KubeApiserverConfigOverridesTemplate,
		KubeControllerManagerConfigOverridesTemplate,
	}
)

var (
	// KubeApiserverConfigOverridesTemplate are overrides that the installer passes to the default config of the
	// kube-apiserver rendered by the cluster-kube-apiserver-operator.
	KubeApiserverConfigOverridesTemplate = template.Must(template.New("kube-apiserver-config-overrides.yaml").Parse(`
apiVersion: kubecontrolplane.config.openshift.io/v1
kind: KubeAPIServerConfig
kubeletClientInfo:
  ca: "" # kubelet uses self-signed serving certs. TODO: fix kubelet pki
`))

	// KubeControllerManagerConfigOverridesTemplate are overrides that the installer passes to the default config of the
	// kube-controller-manager rendered by the cluster-kube-controller-manager-operator.
	KubeControllerManagerConfigOverridesTemplate = template.Must(template.New("kube-controller-manager-config-overrides.yaml").Parse(`
apiVersion: kubecontrolplane.config.openshift.io/v1
kind: KubeControllerManagerConfig
`))
)
<|endoftext|>


<commit_before>package sqlread

type SummaryColumn struct {
	Name string
	Type string
}

type SummaryDataLoc struct {
	Start LexItem
	End   LexItem
}

type SummaryTree map[string]SummaryTable

type SummaryTable struct {
	Create   LexItem
	Cols     []SummaryColumn
	DataLocs []SummaryDataLoc
}

type SummaryParser struct {
	Tree SummaryTree
}

func NewSummaryParser() *SummaryParser {
	return &SummaryParser{
		Tree: make(SummaryTree),
	}
}

func (t *SummaryParser) ParseStart(p *Parser) parseState {
	for {
		c, ok := p.scan()
		if !ok {
			break
		}

		if isOfAny(c, TCreateTable) {
			return t.parseCreate
		}

		if isOfAny(c, TInsertInto) {
			return t.parseInsertIntoBuilder(c)
		}

		skips := []lexItemType{TComment, TDelim, TSemi, TDropTableFullStmt, TLockTableFullStmt, TUnlockTablesFullStmt, TSetFullStmt}
		if isOfAny(c, skips...) {
			continue
		}

		expects := append(skips, TCreateTable, TInsertInto)
		p.errorUnexpectedLex(c, expects...)
		break
	}
	return nil
}

func (t *SummaryParser) parseCreate(p *Parser) parseState {
	c, ok := p.scan()
	if !ok {
		p.errorUnexpectedEOF()
		return nil
	}
	if c.Type != TIdentifier {
		p.errorUnexpectedLex(c, TIdentifier)
		return nil
	}

	if _, ok := t.Tree[c.Val]; !ok {
		t.Tree[c.Val] = SummaryTable{
			Create: c,
			Cols:   make([]SummaryColumn, 0),
		}
	}

	for {
		x, ok := p.scanUntil(TIdentifier, TSemi)
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}

		if x.Type == TSemi {
			return t.ParseStart
		}

		y, ok := p.scan()
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}
		if y.Type != TColumnType {
			p.errorUnexpectedLex(y, TColumnType)
			return nil
		}

		v := t.Tree[c.Val]

		v.Cols = append(v.Cols, SummaryColumn{
			Name: x.Val,
			Type: y.Val,
		})

		t.Tree[c.Val] = v
	}
}

func (t *SummaryParser) parseInsertIntoBuilder(il LexItem) parseState {
	return func(p *Parser) parseState {
		c, ok := p.scan()
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}
		if c.Type != TIdentifier {
			p.errorUnexpectedLex(c, TIdentifier)
			return nil
		}

		s, ok := p.scanUntil(TSemi)
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}

		v := t.Tree[c.Val]

		v.DataLocs = append(v.DataLocs, SummaryDataLoc{
			Start: il,
			End:   s,
		})

		t.Tree[c.Val] = v

		return t.ParseStart
	}
}
<commit_msg>Add Start and End knowledge to Create Table<commit_after>package sqlread

type SummaryColumn struct {
	Name string
	Type string
}

type SummaryDataLoc struct {
	Start LexItem
	End   LexItem
}

type SummaryTree map[string]SummaryTable

type SummaryTable struct {
	Create   LexItem
	Cols     []SummaryColumn
	DataLocs []SummaryDataLoc

	SummaryDataLoc
}

type SummaryParser struct {
	Tree SummaryTree
}

func NewSummaryParser() *SummaryParser {
	return &SummaryParser{
		Tree: make(SummaryTree),
	}
}

func (t *SummaryParser) ParseStart(p *Parser) parseState {
	for {
		c, ok := p.scan()
		if !ok {
			break
		}

		if isOfAny(c, TCreateTable) {
			return t.parseCreateBuilder(c)
		}

		if isOfAny(c, TInsertInto) {
			return t.parseInsertIntoBuilder(c)
		}

		skips := []lexItemType{TComment, TDelim, TSemi, TDropTableFullStmt, TLockTableFullStmt, TUnlockTablesFullStmt, TSetFullStmt}
		if isOfAny(c, skips...) {
			continue
		}

		expects := append(skips, TCreateTable, TInsertInto)
		p.errorUnexpectedLex(c, expects...)
		break
	}
	return nil
}

func (t *SummaryParser) parseCreateBuilder(start LexItem) parseState {
	return func(p *Parser) parseState {
		c, ok := p.scan()
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}
		if c.Type != TIdentifier {
			p.errorUnexpectedLex(c, TIdentifier)
			return nil
		}

		if _, ok := t.Tree[c.Val]; !ok {
			t.Tree[c.Val] = SummaryTable{
				Create: c,
				Cols:   make([]SummaryColumn, 0),
				SummaryDataLoc: SummaryDataLoc{
					Start: start,
				},
			}
		}

		for {
			x, ok := p.scanUntil(TIdentifier, TSemi)
			if !ok {
				p.errorUnexpectedEOF()
				return nil
			}

			if x.Type == TSemi {
				et, _ := t.Tree[c.Val]
				et.End = x
				t.Tree[c.Val] = et

				return t.ParseStart
			}

			y, ok := p.scan()
			if !ok {
				p.errorUnexpectedEOF()
				return nil
			}
			if y.Type != TColumnType {
				p.errorUnexpectedLex(y, TColumnType)
				return nil
			}

			v := t.Tree[c.Val]

			v.Cols = append(v.Cols, SummaryColumn{
				Name: x.Val,
				Type: y.Val,
			})

			t.Tree[c.Val] = v
		}
	}
}

func (t *SummaryParser) parseInsertIntoBuilder(il LexItem) parseState {
	return func(p *Parser) parseState {
		c, ok := p.scan()
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}
		if c.Type != TIdentifier {
			p.errorUnexpectedLex(c, TIdentifier)
			return nil
		}

		s, ok := p.scanUntil(TSemi)
		if !ok {
			p.errorUnexpectedEOF()
			return nil
		}

		v := t.Tree[c.Val]

		v.DataLocs = append(v.DataLocs, SummaryDataLoc{
			Start: il,
			End:   s,
		})

		t.Tree[c.Val] = v

		return t.ParseStart
	}
}
<|endoftext|>