<commit_before>package config

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
)

const Version = "1.0.0"

const (
	DatabaseName   = "sufr.db"
	BucketNameRoot = "sufr"
	BucketNameURL  = "url"
	BucketNameUser = "user"
	BucketNameTag  = "tag"
	DBFileMode     = 0755
)

var (
	ApplicationBind string
	BuildTime       string
	BuildGitHash    string
	DataDir         string
	DatabaseFile    string
	TemplateDir     string
	StaticDir       string
	RootDir         string
	Debug           bool

	ErrDatabaseAlreadyOpen = errors.New("Database is already open")
	ErrKeyNotFound         = errors.New("Key doesn't exist in DB")
)

func New() {
	RootDir = findWorkingDir()

	flag.StringVar(&ApplicationBind, "bind", "localhost:8090", "Host and port to bind to")

	//TODO(kt): handle windows configuration dir
	defaultDataDir := fmt.Sprintf(path.Join(os.Getenv("HOME"), ".config", "sufr", "data"))
	flag.StringVar(&DataDir, "data-dir", defaultDataDir, "Location to store data in")

	defaultTemplateDir := path.Join(RootDir, "templates")
	flag.StringVar(&TemplateDir, "template-dir", defaultTemplateDir, "Location where templates are stored")

	defaultStaticDir := path.Join(RootDir, "static")
	flag.StringVar(&StaticDir, "static-dir", defaultStaticDir, "Location where static assets are stored")

	flag.BoolVar(&Debug, "debug", false, "Turn debugging on")

	flag.Parse()

	if _, err := os.Stat(DataDir); err != nil {
		if os.IsNotExist(err) {
			err := os.MkdirAll(DataDir, os.ModePerm)
			if err != nil {
				panic(err)
			}
		} else {
			panic(err)
		}
	}

	DatabaseFile = path.Join(DataDir, DatabaseName)
}

func execPath() (string, error) {
	f, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	return filepath.Abs(f)
}

// Tries to find the working directory (where templates and static files are).
// If it can't fetch it from the config file, it will just use the execution path.
// Returns a string
func findWorkingDir() string {
	path, err := execPath()
	if err != nil {
		panic("Cannot find exec path")
	}
	i := strings.LastIndex(path, "/")
	return path[:i]
}
<commit_msg>bumping version number to 1.1.0-dev<commit_after>package config

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
)

const Version = "1.1.0-dev"

const (
	DatabaseName   = "sufr.db"
	BucketNameRoot = "sufr"
	BucketNameURL  = "url"
	BucketNameUser = "user"
	BucketNameTag  = "tag"
	DBFileMode     = 0755
)

var (
	ApplicationBind string
	BuildTime       string
	BuildGitHash    string
	DataDir         string
	DatabaseFile    string
	TemplateDir     string
	StaticDir       string
	RootDir         string
	Debug           bool

	ErrDatabaseAlreadyOpen = errors.New("Database is already open")
	ErrKeyNotFound         = errors.New("Key doesn't exist in DB")
)

func New() {
	RootDir = findWorkingDir()

	flag.StringVar(&ApplicationBind, "bind", "localhost:8090", "Host and port to bind to")

	//TODO(kt): handle windows configuration dir
	defaultDataDir := fmt.Sprintf(path.Join(os.Getenv("HOME"), ".config", "sufr", "data"))
	flag.StringVar(&DataDir, "data-dir", defaultDataDir, "Location to store data in")

	defaultTemplateDir := path.Join(RootDir, "templates")
	flag.StringVar(&TemplateDir, "template-dir", defaultTemplateDir, "Location where templates are stored")

	defaultStaticDir := path.Join(RootDir, "static")
	flag.StringVar(&StaticDir, "static-dir", defaultStaticDir, "Location where static assets are stored")

	flag.BoolVar(&Debug, "debug", false, "Turn debugging on")

	flag.Parse()

	if _, err := os.Stat(DataDir); err != nil {
		if os.IsNotExist(err) {
			err := os.MkdirAll(DataDir, os.ModePerm)
			if err != nil {
				panic(err)
			}
		} else {
			panic(err)
		}
	}

	DatabaseFile = path.Join(DataDir, DatabaseName)
}

func execPath() (string, error) {
	f, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	return filepath.Abs(f)
}

// Tries to find the working directory (where templates and static files are).
// If it can't fetch it from the config file, it will just use the execution path.
// Returns a string
func findWorkingDir() string {
	path, err := execPath()
	if err != nil {
		panic("Cannot find exec path")
	}
	i := strings.LastIndex(path, "/")
	return path[:i]
}
<|endoftext|>


<commit_before>package config

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/nullbio/abcweb/strmangle"
	"github.com/nullbio/shift"
	"github.com/spf13/afero"
)

// AppFS is a handle to the filesystem in use
var AppFS = afero.NewOsFs()

// DBConfig holds the configuration variables contained in the database.toml
// file for the environment currently loaded (obtained from GetDatabaseEnv())
type DBConfig struct {
	DB      string
	Host    string
	Port    int
	DBName  string
	User    string
	Pass    string
	SSLMode string
	// Other SQLBoiler flags
	Blacklist        []string
	Whitelist        []string
	Tag              []string
	BaseDir          string
	Output           string
	PkgName          string
	Schema           string
	TinyintNotBool   bool
	NoAutoTimestamps bool
	Debug            bool
	NoHooks          bool
	NoTests          bool
}

// AppConfig holds the relevant generated app config.toml file variables
type AppConfig struct {
	DefaultEnv string `toml:"default_env"`
}

// LoadDBConfig loads the config vars in database.toml into a DBConfig object
func LoadDBConfig(appPath string, env string) *DBConfig {
	cfg := &DBConfig{}
	appName := GetAppName(appPath)
	configPath := filepath.Join(appPath, "database.toml")

	err := shift.Load(cfg, configPath, strmangle.EnvAppName(appName), env)
	if err != nil {
		log.Fatal("unable to load database.toml:", err)
	}

	return cfg
}

// GetActiveEnv attempts to get the config.toml and database.toml environment
// to load by checking the following, in the following order:
// 1. environment variable $APPNAME_ENV (APPNAME is envAppName variable value)
// 2. config.toml "default_env"
func GetActiveEnv(appPath string) string {
	appName := strmangle.EnvAppName(GetAppName(appPath))

	val := os.Getenv(appName + "_ENV")
	if val != "" {
		return val
	}

	contents, err := afero.ReadFile(AppFS, filepath.Join(appPath, "config.toml"))
	if err != nil {
		log.Fatal("unable to read config.toml file:", err)
	}

	var config AppConfig

	_, err = toml.Decode(string(contents), &config)
	if err != nil {
		log.Fatal("unable to decode config.toml file:", err)
	}

	return config.DefaultEnv
}

// GetAppPath executes the git cmd "git rev-parse --show-toplevel" to obtain
// the full path of the current app. The last folder in the path is the app name.
func GetAppPath() string {
	gitCmd := exec.Command("git", "rev-parse", "--show-toplevel")

	b := &bytes.Buffer{}
	gitCmd.Stdout = b

	err := gitCmd.Run()
	if err != nil {
		log.Fatal("Cannot execute git command:", err)
	}

	output := b.String()

	if len(output) == 0 {
		log.Fatalln("No output for git command")
	}

	return strings.TrimSpace(output)
}

// GetAppName gets the appname portion of a project path
func GetAppName(appPath string) string {
	split := strings.Split(appPath, string(os.PathSeparator))
	return split[len(split)-1]
}
<commit_msg>assign apppath to config.AppPath global<commit_after>package config

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/nullbio/abcweb/strmangle"
	"github.com/nullbio/shift"
	"github.com/spf13/afero"
)

// AppFS is a handle to the filesystem in use
var AppFS = afero.NewOsFs()

// AppPath is the path to the project, set using the init function
var AppPath string

func init() {
	AppPath = GetAppPath()
}

// DBConfig holds the configuration variables contained in the database.toml
// file for the environment currently loaded (obtained from GetDatabaseEnv())
type DBConfig struct {
	DB      string
	Host    string
	Port    int
	DBName  string
	User    string
	Pass    string
	SSLMode string
	// Other SQLBoiler flags
	Blacklist        []string
	Whitelist        []string
	Tag              []string
	BaseDir          string
	Output           string
	PkgName          string
	Schema           string
	TinyintNotBool   bool
	NoAutoTimestamps bool
	Debug            bool
	NoHooks          bool
	NoTests          bool
}

// AppConfig holds the relevant generated app config.toml file variables
type AppConfig struct {
	DefaultEnv string `toml:"default_env"`
}

// LoadDBConfig loads the config vars in database.toml into a DBConfig object
func LoadDBConfig(appPath string, env string) *DBConfig {
	cfg := &DBConfig{}
	appName := GetAppName(appPath)
	configPath := filepath.Join(appPath, "database.toml")

	err := shift.Load(cfg, configPath, strmangle.EnvAppName(appName), env)
	if err != nil {
		log.Fatal("unable to load database.toml:", err)
	}

	return cfg
}

// GetActiveEnv attempts to get the config.toml and database.toml environment
// to load by checking the following, in the following order:
// 1. environment variable $APPNAME_ENV (APPNAME is envAppName variable value)
// 2. config.toml "default_env"
func GetActiveEnv(appPath string) string {
	appName := strmangle.EnvAppName(GetAppName(appPath))

	val := os.Getenv(appName + "_ENV")
	if val != "" {
		return val
	}

	contents, err := afero.ReadFile(AppFS, filepath.Join(appPath, "config.toml"))
	if err != nil {
		log.Fatal("unable to read config.toml file:", err)
	}

	var config AppConfig

	_, err = toml.Decode(string(contents), &config)
	if err != nil {
		log.Fatal("unable to decode config.toml file:", err)
	}

	return config.DefaultEnv
}

// GetAppPath executes the git cmd "git rev-parse --show-toplevel" to obtain
// the full path of the current app. The last folder in the path is the app name.
func GetAppPath() string {
	if len(AppPath) > 0 {
		return AppPath
	}

	gitCmd := exec.Command("git", "rev-parse", "--show-toplevel")

	b := &bytes.Buffer{}
	gitCmd.Stdout = b

	err := gitCmd.Run()
	if err != nil {
		log.Fatal("Cannot execute git command:", err)
	}

	output := b.String()

	if len(output) == 0 {
		log.Fatalln("No output for git command")
	}

	return strings.TrimSpace(output)
}

// GetAppName gets the appname portion of a project path
func GetAppName(appPath string) string {
	split := strings.Split(appPath, string(os.PathSeparator))
	return split[len(split)-1]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"github.com/Sirupsen/logrus"
)

type Instance struct {
	time *InstanceTime
	name map[ClientID]ClientName

	g *Game
	r InstanceInput
	w InstanceOutputWriter
}

// NewInstance returns a Instance
func NewInstance(r InstanceInput, w InstanceOutputWriter) *Instance {
	time := new(InstanceTime)
	return &Instance{
		time: time,
		name: make(map[ClientID]ClientName),

		g: NewGame(time, w),
		r: r,
		w: w,
	}
}

// Run starts the instance routine
func (i *Instance) Run() {
	t := time.Tick(RealGameTick)
	for {
		select {
		case <-t:
			*i.time = i.time.Add(GameTick)
			if i.time.IsRegenerationTick() {
				i.g.PerformRegenerationTick()
			}
			if i.time.IsPeriodicalTick() {
				i.g.PerformPeriodicalTick()
			}
			i.g.PerformGameTick()
		case input, ok := <-i.r:
			if !ok {
				log.Fatal("Cannot read from the input channel")
			}
			id := input.ClientID
			switch input := input.Input.(type) {
			case InputConnect:
				i.connect(id, input)
			case InputDisconnect:
				i.disconnect(id, input)
			case InputChat:
				i.chat(id, input)
			case InputStage:
			case InputJoin:
				i.join(id, input)
			case InputLeave:
				i.leave(id, input)
			case InputAbility:
				i.ability(id, input)
			case InputInterrupt:
			default:
				log.Fatal("Unknown input type")
			}
		}
	}
}

// connect
func (i *Instance) connect(id ClientID, input InputConnect) {
	i.name[id] = input.ClientName

	i.w.BindClientID(id).Write(OutputMessage{
		Message: "Welcome to Crescent!",
	})
	i.w.Write(OutputMessage{
		Message: fmt.Sprintf("%s has connected.", input.ClientName),
	})
}

// disconnect
func (i *Instance) disconnect(id ClientID, input InputDisconnect) {
	name := i.name[id]
	delete(i.name, id)

	i.w.Write(OutputMessage{
		Message: fmt.Sprintf("%s has disconnected.", name),
	})
}

// chat
func (i *Instance) chat(id ClientID, input InputChat) {
	name := i.name[id]
	message := input.Message

	i.w.Write(OutputChat{
		ClientName: i.name[id],
		Message:    input.Message,
	})
	log.WithFields(logrus.Fields{
		"type":    "chat",
		"name":    name,
		"message": message,
	}).Infof("%s: %s", name, message)
}

// join
func (i *Instance) join(id ClientID, input InputJoin) {
	// TODO WIP
	class := NewClassHealer()
	u, err := i.g.units.Join(0, UnitName(i.name[id]), class)
	if err != nil {
		return
	}
	i.w.Write(OutputUnitJoin{
		UnitID:       u.ID(),
		UnitGroup:    u.Group(),
		UnitPosition: u.Position(),
		UnitName:     u.Name(),
		ClassName:    u.ClassName(),
		Health:       u.Health(),
		HealthMax:    u.HealthMax(),
		Mana:         u.Mana(),
		ManaMax:      u.ManaMax(),
	})
}

// leave
func (i *Instance) leave(id ClientID, input InputLeave) {
	// TODO WIP
	i.g.units.Leave(0)
	i.w.Write(OutputUnitLeave{
		UnitID: 0,
	})
}

// ability
func (i *Instance) ability(id ClientID, input InputAbility) {
	// TODO WIP
	u := i.g.units.Find(0)
	if input.ObjectUnitID == nil {
		i.g.Activating(u, nil, u.Ability(input.AbilityName))
	} else {
		i.g.Activating(u, i.g.units.Find(*input.ObjectUnitID), u.Ability(input.AbilityName))
	}
}
<commit_msg>Add comments<commit_after>package main

import (
	"fmt"
	"time"

	"github.com/Sirupsen/logrus"
)

type Instance struct {
	time *InstanceTime
	name map[ClientID]ClientName

	g *Game
	r InstanceInput
	w InstanceOutputWriter
}

// NewInstance returns a Instance
func NewInstance(r InstanceInput, w InstanceOutputWriter) *Instance {
	time := new(InstanceTime)
	return &Instance{
		time: time,
		name: make(map[ClientID]ClientName),

		g: NewGame(time, w),
		r: r,
		w: w,
	}
}

// Run starts the instance routine
func (i *Instance) Run() {
	t := time.Tick(RealGameTick)
	for {
		select {
		case <-t:
			*i.time = i.time.Add(GameTick)
			if i.time.IsRegenerationTick() {
				i.g.PerformRegenerationTick()
			}
			if i.time.IsPeriodicalTick() {
				i.g.PerformPeriodicalTick()
			}
			i.g.PerformGameTick()
		case input, ok := <-i.r:
			if !ok {
				log.Fatal("Cannot read from the input channel")
			}
			id := input.ClientID
			switch input := input.Input.(type) {
			case InputConnect:
				i.connect(id, input)
			case InputDisconnect:
				i.disconnect(id, input)
			case InputChat:
				i.chat(id, input)
			case InputStage:
				// TODO WIP
			case InputJoin:
				i.join(id, input)
			case InputLeave:
				i.leave(id, input)
			case InputAbility:
				i.ability(id, input)
			case InputInterrupt:
				// TODO WIP
			default:
				log.Fatal("Unknown input type")
			}
		}
	}
}

// connect
func (i *Instance) connect(id ClientID, input InputConnect) {
	i.name[id] = input.ClientName

	i.w.BindClientID(id).Write(OutputMessage{
		Message: "Welcome to Crescent!",
	})
	i.w.Write(OutputMessage{
		Message: fmt.Sprintf("%s has connected.", input.ClientName),
	})
}

// disconnect
func (i *Instance) disconnect(id ClientID, input InputDisconnect) {
	name := i.name[id]
	delete(i.name, id)

	i.w.Write(OutputMessage{
		Message: fmt.Sprintf("%s has disconnected.", name),
	})
}

// chat
func (i *Instance) chat(id ClientID, input InputChat) {
	name := i.name[id]
	message := input.Message

	i.w.Write(OutputChat{
		ClientName: i.name[id],
		Message:    input.Message,
	})
	log.WithFields(logrus.Fields{
		"type":    "chat",
		"name":    name,
		"message": message,
	}).Infof("%s: %s", name, message)
}

// join
func (i *Instance) join(id ClientID, input InputJoin) {
	// TODO WIP
	class := NewClassHealer()
	u, err := i.g.units.Join(0, UnitName(i.name[id]), class)
	if err != nil {
		return
	}
	i.w.Write(OutputUnitJoin{
		UnitID:       u.ID(),
		UnitGroup:    u.Group(),
		UnitPosition: u.Position(),
		UnitName:     u.Name(),
		ClassName:    u.ClassName(),
		Health:       u.Health(),
		HealthMax:    u.HealthMax(),
		Mana:         u.Mana(),
		ManaMax:      u.ManaMax(),
	})
}

// leave
func (i *Instance) leave(id ClientID, input InputLeave) {
	// TODO WIP
	i.g.units.Leave(0)
	i.w.Write(OutputUnitLeave{
		UnitID: 0,
	})
}

// ability
func (i *Instance) ability(id ClientID, input InputAbility) {
	// TODO WIP
	u := i.g.units.Find(0)
	if input.ObjectUnitID == nil {
		i.g.Activating(u, nil, u.Ability(input.AbilityName))
	} else {
		i.g.Activating(u, i.g.units.Find(*input.ObjectUnitID), u.Ability(input.AbilityName))
	}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Intel Corporation
//
// 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 bat contains a number of helper functions that can be used to perform
// various operations on a ciao cluster such as creating an instance or retrieving
// a list of all the defined workloads, etc.  All of these helper functions are
// implemented by calling ciao-cli rather than by using ciao's REST APIs.  This
// package is mainly intended for use by BAT tests.  Manipulating the cluster
// via ciao-cli, rather than through the REST APIs, allows us to test a little
// bit more of ciao.
package bat

import (
	"context"
	"fmt"
	"os"
	"strings"

	"gopkg.in/yaml.v2"
)

// Source is provided to the disk structure to indicate whether the
// disk should be cloned from a volume or an image.
type Source struct {
	Type string `yaml:"service"`
	ID   string `yaml:"id"`
}

// Disk describes the storage for the workload definition.
type Disk struct {
	ID        *string `yaml:"volume_id"`
	Size      int     `yaml:"size"`
	Bootable  bool    `yaml:"bootable"`
	Source    *Source `yaml:"source"`
	Ephemeral bool    `yaml:"ephemeral"`
}

// DefaultResources indicate how many cpus and mem to allocate.
type DefaultResources struct {
	VCPUs int `yaml:"vcpus"`
	MemMB int `yaml:"mem_mb"`
}

// WorkloadOptions is used to generate a workload definition in yaml.
type WorkloadOptions struct {
	Description     string           `yaml:"description"`
	VMType          string           `yaml:"vm_type"`
	FWType          string           `yaml:"fw_type"`
	ImageName       string           `yaml:"image_id"`
	Defaults        DefaultResources `yaml:"defaults"`
	CloudConfigFile string           `yaml:"cloud_init"`
	Disks           []Disk           `yaml:"disks"`
}

// this function should output the yaml file for the workload definition
func createWorkloadDefinition(filename string, opt WorkloadOptions) error {
	// take the cloud config file and output it to a file.
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	y, err := yaml.Marshal(opt)
	if err != nil {
		return err
	}

	_, err = f.Write(y)
	return err
}

// this function should output a cloud init file for the workload definition
func createCloudConfig(filename string, config string) error {
	// take the cloud config file and output it to a file.
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.WriteString(config)
	return err
}

func createWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string, public bool) (string, error) {
	// write out the cloud config.
	err := createCloudConfig("config.yaml", config)
	if err != nil {
		return "", err
	}
	defer os.Remove("config.yaml")

	opt.CloudConfigFile = "config.yaml"

	// write out the workload definition
	err = createWorkloadDefinition("workload.yaml", opt)
	if err != nil {
		return "", err
	}
	defer os.Remove("workload.yaml")

	// send the workload create command to ciao-cli
	args := []string{"workload", "create", "-yaml", "workload.yaml"}

	var data []byte
	if public {
		data, err = RunCIAOCLIAsAdmin(ctx, tenant, args)
	} else {
		data, err = RunCIAOCLI(ctx, tenant, args)
	}

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

	// get the returned workload ID
	s := strings.SplitAfter(string(data), ":")
	if len(s) != 2 {
		return "", fmt.Errorf("Problem parsing workload ID")
	}

	return strings.TrimSpace(s[1]), nil
}

// CreatePublicWorkload will call ciao-cli as admin to create a workload.
// It will first output the cloud init yaml file to the current working
// directory. Then it will output the workload definition to the current
// working directory. Finally it will call ciao-cli workload create -yaml
// to upload the workload definition. It will clean up all the files it
// created when it is done.
func CreatePublicWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string) (string, error) {
	return createWorkload(ctx, "", opt, config, true)
}

// CreateWorkload will call ciao-cli to create a workload definition.
// It will first output the cloud init yaml file to the current working
// directory. Then it will output the workload definition to the current
// working directory. Finally it will call ciao-cli workload create -yaml
// to upload the workload definition. It will clean up all the files it
// created when it is done.
func CreateWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string) (string, error) {
	return createWorkload(ctx, tenant, opt, config, false)
}

// GetAllWorkloads retrieves a list of all workloads in the cluster by calling
// ciao-cli workload list.  An error will be returned if the following
// environment variables are not set; CIAO_IDENTITY,  CIAO_CONTROLLER,
// CIAO_USERNAME, CIAO_PASSWORD.
func GetAllWorkloads(ctx context.Context, tenant string) ([]Workload, error) {
	var workloads []Workload

	args := []string{"workload", "list", "-f", "{{tojson .}}"}
	err := RunCIAOCLIJS(ctx, tenant, args, &workloads)
	if err != nil {
		return nil, err
	}

	return workloads, nil
}

// GetWorkloadByName will return a specific workload referenced by name.
// An error will be returned if either no workloads exist in the cluster,
// or if the specific workload does not exist. It inherits all error
// conditions of GetAllWorkloads.
func GetWorkloadByName(ctx context.Context, tenant string, name string) (Workload, error) {
	wls, err := GetAllWorkloads(ctx, tenant)
	if err != nil {
		return Workload{}, err
	}

	if len(wls) == 0 {
		return Workload{}, fmt.Errorf("No workloads defined for tenant %s", tenant)
	}

	for _, w := range wls {
		if w.Name == name {
			return w, nil
		}
	}

	return Workload{}, fmt.Errorf("No matching workload for %s", name)
}

// GetWorkloadByID will return a specific workload referenced by name.
// An error will be returned if either no workloads exist in the cluster,
// or if the specific workload does not exist. It inherits all error
// conditions of GetAllWorkloads.
func GetWorkloadByID(ctx context.Context, tenant string, ID string) (Workload, error) {
	wls, err := GetAllWorkloads(ctx, tenant)
	if err != nil {
		return Workload{}, err
	}

	if len(wls) == 0 {
		return Workload{}, fmt.Errorf("No workloads defined for tenant %s", tenant)
	}

	for _, w := range wls {
		if w.ID == ID {
			return w, nil
		}
	}

	return Workload{}, fmt.Errorf("No matching workload for %s", ID)
}
<commit_msg>bat: write workload yaml files to temp directory<commit_after>//
// Copyright (c) 2017 Intel Corporation
//
// 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 bat contains a number of helper functions that can be used to perform
// various operations on a ciao cluster such as creating an instance or retrieving
// a list of all the defined workloads, etc.  All of these helper functions are
// implemented by calling ciao-cli rather than by using ciao's REST APIs.  This
// package is mainly intended for use by BAT tests.  Manipulating the cluster
// via ciao-cli, rather than through the REST APIs, allows us to test a little
// bit more of ciao.
package bat

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"gopkg.in/yaml.v2"
)

// Source is provided to the disk structure to indicate whether the
// disk should be cloned from a volume or an image.
type Source struct {
	Type string `yaml:"service"`
	ID   string `yaml:"id"`
}

// Disk describes the storage for the workload definition.
type Disk struct {
	ID        *string `yaml:"volume_id"`
	Size      int     `yaml:"size"`
	Bootable  bool    `yaml:"bootable"`
	Source    *Source `yaml:"source"`
	Ephemeral bool    `yaml:"ephemeral"`
}

// DefaultResources indicate how many cpus and mem to allocate.
type DefaultResources struct {
	VCPUs int `yaml:"vcpus"`
	MemMB int `yaml:"mem_mb"`
}

// WorkloadOptions is used to generate a workload definition in yaml.
type WorkloadOptions struct {
	Description     string           `yaml:"description"`
	VMType          string           `yaml:"vm_type"`
	FWType          string           `yaml:"fw_type"`
	ImageName       string           `yaml:"image_id"`
	Defaults        DefaultResources `yaml:"defaults"`
	CloudConfigFile string           `yaml:"cloud_init"`
	Disks           []Disk           `yaml:"disks"`
}

// this function should output the yaml file for the workload definition
func createWorkloadDefinition(filename string, opt WorkloadOptions) error {
	// take the cloud config file and output it to a file.
	y, err := yaml.Marshal(opt)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(filename, y, 0644)
}

// this function should output a cloud init file for the workload definition
func createCloudConfig(filename string, config string) error {
	// take the cloud config file and output it to a file.
	// convert string to bytes.
	return ioutil.WriteFile(filename, []byte(config), 0644)
}

func createWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string, public bool) (ID string, err error) {
	cwd, err := os.Getwd()
	if err != nil {
		return "", err
	}

	// create temp dir for the yaml files
	dir, err := ioutil.TempDir("", "ciao_bat")
	if err != nil {
		return "", err
	}

	// you have to call workload create from the same working dir
	// as you have placed your yaml files, so change into that dir.
	err = os.Chdir(dir)
	if err != nil {
		os.RemoveAll(dir)
		return "", err
	}

	// change back to cwd and clean up temp dir on exit.
	defer func() {
		chdirErr := os.Chdir(cwd)
		if err == nil {
			err = chdirErr
		}

		os.RemoveAll(dir)
	}()

	// write out the cloud config.
	err = createCloudConfig("config.yaml", config)
	if err != nil {
		return "", err
	}

	opt.CloudConfigFile = "config.yaml"

	// write out the workload definition
	err = createWorkloadDefinition("workload.yaml", opt)
	if err != nil {
		return "", err
	}

	// send the workload create command to ciao-cli
	args := []string{"workload", "create", "-yaml", "workload.yaml"}

	var data []byte
	if public {
		data, err = RunCIAOCLIAsAdmin(ctx, tenant, args)
	} else {
		data, err = RunCIAOCLI(ctx, tenant, args)
	}

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

	// get the returned workload ID
	s := strings.SplitAfter(string(data), ":")
	if len(s) != 2 {
		return "", fmt.Errorf("Problem parsing workload ID")
	}

	return strings.TrimSpace(s[1]), nil
}

// CreatePublicWorkload will call ciao-cli as admin to create a workload.
// It will first output the cloud init yaml file to the current working
// directory. Then it will output the workload definition to the current
// working directory. Finally it will call ciao-cli workload create -yaml
// to upload the workload definition. It will clean up all the files it
// created when it is done.
func CreatePublicWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string) (string, error) {
	return createWorkload(ctx, "", opt, config, true)
}

// CreateWorkload will call ciao-cli to create a workload definition.
// It will first output the cloud init yaml file to the current working
// directory. Then it will output the workload definition to the current
// working directory. Finally it will call ciao-cli workload create -yaml
// to upload the workload definition. It will clean up all the files it
// created when it is done.
func CreateWorkload(ctx context.Context, tenant string, opt WorkloadOptions, config string) (string, error) {
	return createWorkload(ctx, tenant, opt, config, false)
}

// GetAllWorkloads retrieves a list of all workloads in the cluster by calling
// ciao-cli workload list.  An error will be returned if the following
// environment variables are not set; CIAO_IDENTITY,  CIAO_CONTROLLER,
// CIAO_USERNAME, CIAO_PASSWORD.
func GetAllWorkloads(ctx context.Context, tenant string) ([]Workload, error) {
	var workloads []Workload

	args := []string{"workload", "list", "-f", "{{tojson .}}"}
	err := RunCIAOCLIJS(ctx, tenant, args, &workloads)
	if err != nil {
		return nil, err
	}

	return workloads, nil
}

// GetWorkloadByName will return a specific workload referenced by name.
// An error will be returned if either no workloads exist in the cluster,
// or if the specific workload does not exist. It inherits all error
// conditions of GetAllWorkloads.
func GetWorkloadByName(ctx context.Context, tenant string, name string) (Workload, error) {
	wls, err := GetAllWorkloads(ctx, tenant)
	if err != nil {
		return Workload{}, err
	}

	if len(wls) == 0 {
		return Workload{}, fmt.Errorf("No workloads defined for tenant %s", tenant)
	}

	for _, w := range wls {
		if w.Name == name {
			return w, nil
		}
	}

	return Workload{}, fmt.Errorf("No matching workload for %s", name)
}

// GetWorkloadByID will return a specific workload referenced by name.
// An error will be returned if either no workloads exist in the cluster,
// or if the specific workload does not exist. It inherits all error
// conditions of GetAllWorkloads.
func GetWorkloadByID(ctx context.Context, tenant string, ID string) (Workload, error) {
	wls, err := GetAllWorkloads(ctx, tenant)
	if err != nil {
		return Workload{}, err
	}

	if len(wls) == 0 {
		return Workload{}, fmt.Errorf("No workloads defined for tenant %s", tenant)
	}

	for _, w := range wls {
		if w.ID == ID {
			return w, nil
		}
	}

	return Workload{}, fmt.Errorf("No matching workload for %s", ID)
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package vmx

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
)

type Encoder struct {
	// Buffer where the vmx file will be written to
	buffer *bytes.Buffer
	// Maximum recursion allowed
	maxRecursion uint8
	// Current recursion level
	currentRecursion uint8
	// Parent key, used for recursion. This will allow us to set the correct
	// keys for nested structures.
	parentKey string
}

// Creates a new encoder
func NewEncoder(buffer *bytes.Buffer) *Encoder {
	return &Encoder{
		buffer:       buffer,
		maxRecursion: 5,
	}
}

// Encodes Go structure into a VMX structure, recursively.
func (e *Encoder) Encode(v interface{}) error {
	val := reflect.ValueOf(v)
	return e.encode(val)
}

// Does the actual encoding work
func (e *Encoder) encode(val reflect.Value) error {
	// Drill into interfaces and pointers.
	// This can turn into an infinite loop given a cyclic chain,
	// but it matches the Go 1 behavior.
	for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return nil
		}
		val = val.Elem()
	}

	for i := 0; i < val.NumField(); i++ {
		valueField := val.Field(i)

		typeField := val.Type().Field(i)
		tag := typeField.Tag

		key, omitempty, err := parseTag(string(tag))
		if err != nil {
			return err
		}

		if key == "-" || !valueField.IsValid() ||
			omitempty && isEmptyValue(valueField) ||
			key == "" && !typeField.Anonymous {
			continue
		}

		switch valueField.Kind() {
		case reflect.Struct:
			err = e.encodeStruct(valueField, key)
		case reflect.Array, reflect.Slice:
			err = e.encodeArray(valueField, key)
		default:
			if e.parentKey != "" {
				key = e.parentKey + "." + key
			}
			e.buffer.WriteString(fmt.Sprintf("%s = \"%v\"\n", key, valueField.Interface()))
		}

		if err != nil {
			return err
		}
	}

	return nil
}

// When an array or slice type is found in the Go structure, this function encodes it
// recursively.
func (e *Encoder) encodeArray(valueField reflect.Value, key string) error {
	adaptersCnt := 0
	devicesCnt := 0

	for i := 0; i < valueField.Len(); i++ {
		switch key {
		case "ide":
			if i >= (MAX_IDE_ADAPTERS * MAX_IDE_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_IDE_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++

		case "scsi":
			if i >= (MAX_SCSI_ADAPTERS * MAX_SCSI_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_SCSI_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++
		case "sata":
			if i >= (MAX_SATA_ADAPTERS * MAX_SATA_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_SATA_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++
		case "usb":
			if i >= MAX_USB_ADAPTERS*MAX_USB_DEVICES {
				return nil
			}

			e.parentKey = fmt.Sprintf("%s:%d", key, devicesCnt)
			devicesCnt++
		case "ethernet":
			if i >= MAX_VNICS {
				return nil
			}
			e.parentKey = key + strconv.Itoa(i)
		default:
			e.parentKey = key + strconv.Itoa(i)
		}

		err := e.encode(valueField.Index(i))
		if err != nil {
			return err
		}
	}
	return nil
}

// Encodes a Go struct type into a VMX string, recursively.
func (e *Encoder) encodeStruct(valueField reflect.Value, key string) error {
	e.currentRecursion++
	if e.currentRecursion > e.maxRecursion {
		return nil
	}

	e.parentKey += key
	err := e.encode(valueField)
	if err != nil {
		return err
	}
	e.parentKey = ""
	e.currentRecursion--
	return nil
}

// Checks whether or not the reflected value is empty
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<commit_msg>remove blank line<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package vmx

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
)

type Encoder struct {
	// Buffer where the vmx file will be written to
	buffer *bytes.Buffer
	// Maximum recursion allowed
	maxRecursion uint8
	// Current recursion level
	currentRecursion uint8
	// Parent key, used for recursion. This will allow us to set the correct
	// keys for nested structures.
	parentKey string
}

// Creates a new encoder
func NewEncoder(buffer *bytes.Buffer) *Encoder {
	return &Encoder{
		buffer:       buffer,
		maxRecursion: 5,
	}
}

// Encodes Go structure into a VMX structure, recursively.
func (e *Encoder) Encode(v interface{}) error {
	val := reflect.ValueOf(v)
	return e.encode(val)
}

// Does the actual encoding work
func (e *Encoder) encode(val reflect.Value) error {
	// Drill into interfaces and pointers.
	// This can turn into an infinite loop given a cyclic chain,
	// but it matches the Go 1 behavior.
	for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return nil
		}
		val = val.Elem()
	}

	for i := 0; i < val.NumField(); i++ {
		valueField := val.Field(i)
		typeField := val.Type().Field(i)
		tag := typeField.Tag

		key, omitempty, err := parseTag(string(tag))
		if err != nil {
			return err
		}

		if key == "-" || !valueField.IsValid() ||
			omitempty && isEmptyValue(valueField) ||
			key == "" && !typeField.Anonymous {
			continue
		}

		switch valueField.Kind() {
		case reflect.Struct:
			err = e.encodeStruct(valueField, key)
		case reflect.Array, reflect.Slice:
			err = e.encodeArray(valueField, key)
		default:
			if e.parentKey != "" {
				key = e.parentKey + "." + key
			}
			e.buffer.WriteString(fmt.Sprintf("%s = \"%v\"\n", key, valueField.Interface()))
		}

		if err != nil {
			return err
		}
	}

	return nil
}

// When an array or slice type is found in the Go structure, this function encodes it
// recursively.
func (e *Encoder) encodeArray(valueField reflect.Value, key string) error {
	adaptersCnt := 0
	devicesCnt := 0

	for i := 0; i < valueField.Len(); i++ {
		switch key {
		case "ide":
			if i >= (MAX_IDE_ADAPTERS * MAX_IDE_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_IDE_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++

		case "scsi":
			if i >= (MAX_SCSI_ADAPTERS * MAX_SCSI_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_SCSI_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++
		case "sata":
			if i >= (MAX_SATA_ADAPTERS * MAX_SATA_DEVICES_PER_ADAPTER) {
				return nil
			}

			if devicesCnt >= MAX_SATA_DEVICES_PER_ADAPTER {
				adaptersCnt++
				devicesCnt = 0
			}

			e.parentKey = fmt.Sprintf("%s%d:%d", key, adaptersCnt, devicesCnt)
			devicesCnt++
		case "usb":
			if i >= MAX_USB_ADAPTERS*MAX_USB_DEVICES {
				return nil
			}

			e.parentKey = fmt.Sprintf("%s:%d", key, devicesCnt)
			devicesCnt++
		case "ethernet":
			if i >= MAX_VNICS {
				return nil
			}
			e.parentKey = key + strconv.Itoa(i)
		default:
			e.parentKey = key + strconv.Itoa(i)
		}

		err := e.encode(valueField.Index(i))
		if err != nil {
			return err
		}
	}
	return nil
}

// Encodes a Go struct type into a VMX string, recursively.
func (e *Encoder) encodeStruct(valueField reflect.Value, key string) error {
	e.currentRecursion++
	if e.currentRecursion > e.maxRecursion {
		return nil
	}

	e.parentKey += key
	err := e.encode(valueField)
	if err != nil {
		return err
	}
	e.parentKey = ""
	e.currentRecursion--
	return nil
}

// Checks whether or not the reflected value is empty
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<|endoftext|>


<commit_before>// nmon2influxdb
// import nmon report in InfluxDB
// author: adejoux@djouxtech.net

package main

import (
	"bufio"
	"fmt"
	"github.com/adejoux/influxdbclient"
	"github.com/codegangsta/cli"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

var hostRegexp = regexp.MustCompile(`^AAA,host,(\S+)`)
var osRegexp = regexp.MustCompile(`^AAA,.*(Linux|AIX)`)
var timeRegexp = regexp.MustCompile(`^ZZZZ,([^,]+),(.*)$`)
var intervalRegexp = regexp.MustCompile(`^AAA,interval,(\d+)`)
var headerRegexp = regexp.MustCompile(`^AAA|^BBB|^UARG|,T\d`)
var infoRegexp = regexp.MustCompile(`AAA,(.*)`)
var badRegexp = regexp.MustCompile(`,,`)
var cpuallRegexp = regexp.MustCompile(`^CPU\d+|^SCPU\d+|^PCPU\d+`)
var diskallRegexp = regexp.MustCompile(`^DISK`)
var skipRegexp = regexp.MustCompile(`T0000|^Z|^TOP,%CPU`)
var statsRegexp = regexp.MustCompile(`^[^,]+?,(T\d+)`)
var topRegexp = regexp.MustCompile(`^TOP,\d+,(T\d+)`)
var nfsRegexp = regexp.MustCompile(`^NFS`)
var nameRegexp = regexp.MustCompile(`(\d+)$`)

func NmonImport(c *cli.Context) {

	if len(c.Args()) < 1 {
		fmt.Printf("file name needs to be provided\n")
		os.Exit(1)
	}

	// parsing parameters
	params := ParseParameters(c)

	influxdb := influxdbclient.NewInfluxDB(params.Server, params.Port, params.Db, params.User, params.Password)
	influxdb.SetDebug(params.Debug)
	influxdb.Connect()
	if exist, _ := influxdb.ExistDB(params.Db); exist != true {
		_, err := influxdb.CreateDB(params.Db)
		check(err)
	}

	for _, nmon_file := range c.Args() {

		nmon := InitNmon(params, nmon_file)
		file, err := os.Open(nmon_file)
		check(err)

		defer file.Close()
		reader := bufio.NewReader(file)
		scanner := bufio.NewScanner(reader)
		scanner.Split(bufio.ScanLines)

		var lines []string

		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}

		sort.Strings(lines)

		for _, line := range lines {

			if cpuallRegexp.MatchString(line) && !params.CpuAll {
				continue
			}

			if diskallRegexp.MatchString(line) && params.NoDisks {
				continue
			}

			if skipRegexp.MatchString(line) {
				continue
			}

			if statsRegexp.MatchString(line) {
				matched := statsRegexp.FindStringSubmatch(line)
				elems := strings.Split(line, ",")
				name := elems[0]

				timeStr, err := nmon.GetTimeStamp(matched[1])
				check(err)

				timestamp, err := ConvertTimeStamp(timeStr, nmon.Params.TZ)

				for i, value := range elems[2:] {
					if len(nmon.DataSeries[name].Columns) < i+1 {
						if nmon.Debug {
							fmt.Printf(line)
							fmt.Printf("Entry added position %d in serie %s since nmon start: skipped\n", i+1, name)
						}
						continue
					}
					column := nmon.DataSeries[name].Columns[i]
					tags := map[string]string{"host": nmon.Hostname, "name": column}

					// try to convert string to integer
					converted, err := strconv.ParseFloat(value, 64)
					if err != nil {
						//if not working, skip to next value. We don't want text values in InfluxDB.
						continue
					}

					//send integer if it worked
					field := map[string]interface{}{"value": converted}

					measurement := ""
					if nfsRegexp.MatchString(name) {
						measurement = name
					} else {
						measurement = nameRegexp.ReplaceAllString(name, "")
					}

					influxdb.AddPoint(measurement, timestamp, field, tags)

					if influxdb.PointsCount() == 10000 {
						err = influxdb.WritePoints()
						check(err)
						influxdb.ClearPoints()
						fmt.Printf("#")
					}
				}
			}

			if topRegexp.MatchString(line) {
				matched := topRegexp.FindStringSubmatch(line)
				elems := strings.Split(line, ",")
				timeStr, err := nmon.GetTimeStamp(matched[1])
				check(err)
				timestamp, err := ConvertTimeStamp(timeStr, nmon.Params.TZ)

				if len(elems) < 14 {
					fmt.Printf("error TOP import:")
					fmt.Println(elems)
					continue
				}

				for i, value := range elems[3:12] {
					column := nmon.DataSeries["TOP"].Columns[i]

					var wlmclass string
					if len(elems) < 15 {
						wlmclass = "none"
					} else {
						wlmclass = elems[14]
					}

					tags := map[string]string{"host": nmon.Hostname, "name": column, "pid": elems[1], "command": elems[13], "wlm": wlmclass}

					// try to convert string to integer
					converted, err := strconv.ParseFloat(value, 64)
					if err != nil {
						//if not working, skip to next value. We don't want text values in InfluxDB.
						continue
					}

					//send integer if it worked
					field := map[string]interface{}{"value": converted}

					influxdb.AddPoint("TOP", timestamp, field, tags)

					if influxdb.PointsCount() == 10000 {
						err = influxdb.WritePoints()
						check(err)
						influxdb.ClearPoints()
						fmt.Printf("#")
					}
				}
			}
		}
		// flushing remaining data
		influxdb.WritePoints()
		fmt.Printf("#\n")

		fmt.Printf("File %s imported !\n", nmon_file)
	}
}
<commit_msg>check error when starting influxdb connection<commit_after>// nmon2influxdb
// import nmon report in InfluxDB
// author: adejoux@djouxtech.net

package main

import (
	"bufio"
	"fmt"
	"github.com/adejoux/influxdbclient"
	"github.com/codegangsta/cli"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

var hostRegexp = regexp.MustCompile(`^AAA,host,(\S+)`)
var osRegexp = regexp.MustCompile(`^AAA,.*(Linux|AIX)`)
var timeRegexp = regexp.MustCompile(`^ZZZZ,([^,]+),(.*)$`)
var intervalRegexp = regexp.MustCompile(`^AAA,interval,(\d+)`)
var headerRegexp = regexp.MustCompile(`^AAA|^BBB|^UARG|,T\d`)
var infoRegexp = regexp.MustCompile(`AAA,(.*)`)
var badRegexp = regexp.MustCompile(`,,`)
var cpuallRegexp = regexp.MustCompile(`^CPU\d+|^SCPU\d+|^PCPU\d+`)
var diskallRegexp = regexp.MustCompile(`^DISK`)
var skipRegexp = regexp.MustCompile(`T0000|^Z|^TOP,%CPU`)
var statsRegexp = regexp.MustCompile(`^[^,]+?,(T\d+)`)
var topRegexp = regexp.MustCompile(`^TOP,\d+,(T\d+)`)
var nfsRegexp = regexp.MustCompile(`^NFS`)
var nameRegexp = regexp.MustCompile(`(\d+)$`)

func NmonImport(c *cli.Context) {

	if len(c.Args()) < 1 {
		fmt.Printf("file name needs to be provided\n")
		os.Exit(1)
	}

	// parsing parameters
	params := ParseParameters(c)

	influxdb := influxdbclient.NewInfluxDB(params.Server, params.Port, params.Db, params.User, params.Password)
	influxdb.SetDebug(params.Debug)
	err := influxdb.Connect()
	check(err)

	if exist, _ := influxdb.ExistDB(params.Db); exist != true {
		_, err := influxdb.CreateDB(params.Db)
		check(err)
	}

	for _, nmon_file := range c.Args() {

		nmon := InitNmon(params, nmon_file)
		file, err := os.Open(nmon_file)
		check(err)

		defer file.Close()
		reader := bufio.NewReader(file)
		scanner := bufio.NewScanner(reader)
		scanner.Split(bufio.ScanLines)

		var lines []string

		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}

		sort.Strings(lines)

		for _, line := range lines {

			if cpuallRegexp.MatchString(line) && !params.CpuAll {
				continue
			}

			if diskallRegexp.MatchString(line) && params.NoDisks {
				continue
			}

			if skipRegexp.MatchString(line) {
				continue
			}

			if statsRegexp.MatchString(line) {
				matched := statsRegexp.FindStringSubmatch(line)
				elems := strings.Split(line, ",")
				name := elems[0]

				timeStr, err := nmon.GetTimeStamp(matched[1])
				check(err)

				timestamp, err := ConvertTimeStamp(timeStr, nmon.Params.TZ)

				for i, value := range elems[2:] {
					if len(nmon.DataSeries[name].Columns) < i+1 {
						if nmon.Debug {
							fmt.Printf(line)
							fmt.Printf("Entry added position %d in serie %s since nmon start: skipped\n", i+1, name)
						}
						continue
					}
					column := nmon.DataSeries[name].Columns[i]
					tags := map[string]string{"host": nmon.Hostname, "name": column}

					// try to convert string to integer
					converted, err := strconv.ParseFloat(value, 64)
					if err != nil {
						//if not working, skip to next value. We don't want text values in InfluxDB.
						continue
					}

					//send integer if it worked
					field := map[string]interface{}{"value": converted}

					measurement := ""
					if nfsRegexp.MatchString(name) {
						measurement = name
					} else {
						measurement = nameRegexp.ReplaceAllString(name, "")
					}

					influxdb.AddPoint(measurement, timestamp, field, tags)

					if influxdb.PointsCount() == 10000 {
						err = influxdb.WritePoints()
						check(err)
						influxdb.ClearPoints()
						fmt.Printf("#")
					}
				}
			}

			if topRegexp.MatchString(line) {
				matched := topRegexp.FindStringSubmatch(line)
				elems := strings.Split(line, ",")
				timeStr, err := nmon.GetTimeStamp(matched[1])
				check(err)
				timestamp, err := ConvertTimeStamp(timeStr, nmon.Params.TZ)

				if len(elems) < 14 {
					fmt.Printf("error TOP import:")
					fmt.Println(elems)
					continue
				}

				for i, value := range elems[3:12] {
					column := nmon.DataSeries["TOP"].Columns[i]

					var wlmclass string
					if len(elems) < 15 {
						wlmclass = "none"
					} else {
						wlmclass = elems[14]
					}

					tags := map[string]string{"host": nmon.Hostname, "name": column, "pid": elems[1], "command": elems[13], "wlm": wlmclass}

					// try to convert string to integer
					converted, err := strconv.ParseFloat(value, 64)
					if err != nil {
						//if not working, skip to next value. We don't want text values in InfluxDB.
						continue
					}

					//send integer if it worked
					field := map[string]interface{}{"value": converted}

					influxdb.AddPoint("TOP", timestamp, field, tags)

					if influxdb.PointsCount() == 10000 {
						err = influxdb.WritePoints()
						check(err)
						influxdb.ClearPoints()
						fmt.Printf("#")
					}
				}
			}
		}
		// flushing remaining data
		influxdb.WritePoints()
		fmt.Printf("#\n")

		fmt.Printf("File %s imported !\n", nmon_file)
	}
}
<|endoftext|>


<commit_before>package cart

import (
	"sync"
	"net/http"
	"os"
	"time"
)

type Engine struct {
	Router
	routers			map[string]*Router	//saved routers
	engine			*Engine
	pool        	sync.Pool
	tree			*node 	//match trees

	NotFound		HandlerFinal
}

var _ http.Handler = &Engine{}

var server *http.Server

func (e *Engine) allocateContext() *Context {
	return &Context{}
}

func (e *Engine) findRouter(absolutePath string) (*Router, bool) {
	router := e.routers[absolutePath]
	if router == nil {
		return nil, false
	}
	return router, true
}

func (e *Engine) getRouter(absolutePath string) *Router {
	router := e.routers[absolutePath]
	if router == nil {
		router = &Router{
			engine:e,
			Path:absolutePath,
			methods:make([]method,0),
		}
	}
	return router
}

func (e *Engine) addRoute(router *Router) {
	if router.Path[0] != '/' {
		panic("Path must begin with '/' in path '" + router.Path + "'")
	}
	if e.tree == nil {
		e.tree = &node{}
	}
	if _, found := e.tree.findCaseInsensitivePath(router.Path, true); !found {
		e.routers[router.Path] = router
		e.tree.addRoute(router.Path, router)
	}
}

func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := e.pool.Get().(*Context)
	c.reset(w, req)
	e.serveHTTP(c)
	e.pool.Put(c)
}

func (e *Engine) mixMethods(httpMethod string, r *Router) HandlerCompose {
	//http method find any
	var methods HandlerCompose
	if m, find := r.getMethod("ANY"); find {
		methods = compose(m)
	}
	if m, find := r.getMethod(httpMethod); find {
		if methods != nil {
			methods = compose(methods,m)
		} else {
			methods = compose(m)
		}
	}
	return methods
}

func (e *Engine) serveHTTP(c *Context) {
	path := c.Request.URL.Path
	httpMethod := c.Request.Method
	if root := e.tree; root != nil {
		if r, ps, tsr := root.getValue(path); r != nil {
			router := r.(*Router)
			c.Router = router
			c.Params = ps
			final := func() {
				if c.Response.Size() == -1 && c.Response.Status() == 200 {
					c.Response.WriteString("empty page")
				}
			}

			//methods
			methods := e.mixMethods(httpMethod, router)
			//middleware
			composed := router.composed
			if composed != nil && methods != nil {
				composed = compose(composed, methods)
			} else if composed == nil && methods != nil {
				composed = methods
			}
			if composed != nil {
				composed(c,final)()
			} else {
				final()
			}

			c.Response.WriteHeaderNow()
			return
		} else if httpMethod != "CONNECT" && path != "/" {
			code := 301 // Permanent redirect, request with GET method
			if httpMethod != "GET" {
				code = 307
			}
			if tsr {
				if len(path) > 1 && path[len(path)-1] == '/' {
					c.Request.URL.Path = path[:len(path)-1]
				} else {
					c.Request.URL.Path = path + "/"
				}
				http.Redirect(c.Response, c.Request, c.Request.URL.String(), code)
				return
			}
		}
	}
	//find / middleware

	final404 := func() {
		// 404 error
		c.Response.WriteHeader(404)
		if e.NotFound != nil {
			e.NotFound(c);
		} else {
			c.Response.WriteString("404 error")
		}
	}
	if r, find := e.findRouter("/"); find {
		r.composed(c,final404)()
	} else {
		final404()
	}
}

/*
init new Engine
 */
func (e *Engine) init() {
	e.Router = Router{
		Path: "/",
	}
	e.Router.engine = e
	e.pool.New = func() interface{} {
		return e.allocateContext()
	}
	e.tree = &node{}
	e.routers = make(map[string]*Router)
}
/*
Run the server
 */
func (e *Engine) Run(addr ...string) (err error) {
	defer func() { debugError(err) }()
	address := resolveAddress(addr)
	debugPrint("PID:%d Listening and serving HTTP on %s\n", os.Getpid(), address)

	server = &http.Server{
		Addr: address,
		Handler: e,
		ReadTimeout: time.Second * 90,
		//ReadHeaderTimeout: time.Second * 90,
		WriteTimeout: time.Second * 90,
		//IdleTimeout: time.Second * 90,
	}
	err = server.ListenAndServe()
	return
}

<commit_msg>add NotFound<commit_after>package cart

import (
	"sync"
	"net/http"
	"os"
	"time"
)

type Engine struct {
	Router
	routers			map[string]*Router	//saved routers
	engine			*Engine
	pool        	sync.Pool
	tree			*node 	//match trees

	NotFound		HandlerFinal
}

var _ http.Handler = &Engine{}

var server *http.Server

func (e *Engine) allocateContext() *Context {
	return &Context{}
}

func (e *Engine) findRouter(absolutePath string) (*Router, bool) {
	router := e.routers[absolutePath]
	if router == nil {
		return nil, false
	}
	return router, true
}

func (e *Engine) getRouter(absolutePath string) *Router {
	router := e.routers[absolutePath]
	if router == nil {
		router = &Router{
			engine:e,
			Path:absolutePath,
			methods:make([]method,0),
		}
	}
	return router
}

func (e *Engine) addRoute(router *Router) {
	if router.Path[0] != '/' {
		panic("Path must begin with '/' in path '" + router.Path + "'")
	}
	if e.tree == nil {
		e.tree = &node{}
	}
	if _, found := e.tree.findCaseInsensitivePath(router.Path, true); !found {
		e.routers[router.Path] = router
		e.tree.addRoute(router.Path, router)
	}
}

func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := e.pool.Get().(*Context)
	c.reset(w, req)
	e.serveHTTP(c)
	e.pool.Put(c)
}

func (e *Engine) mixMethods(httpMethod string, r *Router) HandlerCompose {
	//http method find any
	var methods HandlerCompose
	if m, find := r.getMethod("ANY"); find {
		methods = compose(m)
	}
	if m, find := r.getMethod(httpMethod); find {
		if methods != nil {
			methods = compose(methods,m)
		} else {
			methods = compose(m)
		}
	}
	return methods
}

func (e *Engine) serveHTTP(c *Context) {
	path := c.Request.URL.Path
	httpMethod := c.Request.Method

	final404 := func() {
		// 404 error
		c.Response.WriteHeader(404)
		if e.NotFound != nil {
			e.NotFound(c);
		} else {
			c.Response.WriteString("404 Not Found")
		}
	}

	if root := e.tree; root != nil {
		if r, ps, tsr := root.getValue(path); r != nil {
			router := r.(*Router)
			c.Router = router
			c.Params = ps

			//methods
			methods := e.mixMethods(httpMethod, router)
			//middleware
			composed := router.composed
			if composed != nil && methods != nil {
				composed = compose(composed, methods)
			} else if composed == nil && methods != nil {
				composed = methods
			}
			if composed != nil {
				composed(c,final404)()
			} else {
				final404()
			}

			c.Response.WriteHeaderNow()
			return
		} else if httpMethod != "CONNECT" && path != "/" {
			code := 301 // Permanent redirect, request with GET method
			if httpMethod != "GET" {
				code = 307
			}
			if tsr {
				if len(path) > 1 && path[len(path)-1] == '/' {
					c.Request.URL.Path = path[:len(path)-1]
				} else {
					c.Request.URL.Path = path + "/"
				}
				http.Redirect(c.Response, c.Request, c.Request.URL.String(), code)
				return
			}
		}
	}
	//find / middleware

	if r, find := e.findRouter("/"); find {
		r.composed(c,final404)()
	} else {
		final404()
	}
}

/*
init new Engine
 */
func (e *Engine) init() {
	e.Router = Router{
		Path: "/",
	}
	e.Router.engine = e
	e.pool.New = func() interface{} {
		return e.allocateContext()
	}
	e.tree = &node{}
	e.routers = make(map[string]*Router)
}
/*
Run the server
 */
func (e *Engine) Run(addr ...string) (err error) {
	defer func() { debugError(err) }()
	address := resolveAddress(addr)
	debugPrint("PID:%d Listening and serving HTTP on %s\n", os.Getpid(), address)

	server = &http.Server{
		Addr: address,
		Handler: e,
		ReadTimeout: time.Second * 90,
		//ReadHeaderTimeout: time.Second * 90,
		WriteTimeout: time.Second * 90,
		//IdleTimeout: time.Second * 90,
	}
	err = server.ListenAndServe()
	return
}

<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"runtime/pprof"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/node_exporter/collector"
)

const subsystem = "exporter"

var (
	configFile        = flag.String("config", "node_exporter.conf", "config file.")
	memProfile        = flag.String("memprofile", "", "write memory profile to this file")
	listeningAddress  = flag.String("listen", ":8080", "address to listen on")
	enabledCollectors = flag.String("enabledCollectors", "attributes,diskstats,filesystem,loadavg,meminfo,stat,time,netdev,netstat", "comma-seperated list of collectors to use")
	printCollectors   = flag.Bool("printCollectors", false, "If true, print available collectors and exit")

	collectorLabelNames = []string{"collector", "result"}

	scrapeDurations = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Namespace: collector.Namespace,
			Subsystem: subsystem,
			Name:      "scrape_duration_seconds",
			Help:      "node_exporter: Duration of a scrape job.",
		},
		collectorLabelNames,
	)
)

// Implements Collector.
type NodeCollector struct {
	collectors map[string]collector.Collector
}

// Implements Collector.
func (n NodeCollector) Describe(ch chan<- *prometheus.Desc) {
	scrapeDurations.Describe(ch)
}

// Implements Collector.
func (n NodeCollector) Collect(ch chan<- prometheus.Metric) {
	wg := sync.WaitGroup{}
	wg.Add(len(n.collectors))
	for name, c := range n.collectors {
		go func(name string, c collector.Collector) {
			Execute(name, c, ch)
			wg.Done()
		}(name, c)
	}
	wg.Wait()
	scrapeDurations.Collect(ch)
}

func Execute(name string, c collector.Collector, ch chan<- prometheus.Metric) {
	begin := time.Now()
	err := c.Update(ch)
	duration := time.Since(begin)
	var result string

	if err != nil {
		glog.Infof("ERROR: %s failed after %fs: %s", name, duration.Seconds(), err)
		result = "error"
	} else {
		glog.Infof("OK: %s success after %fs.", name, duration.Seconds())
		result = "success"
	}
	scrapeDurations.WithLabelValues(name, result).Observe(duration.Seconds())
}

func getConfig(file string) (*collector.Config, error) {
	config := &collector.Config{}
	glog.Infof("Reading config %s", *configFile)
	bytes, err := ioutil.ReadFile(*configFile)
	if err != nil {
		return nil, err
	}
	return config, json.Unmarshal(bytes, &config)
}

func loadCollectors(file string) (map[string]collector.Collector, error) {
	collectors := map[string]collector.Collector{}
	config, err := getConfig(file)
	if err != nil {
		return nil, fmt.Errorf("couldn't read config %s: %s", file, err)
	}
	for _, name := range strings.Split(*enabledCollectors, ",") {
		fn, ok := collector.Factories[name]
		if !ok {
			return nil, fmt.Errorf("collector '%s' not available", name)
		}
		c, err := fn(*config)
		if err != nil {
			return nil, err
		}
		collectors[name] = c
	}
	return collectors, nil
}

func main() {
	flag.Parse()
	if *printCollectors {
		fmt.Printf("Available collectors:\n")
		for n, _ := range collector.Factories {
			fmt.Printf(" - %s\n", n)
		}
		return
	}
	collectors, err := loadCollectors(*configFile)
	if err != nil {
		log.Fatalf("Couldn't load config and collectors: %s", err)
	}

	glog.Infof("Enabled collectors:")
	for n, _ := range collectors {
		glog.Infof(" - %s", n)
	}

	nodeCollector := NodeCollector{collectors: collectors}
	prometheus.MustRegister(nodeCollector)

	sigUsr1 := make(chan os.Signal)
	signal.Notify(sigUsr1, syscall.SIGUSR1)

	go func() {
		http.Handle("/metrics", prometheus.Handler())
		http.ListenAndServe(*listeningAddress, nil)
	}()

	for {
		select {
		case <-sigUsr1:
			glog.Infof("got signal")
			if *memProfile != "" {
				glog.Infof("Writing memory profile to %s", *memProfile)
				f, err := os.Create(*memProfile)
				if err != nil {
					log.Fatal(err)
				}
				pprof.WriteHeapProfile(f)
				f.Close()
			}
		}
	}

}
<commit_msg>Add Basic Auth support<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"runtime/pprof"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/node_exporter/collector"
)

const subsystem = "exporter"

var (
	configFile        = flag.String("config", "node_exporter.conf", "Path to config file.")
	memProfile        = flag.String("memprofile", "", "Write memory profile to this file.")
	listeningAddress  = flag.String("listen", ":8080", "Address to listen on.")
	enabledCollectors = flag.String("enabledCollectors", "attributes,diskstats,filesystem,loadavg,meminfo,stat,time,netdev,netstat", "Comma-separated list of collectors to use.")
	printCollectors   = flag.Bool("printCollectors", false, "If true, print available collectors and exit.")
	authUser          = flag.String("auth.user", "", "Username for basic auth.")
	authPass          = flag.String("auth.pass", "", "Password for basic auth.")

	collectorLabelNames = []string{"collector", "result"}

	scrapeDurations = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Namespace: collector.Namespace,
			Subsystem: subsystem,
			Name:      "scrape_duration_seconds",
			Help:      "node_exporter: Duration of a scrape job.",
		},
		collectorLabelNames,
	)
)

// Implements Collector.
type NodeCollector struct {
	collectors map[string]collector.Collector
}

// Implements Collector.
func (n NodeCollector) Describe(ch chan<- *prometheus.Desc) {
	scrapeDurations.Describe(ch)
}

// Implements Collector.
func (n NodeCollector) Collect(ch chan<- prometheus.Metric) {
	wg := sync.WaitGroup{}
	wg.Add(len(n.collectors))
	for name, c := range n.collectors {
		go func(name string, c collector.Collector) {
			Execute(name, c, ch)
			wg.Done()
		}(name, c)
	}
	wg.Wait()
	scrapeDurations.Collect(ch)
}

type basicAuthHandler struct {
	handler  http.HandlerFunc
	user     string
	password string
}

func (h *basicAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok || password != h.password || user != h.user {
		w.Header().Set("WWW-Authenticate", "Basic realm=\"metrics\"")
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}
	h.handler(w, r)
	return
}

func Execute(name string, c collector.Collector, ch chan<- prometheus.Metric) {
	begin := time.Now()
	err := c.Update(ch)
	duration := time.Since(begin)
	var result string

	if err != nil {
		glog.Infof("ERROR: %s failed after %fs: %s", name, duration.Seconds(), err)
		result = "error"
	} else {
		glog.Infof("OK: %s success after %fs.", name, duration.Seconds())
		result = "success"
	}
	scrapeDurations.WithLabelValues(name, result).Observe(duration.Seconds())
}

func getConfig(file string) (*collector.Config, error) {
	config := &collector.Config{}
	glog.Infof("Reading config %s", *configFile)
	bytes, err := ioutil.ReadFile(*configFile)
	if err != nil {
		return nil, err
	}
	return config, json.Unmarshal(bytes, &config)
}

func loadCollectors(file string) (map[string]collector.Collector, error) {
	collectors := map[string]collector.Collector{}
	config, err := getConfig(file)
	if err != nil {
		return nil, fmt.Errorf("couldn't read config %s: %s", file, err)
	}
	for _, name := range strings.Split(*enabledCollectors, ",") {
		fn, ok := collector.Factories[name]
		if !ok {
			return nil, fmt.Errorf("collector '%s' not available", name)
		}
		c, err := fn(*config)
		if err != nil {
			return nil, err
		}
		collectors[name] = c
	}
	return collectors, nil
}

func main() {
	flag.Parse()
	if *printCollectors {
		fmt.Printf("Available collectors:\n")
		for n, _ := range collector.Factories {
			fmt.Printf(" - %s\n", n)
		}
		return
	}
	collectors, err := loadCollectors(*configFile)
	if err != nil {
		log.Fatalf("Couldn't load config and collectors: %s", err)
	}

	glog.Infof("Enabled collectors:")
	for n, _ := range collectors {
		glog.Infof(" - %s", n)
	}

	nodeCollector := NodeCollector{collectors: collectors}
	prometheus.MustRegister(nodeCollector)

	sigUsr1 := make(chan os.Signal)
	signal.Notify(sigUsr1, syscall.SIGUSR1)

	handler := prometheus.Handler()
	if *authUser != "" || *authPass != "" {
		if *authUser == "" || *authPass == "" {
			glog.Fatal("You need to specify -auth.user and -auth.pass to enable basic auth")
		}
		handler = &basicAuthHandler{
			handler:  prometheus.Handler().ServeHTTP,
			user:     *authUser,
			password: *authPass,
		}
	}
	go func() {
		http.Handle("/metrics", handler)
		err := http.ListenAndServe(*listeningAddress, nil)
		if err != nil {
			glog.Fatal(err)
		}
	}()

	for {
		select {
		case <-sigUsr1:
			glog.Infof("got signal")
			if *memProfile != "" {
				glog.Infof("Writing memory profile to %s", *memProfile)
				f, err := os.Create(*memProfile)
				if err != nil {
					log.Fatal(err)
				}
				pprof.WriteHeapProfile(f)
				f.Close()
			}
		}
	}

}
<|endoftext|>


<commit_before>package main

import "fmt"
import "github.com/spiceworks/spicelog"
import "reflect"
import "bytes"
import "time"

type CodeEmitter interface {
	Emit(*panicWriter) error
	Imports() []string
}

type ColumnizedField struct {
	DataTypeDefn []interface{}
	Name         string
	DataType     string
}

type ColumnizedStruct struct {
	PluralModelName   string
	SingularModelName string
	ListTypeName      string
	Fields            []ColumnizedField
	Columns           []Column
	PrimaryKey        []ColumnizedField
	Unique            []ColumnizedField
	TableName         string

	TheColumnType *ColumnType
}

func NewColumnizedStruct(t Table,
	tableNameToStructNames func(string) (string, string),
	columnNameToFieldName func(string) string,
	columnnToDataType func(Column) []interface{}) (*ColumnizedStruct, error) {
	this := new(ColumnizedStruct)
	this.TableName = t.Name()

	this.PluralModelName, this.SingularModelName = tableNameToStructNames(t.Name())
	this.ListTypeName = fmt.Sprintf("%sList", this.SingularModelName)

	spicelog.Infof("Table %q Plural %q Singular %q",
		t.Name(),
		this.PluralModelName,
		this.SingularModelName)
	var err error
	this.Columns, err = t.Columns()
	if err != nil {
		return nil, err
	}

	primaryKey, err := t.PrimaryKey()
	if err != nil {
		return nil, err
	}
	primaryKeys := make(map[string]int)
	for _, v := range primaryKey {
		primaryKeys[v] = 0
	}

	unique, err := t.Unique()
	if err != nil {
		return nil, err
	}
	uniques := make(map[string]int)
	for _, v := range unique {
		uniques[v] = 0
	}

	for _, column := range this.Columns {
		field := ColumnizedField{}

		field.Name = columnNameToFieldName(column.Name())
		field.DataTypeDefn = columnToDataType(column)

		field.DataType, err = dataTypeToString(field.DataTypeDefn)
		if err != nil {
			return nil, err
		}

		this.Fields = append(this.Fields, field)
		spicelog.Infof("Table %q Column %q Field %q",
			t.Name(),
			column.Name(),
			field.Name)

		_, ok := uniques[column.Name()]
		if ok {
			this.Unique = append(this.Unique, field)
		}

		_, ok = primaryKeys[column.Name()]
		if ok {
			this.PrimaryKey = append(this.PrimaryKey, field)
		}

	}

	return this, nil
}

func dataTypeToString(dt []interface{}) (string, error) {
	buf := new(bytes.Buffer)
	rk, ok := dt[0].(reflect.Kind)
	if !ok {
		return "", fmt.Errorf("First element not %T", rk)
	}
	i := 1

	if rk == reflect.Ptr {
		fmt.Fprintf(buf, "*")

		rk, ok = dt[i].(reflect.Kind)
		i++
		if !ok {
			return "", fmt.Errorf("First element not %T", rk)
		}
	}

	switch rk {
	case reflect.Int32,
		reflect.Int64,
		reflect.Bool,
		reflect.String,
		reflect.Float64:
		fmt.Fprintf(buf, "%v", rk)
	case reflect.Struct:
		fmt.Fprintf(buf, "%T", dt[i])
		i++
	case reflect.Slice:
		fmt.Fprintf(buf, "[]%v", dt[i])
		i++
	default:
		return "", fmt.Errorf("Not convertable %v", dt)
	}

	return buf.String(), nil

}

func (this *ColumnizedStruct) Imports() []string {

	var result []string
	result = append(result, "bytes")
	result = append(result, "fmt")
	result = append(result, "database/sql")
	for _, field := range this.Fields {
		var i int
		kind, ok := field.DataTypeDefn[i].(reflect.Kind)
		i++
		if ok {

			if kind == reflect.Ptr {
				kind, ok = field.DataTypeDefn[i].(reflect.Kind)
				i++
				if !ok {
					continue
				}
			}

			if kind == reflect.Struct {
				_, ok := field.DataTypeDefn[i].(time.Time)
				i++
				if ok {
					result = append(result, "time")
				}
			}

		}
	}

	return result
}

func (this *ColumnizedStruct) Emit(pw *panicWriter) error {
	//--Emit a definition of the model
	pw.fprintLn("type %s struct {",
		this.SingularModelName)
	pw.indent()
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s %s //Column:%s",
			field.Name,
			field.DataType,
			column.Name())
	}
	pw.fprintLn("")
	//--Emit a nested struct that has a boolean
	//indicating if each column is loaded
	pw.fprintLn("IsLoaded struct {")
	pw.indent()
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s bool //Column:%s",
			field.Name,
			column.Name())
	}
	pw.deindent()
	pw.fprintLn("}") //close IsLoaded nested struct

	//--Emit a nested struct that has a boolean indicating
	//if each column is set
	pw.fprintLn("IsSet struct {")
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s bool //Column:%s",
			field.Name,
			column.Name())
	}
	pw.fprintLn("}")
	pw.deindent()
	pw.fprintLn("}") //close struct
	pw.fprintLn("")
	//--Emit a type definition for a list of the model type
	pw.fprintLn("type %s []%s", this.ListTypeName, this.SingularModelName)

	pw.fprintLn("")
	//--Emit a String() for the model type
	pw.fprintLn("func (this *%s) String() string {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("var buf bytes.Buffer")
	pw.fprintLn(`(&buf).WriteString("%s{")`, this.SingularModelName)
	for _, field := range this.Fields {

		pw.fprintLn("if this.IsLoaded.%s || this.IsSet.%s {",
			field.Name,
			field.Name,
		)
		pw.indent()

		if field.DataTypeDefn[0] != reflect.Ptr {
			pw.fprintLn(`fmt.Fprintf(&buf,"%s:%%v, ",this.%s)`,
				field.Name,
				field.Name)
		} else {
			pw.fprintLn("if this.%s != nil {", field.Name)
			pw.indent()
			pw.fprintLn(`fmt.Fprintf(&buf,"%s:%%v, ",*this.%s)`,
				field.Name,
				field.Name,
			)
			pw.deindent()
			pw.fprintLn("} else {")
			pw.indent()
			pw.fprintLn(`(&buf).WriteString("%s:nil, ")`,
				field.Name,
			)
			pw.deindent()
			pw.fprintLn("}")
		}

		pw.deindent()
		pw.fprintLn("}")
	}
	pw.fprintLn(`(&buf).WriteRune('}')`)
	pw.fprintLn("return (&buf).String()")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit an accessor to load multiple fields of the struct
	pw.fprintLn("func (this *%s) Reload(db *sql.DB, columns ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.indent()
	pw.fprintLn("if len(columns) == 0 {")
	pw.indent()
	pw.fprintLn("columns = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("err = this.loadColumnsWhere(db,idColumns,columns...)")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("%s(columns).SetLoaded(this,true)",
		this.TheColumnType.ListTypeName)
	pw.fprintLn("return nil")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit an accessor to load multiple fields of the struct
	//if not already loaded
	pw.fprintLn("func (this *%s) Get(db *sql.DB, columns ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.indent()
	pw.fprintLn("if len(columns) == 0 {")
	pw.indent()
	pw.fprintLn("columns = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("var unloadedColumns []%s", this.TheColumnType.InterfaceName)
	pw.fprintLn("for _, v := range columns {")
	pw.indent()
	pw.fprintLn("if ! v.IsLoaded(this) {")
	pw.indent()
	pw.fprintLn("unloadedColumns = append(unloadedColumns,v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.returnIf("len(unloadedColumns) == 0", "nil")
	pw.fprintLn("return this.Reload(db,unloadedColumns...)")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a setter for each field of the struct
	for _, field := range this.Fields {
		pw.fprintLn("func (this *%s) Set%s(v %s) {",
			this.SingularModelName,
			field.Name,
			field.DataType)
		pw.indent()
		pw.fprintLn("this.%s = v", field.Name)
		pw.fprintLn("this.IsSet.%s = true", field.Name)
		pw.deindent()
		pw.fprintLn("}")
		pw.fprintLn("")
	}

	//--Emit a save function
	//TODO check if table has an "updated_at" style column and
	//call SetUpdatedAt(time.Now()) if not already set
	pw.fprintLn("func (this *%s) Save(db *sql.DB) error {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("var columnsToSave %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToSave = append(columnsToSave, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.fprintLn("err = this.updateColumnsWhere(db,idColumns,columnsToSave...)")
	pw.fprintLn("if err == nil {")
	pw.indent()
	pw.fprintLn("columnsToSave.SetLoaded(this,true)")
	pw.fprintLn("columnsToSave.SetSet(this,false)")
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("return err")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a create function
	//TODO check for "created_at" style column
	pw.fprintLn("func (this *%s) Create(db *sql.DB) error {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("var columnsToCreate %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToCreate = append(columnsToCreate, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.fprintLn("err := this.insertColumns(db,columnsToCreate...)")
	pw.fprintLn("if err == nil {")
	pw.indent()
	pw.fprintLn("columnsToCreate.SetLoaded(this,true)")
	pw.fprintLn("columnsToCreate.SetSet(this,false)")
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("return err")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a FindOrCreate function
	//TODO check for "created_at" style column
	pw.fprintLn("func (this *%s) FindOrCreate(db *sql.DB, columnsToLoad ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.fprintLn("if len(columnsToLoad) == 0 {")
	pw.indent()
	pw.fprintLn("columnsToLoad = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("}")
	//TODO check for id column type and append if not in the list

	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")

	pw.fprintLn("var columnsToSave %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToSave = append(columnsToSave, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.fprintLn("return this.findOrCreateColumnsWhere(db,idColumns,columnsToSave,columnsToLoad)")
	//TODO clear IsSet
	//TODO set IsLoaded
	pw.fprintLn("}")

	return nil
}
<commit_msg>take care of TODOs<commit_after>package main

import "fmt"
import "github.com/spiceworks/spicelog"
import "reflect"
import "bytes"
import "time"

type CodeEmitter interface {
	Emit(*panicWriter) error
	Imports() []string
}

type ColumnizedField struct {
	DataTypeDefn []interface{}
	Name         string
	DataType     string
}

type ColumnizedStruct struct {
	PluralModelName   string
	SingularModelName string
	ListTypeName      string
	Fields            []ColumnizedField
	Columns           []Column
	PrimaryKey        []ColumnizedField
	Unique            []ColumnizedField
	TableName         string

	TheColumnType *ColumnType
}

func NewColumnizedStruct(t Table,
	tableNameToStructNames func(string) (string, string),
	columnNameToFieldName func(string) string,
	columnnToDataType func(Column) []interface{}) (*ColumnizedStruct, error) {
	this := new(ColumnizedStruct)
	this.TableName = t.Name()

	this.PluralModelName, this.SingularModelName = tableNameToStructNames(t.Name())
	this.ListTypeName = fmt.Sprintf("%sList", this.SingularModelName)

	spicelog.Infof("Table %q Plural %q Singular %q",
		t.Name(),
		this.PluralModelName,
		this.SingularModelName)
	var err error
	this.Columns, err = t.Columns()
	if err != nil {
		return nil, err
	}

	primaryKey, err := t.PrimaryKey()
	if err != nil {
		return nil, err
	}
	primaryKeys := make(map[string]int)
	for _, v := range primaryKey {
		primaryKeys[v] = 0
	}

	unique, err := t.Unique()
	if err != nil {
		return nil, err
	}
	uniques := make(map[string]int)
	for _, v := range unique {
		uniques[v] = 0
	}

	for _, column := range this.Columns {
		field := ColumnizedField{}

		field.Name = columnNameToFieldName(column.Name())
		field.DataTypeDefn = columnToDataType(column)

		field.DataType, err = dataTypeToString(field.DataTypeDefn)
		if err != nil {
			return nil, err
		}

		this.Fields = append(this.Fields, field)
		spicelog.Infof("Table %q Column %q Field %q",
			t.Name(),
			column.Name(),
			field.Name)

		_, ok := uniques[column.Name()]
		if ok {
			this.Unique = append(this.Unique, field)
		}

		_, ok = primaryKeys[column.Name()]
		if ok {
			this.PrimaryKey = append(this.PrimaryKey, field)
		}

	}

	return this, nil
}

func dataTypeToString(dt []interface{}) (string, error) {
	buf := new(bytes.Buffer)
	rk, ok := dt[0].(reflect.Kind)
	if !ok {
		return "", fmt.Errorf("First element not %T", rk)
	}
	i := 1

	if rk == reflect.Ptr {
		fmt.Fprintf(buf, "*")

		rk, ok = dt[i].(reflect.Kind)
		i++
		if !ok {
			return "", fmt.Errorf("First element not %T", rk)
		}
	}

	switch rk {
	case reflect.Int32,
		reflect.Int64,
		reflect.Bool,
		reflect.String,
		reflect.Float64:
		fmt.Fprintf(buf, "%v", rk)
	case reflect.Struct:
		fmt.Fprintf(buf, "%T", dt[i])
		i++
	case reflect.Slice:
		fmt.Fprintf(buf, "[]%v", dt[i])
		i++
	default:
		return "", fmt.Errorf("Not convertable %v", dt)
	}

	return buf.String(), nil

}

func (this *ColumnizedStruct) Imports() []string {

	var result []string
	result = append(result, "bytes")
	result = append(result, "fmt")
	result = append(result, "database/sql")
	for _, field := range this.Fields {
		var i int
		kind, ok := field.DataTypeDefn[i].(reflect.Kind)
		i++
		if ok {

			if kind == reflect.Ptr {
				kind, ok = field.DataTypeDefn[i].(reflect.Kind)
				i++
				if !ok {
					continue
				}
			}

			if kind == reflect.Struct {
				_, ok := field.DataTypeDefn[i].(time.Time)
				i++
				if ok {
					result = append(result, "time")
				}
			}

		}
	}

	return result
}

func (this *ColumnizedStruct) Emit(pw *panicWriter) error {
	//--Emit a definition of the model
	pw.fprintLn("type %s struct {",
		this.SingularModelName)
	pw.indent()
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s %s //Column:%s",
			field.Name,
			field.DataType,
			column.Name())
	}
	pw.fprintLn("")
	//--Emit a nested struct that has a boolean
	//indicating if each column is loaded
	pw.fprintLn("IsLoaded struct {")
	pw.indent()
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s bool //Column:%s",
			field.Name,
			column.Name())
	}
	pw.deindent()
	pw.fprintLn("}") //close IsLoaded nested struct

	//--Emit a nested struct that has a boolean indicating
	//if each column is set
	pw.fprintLn("IsSet struct {")
	for i, field := range this.Fields {
		column := this.Columns[i]
		pw.fprintLn("%s bool //Column:%s",
			field.Name,
			column.Name())
	}
	pw.fprintLn("}")
	pw.deindent()
	pw.fprintLn("}") //close struct
	pw.fprintLn("")
	//--Emit a type definition for a list of the model type
	pw.fprintLn("type %s []%s", this.ListTypeName, this.SingularModelName)

	pw.fprintLn("")
	//--Emit a String() for the model type
	pw.fprintLn("func (this *%s) String() string {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("var buf bytes.Buffer")
	pw.fprintLn(`(&buf).WriteString("%s{")`, this.SingularModelName)
	for _, field := range this.Fields {

		pw.fprintLn("if this.IsLoaded.%s || this.IsSet.%s {",
			field.Name,
			field.Name,
		)
		pw.indent()

		if field.DataTypeDefn[0] != reflect.Ptr {
			pw.fprintLn(`fmt.Fprintf(&buf,"%s:%%v, ",this.%s)`,
				field.Name,
				field.Name)
		} else {
			pw.fprintLn("if this.%s != nil {", field.Name)
			pw.indent()
			pw.fprintLn(`fmt.Fprintf(&buf,"%s:%%v, ",*this.%s)`,
				field.Name,
				field.Name,
			)
			pw.deindent()
			pw.fprintLn("} else {")
			pw.indent()
			pw.fprintLn(`(&buf).WriteString("%s:nil, ")`,
				field.Name,
			)
			pw.deindent()
			pw.fprintLn("}")
		}

		pw.deindent()
		pw.fprintLn("}")
	}
	pw.fprintLn(`(&buf).WriteRune('}')`)
	pw.fprintLn("return (&buf).String()")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit an accessor to load multiple fields of the struct
	pw.fprintLn("func (this *%s) Reload(db *sql.DB, columns ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.indent()
	pw.fprintLn("if len(columns) == 0 {")
	pw.indent()
	pw.fprintLn("columns = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("err = this.loadColumnsWhere(db,idColumns,columns...)")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("%s(columns).SetLoaded(this,true)",
		this.TheColumnType.ListTypeName)
	pw.fprintLn("return nil")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit an accessor to load multiple fields of the struct
	//if not already loaded
	pw.fprintLn("func (this *%s) Get(db *sql.DB, columns ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.indent()
	pw.fprintLn("if len(columns) == 0 {")
	pw.indent()
	pw.fprintLn("columns = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("var unloadedColumns []%s", this.TheColumnType.InterfaceName)
	pw.fprintLn("for _, v := range columns {")
	pw.indent()
	pw.fprintLn("if ! v.IsLoaded(this) {")
	pw.indent()
	pw.fprintLn("unloadedColumns = append(unloadedColumns,v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.returnIf("len(unloadedColumns) == 0", "nil")
	pw.fprintLn("return this.Reload(db,unloadedColumns...)")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a setter for each field of the struct
	for _, field := range this.Fields {
		pw.fprintLn("func (this *%s) Set%s(v %s) {",
			this.SingularModelName,
			field.Name,
			field.DataType)
		pw.indent()
		pw.fprintLn("this.%s = v", field.Name)
		pw.fprintLn("this.IsSet.%s = true", field.Name)
		pw.deindent()
		pw.fprintLn("}")
		pw.fprintLn("")
	}

	//--Emit a save function
	//TODO check if table has an "updated_at" style column and
	//call SetUpdatedAt(time.Now()) if not already set
	pw.fprintLn("func (this *%s) Save(db *sql.DB) error {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")
	pw.fprintLn("var columnsToSave %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToSave = append(columnsToSave, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.fprintLn("err = this.updateColumnsWhere(db,idColumns,columnsToSave...)")
	pw.fprintLn("if err == nil {")
	pw.indent()
	pw.fprintLn("columnsToSave.SetLoaded(this,true)")
	pw.fprintLn("columnsToSave.SetSet(this,false)")
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("return err")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a create function
	//TODO check for "created_at" style column
	pw.fprintLn("func (this *%s) Create(db *sql.DB) error {", this.SingularModelName)
	pw.indent()
	pw.fprintLn("var columnsToCreate %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToCreate = append(columnsToCreate, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for
	pw.fprintLn("err := this.insertColumns(db,columnsToCreate...)")
	pw.fprintLn("if err == nil {")
	pw.indent()
	pw.fprintLn("columnsToCreate.SetLoaded(this,true)")
	pw.fprintLn("columnsToCreate.SetSet(this,false)")
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("return err")
	pw.deindent()
	pw.fprintLn("}")

	//--Emit a FindOrCreate function
	//TODO check for "created_at" style column
	pw.fprintLn("func (this *%s) FindOrCreate(db *sql.DB, columnsToLoad ...%s) error {",
		this.SingularModelName,
		this.TheColumnType.InterfaceName,
	)
	pw.indent()

	pw.fprintLn("idColumns, err := this.identifyingColumns()")
	pw.returnIf("err != nil", "err")

	pw.fprintLn("var columnsToSave %s", this.TheColumnType.ListTypeName)
	pw.fprintLn("for _, v := range %s {", this.TheColumnType.AllColumnsName)
	pw.indent()
	pw.fprintLn("if v.IsSet(this) {")
	pw.indent()
	pw.fprintLn("columnsToSave = append(columnsToSave, v)")
	pw.deindent()
	pw.fprintLn("}") //end if
	pw.deindent()
	pw.fprintLn("}") //end for

	pw.fprintLn("if len(columnsToLoad) == 0 {") //Load all columns if not specified
	pw.indent()
	pw.fprintLn("columnsToLoad = %s", this.TheColumnType.AllColumnsName)
	pw.deindent()
	pw.fprintLn("} else {") //Load the columns specified plus those that are set
	//This is mandatory because not all columns are unique and the find-or-create
	//paradigm could return an object that is inconsistent with respect to
	//the database if the row already exists
	//TODO check for id column type and append if not in the list to load
	//	Is this TODO really needed? The user can't reach this code point if the
	//  object is not uniquely identifiable
	pw.indent()
	pw.fprintLn("columnsToLoad = append(columnsToLoad,columnsToSave...)")
	pw.deindent()
	pw.fprintLn("}")

	pw.fprintLn("err = this.findOrCreateColumnsWhere(db,idColumns,columnsToSave,columnsToLoad)")
	pw.fprintLn("if err == nil {")
	pw.indent()
	pw.fprintLn("%s(columnsToLoad).SetLoaded(this,true)",
		this.TheColumnType.ListTypeName) //Set the columns that are loaded
	pw.fprintLn("%s(columnsToLoad).SetSet(this,false)",
		this.TheColumnType.ListTypeName) //Clear the flags for columns that are
	pw.deindent()
	pw.fprintLn("}")
	pw.fprintLn("return err")
	pw.deindent()
	pw.fprintLn("}")

	return nil
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"strings"

	"github.com/docker/libcompose/docker"
	"github.com/docker/libcompose/project"
	"github.com/tcnksm/boot2k8s/config"
)

type UpCommand struct {
	Meta
}

func (c *UpCommand) Run(args []string) int {

	var insecure bool
	flags := flag.NewFlagSet("up", flag.ContinueOnError)
	flags.BoolVar(&insecure, "insecure", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }

	errR, errW := io.Pipe()
	errScanner := bufio.NewScanner(errR)
	go func() {
		for errScanner.Scan() {
			c.Ui.Error(errScanner.Text())
		}
	}()

	flags.SetOutput(errW)

	if err := flags.Parse(args); err != nil {
		return 1
	}

	compose, err := config.Asset("k8s.yml")
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to read k8s.yml: %s", err))
		return 1
	}

	// Setup new docker-compose project
	project, err := docker.NewProject(&docker.Context{
		Context: project.Context{
			ComposeBytes: compose,
			ProjectName:  "boot2k8s",
		},
		Tls: !insecure,
	})

	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to setup project: %s", err))
		return 1
	}

	if err := project.Up(); err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to up project: %s", err))
		return 1
	}

	// Write your code here
	return 0
}

func (c *UpCommand) Synopsis() string {
	return "Up kubernetes cluster"
}

func (c *UpCommand) Help() string {
	helpText := `Up kubernetes cluseter

Options:

  -insecure    Allow insecure non-TLS connection to docker client.
`
	return strings.TrimSpace(helpText)
}
<commit_msg>Add signal handling<commit_after>package command

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"os/signal"
	"strings"

	"github.com/docker/libcompose/docker"
	"github.com/docker/libcompose/project"
	"github.com/tcnksm/boot2k8s/config"
)

type UpCommand struct {
	Meta
}

func (c *UpCommand) Run(args []string) int {

	var insecure bool
	flags := flag.NewFlagSet("up", flag.ContinueOnError)
	flags.BoolVar(&insecure, "insecure", false, "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }

	errR, errW := io.Pipe()
	errScanner := bufio.NewScanner(errR)
	go func() {
		for errScanner.Scan() {
			c.Ui.Error(errScanner.Text())
		}
	}()

	flags.SetOutput(errW)

	if err := flags.Parse(args); err != nil {
		return 1
	}

	compose, err := config.Asset("k8s.yml")
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to read k8s.yml: %s", err))
		return 1
	}

	// Setup new docker-compose project
	project, err := docker.NewProject(&docker.Context{
		Context: project.Context{
			Log:          true,
			ComposeBytes: compose,
			ProjectName:  "boot2k8s",
		},
		Tls: !insecure,
	})

	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to setup project: %s", err))
		return 1
	}

	if err := project.Up(); err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to up project: %s", err))
		return 1
	}

	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, os.Interrupt)
	select {
	case <-sigCh:
		c.Ui.Error("Interrupted")
	}

	return 0
}

func (c *UpCommand) Synopsis() string {
	return "Up kubernetes cluster"
}

func (c *UpCommand) Help() string {
	helpText := `Up kubernetes cluseter

Options:

  -insecure    Allow insecure non-TLS connection to docker client.
`
	return strings.TrimSpace(helpText)
}
<|endoftext|>