<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/fsouza/go-dockerclient"
)

type DockerDynoDriver struct {
	d     *Docker
	state DynoState
	waiting          chan error
}

func (dd *DockerDynoDriver) Build(release *Release) error {
	if dd.d == nil {
		dd.d = &Docker{}
		if err := dd.d.Connect(); err != nil {
			dd.d = nil
			return err
		}
	}

	si, err := dd.d.StackStat("cedar-14")
	if err != nil {
		return err
	}

	imageName, err := dd.d.BuildSlugImage(si, release)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Built image successfully")

	release.imageName = imageName
	return nil
}

func (dd *DockerDynoDriver) State() DynoState {
	return dd.state
}

func (dd *DockerDynoDriver) Start(release *Release, ex *Executor) error {
	if dd.d == nil {
		dd.d = &Docker{}
		if err := dd.d.Connect(); err != nil {
			dd.d = nil
			return err
		}
	}

	ex.containers = make([]*docker.Container, 0)

	// Fill environment vector from Heroku configuration.
	env := make([]string, 0)
	for k, v := range release.config {
		env = append(env, k+"="+v)
	}

	container, err := dd.d.c.CreateContainer(docker.CreateContainerOptions{
		Name: fmt.Sprintf("%v-%v", release.imageName, int32(time.Now().Unix())),
		Config: &docker.Config{
			Cmd:   ex.Args(),
			Env:   env,
			Image: release.imageName,
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	ex.containers = append(ex.containers, container)

	for _, container := range ex.containers {
		err = dd.d.c.StartContainer(container.ID, &docker.HostConfig{})
		if err != nil {
			log.Fatal(err)
		}

		go dd.d.c.Logs(docker.LogsOptions{
			Container:    container.ID,
			Stdout:       true,
			Stderr:       true,
			Follow:       true,
			OutputStream: os.Stdout,
		})
	}

	dd.state = Started
	return nil
}

func (dd *DockerDynoDriver) Stop(ex *Executor) error {
	for _, container := range ex.containers {
		err := dd.d.c.StopContainer(container.ID, 10)
		return err
	}

	// @todo: need to be move this onto an executor instead of a driver
	dd.state = Stopped
	return nil
}
<commit_msg>Small refactoring within dyno driver to consolidate Docker connection checks<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/fsouza/go-dockerclient"
)

type DockerDynoDriver struct {
	d     *Docker
	state DynoState
	waiting          chan error
}

func (dd *DockerDynoDriver) Build(release *Release) error {
	if err := dd.connectDocker(); err != nil {
		return err
	}

	si, err := dd.d.StackStat("cedar-14")
	if err != nil {
		return err
	}

	imageName, err := dd.d.BuildSlugImage(si, release)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Built image successfully")

	release.imageName = imageName
	return nil
}

func (dd *DockerDynoDriver) State() DynoState {
	return dd.state
}

func (dd *DockerDynoDriver) Start(release *Release, ex *Executor) error {
	ex.containers = make([]*docker.Container, 0)

	// Fill environment vector from Heroku configuration.
	env := make([]string, 0)
	for k, v := range release.config {
		env = append(env, k+"="+v)
	}

	container, err := dd.d.c.CreateContainer(docker.CreateContainerOptions{
		Name: fmt.Sprintf("%v-%v", release.imageName, int32(time.Now().Unix())),
		Config: &docker.Config{
			Cmd:   ex.Args(),
			Env:   env,
			Image: release.imageName,
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	ex.containers = append(ex.containers, container)

	for _, container := range ex.containers {
		err = dd.d.c.StartContainer(container.ID, &docker.HostConfig{})
		if err != nil {
			log.Fatal(err)
		}

		go dd.d.c.Logs(docker.LogsOptions{
			Container:    container.ID,
			Stdout:       true,
			Stderr:       true,
			Follow:       true,
			OutputStream: os.Stdout,
		})
	}

	dd.state = Started
	return nil
}

func (dd *DockerDynoDriver) Stop(ex *Executor) error {
	for _, container := range ex.containers {
		err := dd.d.c.StopContainer(container.ID, 10)
		return err
	}

	// @todo: need to be move this onto an executor instead of a driver
	dd.state = Stopped
	return nil
}

func (dd *DockerDynoDriver) connectDocker() error {
	if dd.d == nil {
		dd.d = &Docker{}
		if err := dd.d.Connect(); err != nil {
			dd.d = nil
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package qshell

import (
	"qiniu/api.v6/conf"
)

type ZoneConfig struct {
	UpHost    string
	RsHost    string
	RsfHost   string
	IovipHost string
	ApiHost   string
}

var (
	DEFAULT_API_HOST = ZoneNBConfig.ApiHost
)

const (
	ZoneNB  = "nb"
	ZoneBC  = "bc"
	ZoneHN  = "hn"
	ZoneAWS = "aws"
	ZoneNA0 = "na0"
)

//zone all defaults to the service source site

var ZoneNBConfig = ZoneConfig{
	UpHost:    "http://up.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf.qbox.me",
	IovipHost: "http://iovip.qbox.me",
	ApiHost:   "http://api.qiniu.com",
}

var ZoneBCConfig = ZoneConfig{
	UpHost:    "http://up-z1.qiniu.com",
	RsHost:    "http://rs-z1.qiniu.com",
	RsfHost:   "http://rsf-z1.qbox.me",
	IovipHost: "http://iovip-z1.qbox.me",
	ApiHost:   "http://api-z1.qiniu.com",
}

var ZoneHNConfig = ZoneConfig{
	UpHost:    "http://up-z2.qiniu.com",
	RsHost:    "http://rs-z2.qiniu.com",
	RsfHost:   "http://rsf-z2.qbox.me",
	IovipHost: "http://iovip-z2.qbox.me",
	ApiHost:   "http://api-z2.qiniu.com",
}

var ZoneAWSConfig = ZoneConfig{
	UpHost:    "http://up.gdipper.com",
	RsHost:    "http://rs.gdipper.com",
	RsfHost:   "http://rsf.gdipper.com",
	IovipHost: "http://io.gdipper.com",
	ApiHost:   "http://api.gdipper.com",
}

var ZoneNA0Config = ZoneConfig{
	UpHost:    "http://upload-na0.qiniu.com",
	RsHost:    "http://rs-na0.qbox.me",
	RsfHost:   "http://rsf-na0.qbox.me",
	IovipHost: "http://iovip-na0.qbox.me",
	ApiHost:   "http://api-na0.qiniu.com",
}

func SetZone(zone string) {
	var zoneConfig ZoneConfig
	switch zone {
	case ZoneAWS:
		zoneConfig = ZoneAWSConfig
	case ZoneBC:
		zoneConfig = ZoneBCConfig
	case ZoneHN:
		zoneConfig = ZoneHNConfig
	case ZoneNA0:
		zoneConfig = ZoneNA0Config
	default:
		zoneConfig = ZoneNBConfig
	}
	conf.UP_HOST = zoneConfig.UpHost
	conf.RS_HOST = zoneConfig.RsHost
	conf.RSF_HOST = zoneConfig.RsfHost
	conf.IO_HOST = zoneConfig.IovipHost
	DEFAULT_API_HOST = zoneConfig.ApiHost
}

func IsValidZone(zone string) (valid bool) {
	switch zone {
	case ZoneNB, ZoneBC, ZoneHN, ZoneAWS, ZoneNA0:
		valid = true
	default:
		valid = false
	}
	return
}
<commit_msg>fix rs domain<commit_after>package qshell

import (
	"qiniu/api.v6/conf"
)

type ZoneConfig struct {
	UpHost    string
	RsHost    string
	RsfHost   string
	IovipHost string
	ApiHost   string
}

var (
	DEFAULT_API_HOST = ZoneNBConfig.ApiHost
)

const (
	ZoneNB  = "nb"
	ZoneBC  = "bc"
	ZoneHN  = "hn"
	ZoneAWS = "aws"
	ZoneNA0 = "na0"
)

//zone all defaults to the service source site

var ZoneNBConfig = ZoneConfig{
	UpHost:    "http://up.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf.qbox.me",
	IovipHost: "http://iovip.qbox.me",
	ApiHost:   "http://api.qiniu.com",
}

var ZoneBCConfig = ZoneConfig{
	UpHost:    "http://up-z1.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf-z1.qbox.me",
	IovipHost: "http://iovip-z1.qbox.me",
	ApiHost:   "http://api-z1.qiniu.com",
}

var ZoneHNConfig = ZoneConfig{
	UpHost:    "http://up-z2.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf-z2.qbox.me",
	IovipHost: "http://iovip-z2.qbox.me",
	ApiHost:   "http://api-z2.qiniu.com",
}

var ZoneAWSConfig = ZoneConfig{
	UpHost:    "http://up.gdipper.com",
	RsHost:    "http://rs.gdipper.com",
	RsfHost:   "http://rsf.gdipper.com",
	IovipHost: "http://io.gdipper.com",
	ApiHost:   "http://api.gdipper.com",
}

var ZoneNA0Config = ZoneConfig{
	UpHost:    "http://upload-na0.qiniu.com",
	RsHost:    "http://rs-na0.qbox.me",
	RsfHost:   "http://rsf-na0.qbox.me",
	IovipHost: "http://iovip-na0.qbox.me",
	ApiHost:   "http://api-na0.qiniu.com",
}

func SetZone(zone string) {
	var zoneConfig ZoneConfig
	switch zone {
	case ZoneAWS:
		zoneConfig = ZoneAWSConfig
	case ZoneBC:
		zoneConfig = ZoneBCConfig
	case ZoneHN:
		zoneConfig = ZoneHNConfig
	case ZoneNA0:
		zoneConfig = ZoneNA0Config
	default:
		zoneConfig = ZoneNBConfig
	}
	conf.UP_HOST = zoneConfig.UpHost
	conf.RS_HOST = zoneConfig.RsHost
	conf.RSF_HOST = zoneConfig.RsfHost
	conf.IO_HOST = zoneConfig.IovipHost
	DEFAULT_API_HOST = zoneConfig.ApiHost
}

func IsValidZone(zone string) (valid bool) {
	switch zone {
	case ZoneNB, ZoneBC, ZoneHN, ZoneAWS, ZoneNA0:
		valid = true
	default:
		valid = false
	}
	return
}
<|endoftext|>


<commit_before>package digests

import (
	"fmt"

	"github.com/ion-channel/ionic/scanner"
	"github.com/ion-channel/ionic/scans"
)

type dfilter func(*scans.Dependency) *scans.Dependency

func nv(d *scans.Dependency) *scans.Dependency {
	if d.Requirement == "" || d.Requirement == ">= 0" || d.Requirement == "\u003e= 0" {
		return d
	}
	if d.Dependencies != nil {
		for _, dep := range d.Dependencies {
			f := nv(&dep)
			if f != nil {
				return d
			}
		}
	}
	return nil
}

func od(d *scans.Dependency) *scans.Dependency {
	if d.Version < d.LatestVersion {
		return d
	}
	return nil
}

func giveem(d *scans.Dependency) *scans.Dependency {
	return d
}

func direct(d *scans.Dependency) *scans.Dependency {
	ff := d
	ff.Dependencies = nil
	return ff
}

func filterDependencies(data interface{}, unique bool, f dfilter) ([]scans.Dependency, error) {
	b, ok := data.(scans.DependencyResults)
	if !ok {
		return nil, fmt.Errorf("error coercing evaluation translated results into dep")
	}
	ds := []scans.Dependency{}
	for _, dr := range b.Dependencies {

		filtered := f(&dr)
		if filtered != nil {

			ds = append(ds, *filtered)
		}
	}
	return ds, nil
}

func dependencyDigests(status *scanner.ScanStatus, eval *scans.Evaluation) ([]Digest, error) {
	digests := make([]Digest, 0)
	var data interface{}

	var updateAvailable, noVersions, directDeps, transDeps int
	if eval != nil && !status.Errored() {
		data = eval.TranslatedResults.Data
		b, ok := data.(scans.DependencyResults)
		if !ok {
			return nil, fmt.Errorf("error coercing evaluation translated results into dependency bytes")
		}
		updateAvailable = b.Meta.UpdateAvailableCount
		noVersions = b.Meta.NoVersionCount
		directDeps = b.Meta.FirstDegreeCount
		transDeps = b.Meta.TotalUniqueCount - b.Meta.FirstDegreeCount
	}

	d := NewDigest(status, dependencyOutdatedIndex, "dependency outdated", "dependencies outdated")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, od)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}

		err = d.AppendEval(eval, "count", updateAvailable)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies outdated digest: %v", err.Error())
		}

		d.MarshalSourceData(filtered, "dependency")
		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.
	}

	digests = append(digests, *d)

	// No version specified
	d = NewDigest(status, noVersionIndex, "dependency no version specified", "dependencies no version specified")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, nv)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", noVersions)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies no version digest: %v", err.Error())
		}

		if noVersions > 0 {
			d.Warning = true
			d.WarningMessage = "dependencies with no version specified"

			if noVersions == 1 {
				d.WarningMessage = "dependency with no version specified"
			}
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, directDependencyIndex, "direct dependency", "direct dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, direct)

		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to direct dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", directDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create direct dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if directDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no direct dependencies found"
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, transitiveDependencyIndex, "transitive dependency", "transitive dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, giveem)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to transitive dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", transDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create transitive dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if transDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no transitive dependencies found"
		}
	}

	digests = append(digests, *d)

	return digests, nil
}
<commit_msg>Calculated all branches with outdated version<commit_after>package digests

import (
	"fmt"

	"github.com/ion-channel/ionic/scanner"
	"github.com/ion-channel/ionic/scans"
)

type dfilter func(*scans.Dependency) *scans.Dependency

func nv(d *scans.Dependency) *scans.Dependency {
	if d.Requirement == "" || d.Requirement == ">= 0" || d.Requirement == "\u003e= 0" {
		return d
	}
	if d.Dependencies != nil {
		for _, dep := range d.Dependencies {
			f := nv(&dep)
			if f != nil {
				return d
			}
		}
	}
	return nil
}

func od(d *scans.Dependency) *scans.Dependency {
	if d.Version < d.LatestVersion {
		return d
	}
	if d.Dependencies != nil {
		for _, dep := range d.Dependencies {
			f := od(&dep)
			if f != nil {
				return d
			}
		}
	}
	return nil
}

func giveem(d *scans.Dependency) *scans.Dependency {
	return d
}

func direct(d *scans.Dependency) *scans.Dependency {
	ff := d
	ff.Dependencies = nil
	return ff
}

func filterDependencies(data interface{}, unique bool, f dfilter) ([]scans.Dependency, error) {
	b, ok := data.(scans.DependencyResults)
	if !ok {
		return nil, fmt.Errorf("error coercing evaluation translated results into dep")
	}
	ds := []scans.Dependency{}
	for _, dr := range b.Dependencies {

		filtered := f(&dr)
		if filtered != nil {

			ds = append(ds, *filtered)
		}
	}
	return ds, nil
}

func dependencyDigests(status *scanner.ScanStatus, eval *scans.Evaluation) ([]Digest, error) {
	digests := make([]Digest, 0)
	var data interface{}

	var updateAvailable, noVersions, directDeps, transDeps int
	if eval != nil && !status.Errored() {
		data = eval.TranslatedResults.Data
		b, ok := data.(scans.DependencyResults)
		if !ok {
			return nil, fmt.Errorf("error coercing evaluation translated results into dependency bytes")
		}
		updateAvailable = b.Meta.UpdateAvailableCount
		noVersions = b.Meta.NoVersionCount
		directDeps = b.Meta.FirstDegreeCount
		transDeps = b.Meta.TotalUniqueCount - b.Meta.FirstDegreeCount
	}

	d := NewDigest(status, dependencyOutdatedIndex, "dependency outdated", "dependencies outdated")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, od)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}

		err = d.AppendEval(eval, "count", updateAvailable)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies outdated digest: %v", err.Error())
		}

		d.MarshalSourceData(filtered, "dependency")
		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.
	}

	digests = append(digests, *d)

	// No version specified
	d = NewDigest(status, noVersionIndex, "dependency no version specified", "dependencies no version specified")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, nv)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", noVersions)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies no version digest: %v", err.Error())
		}

		if noVersions > 0 {
			d.Warning = true
			d.WarningMessage = "dependencies with no version specified"

			if noVersions == 1 {
				d.WarningMessage = "dependency with no version specified"
			}
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, directDependencyIndex, "direct dependency", "direct dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, direct)

		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to direct dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", directDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create direct dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if directDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no direct dependencies found"
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, transitiveDependencyIndex, "transitive dependency", "transitive dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, giveem)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to transitive dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", transDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create transitive dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if transDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no transitive dependencies found"
		}
	}

	digests = append(digests, *d)

	return digests, nil
}
<|endoftext|>


<commit_before>package backend

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/influxdata/flux"
	"github.com/influxdata/flux/lang"
	"github.com/influxdata/influxdb"
	platform "github.com/influxdata/influxdb"
	pctx "github.com/influxdata/influxdb/context"
	"github.com/influxdata/influxdb/models"
	"github.com/influxdata/influxdb/query"
	"github.com/influxdata/influxdb/storage"
	"github.com/influxdata/influxdb/tsdb"
)

const (
	runIDField        = "runID"
	scheduledForField = "scheduledFor"
	startedAtField    = "startedAt"
	finishedAtField   = "finishedAt"
	requestedAtField  = "requestedAt"
	statusField       = "status"
	logField          = "logs"

	taskIDTag = "taskID"

	// Fixed system bucket ID for task and run logs.
	taskSystemBucketID platform.ID = 10
)

var (
	// ErrTaskNotFound indicates no task could be found for given parameters.
	ErrTaskNotFound = errors.New("task not found")

	// ErrRunNotFound is returned when searching for a single run that doesn't exist.
	ErrRunNotFound = errors.New("run not found")
)

// NewAnalyticalStorage creates a new analytical store with access to the necessary systems for storing data and to act as a middleware
func NewAnalyticalStorage(ts influxdb.TaskService, tcs TaskControlService, pw storage.PointsWriter, qs query.QueryService) *AnalyticalStorage {
	return &AnalyticalStorage{
		TaskService:        ts,
		TaskControlService: tcs,
		pw:                 pw,
		qs:                 qs,
	}
}

type AnalyticalStorage struct {
	influxdb.TaskService
	TaskControlService

	pw storage.PointsWriter
	qs query.QueryService
}

func (as *AnalyticalStorage) FinishRun(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	run, err := as.TaskControlService.FinishRun(ctx, taskID, runID)
	if run != nil {
		task, err := as.TaskService.FindTaskByID(ctx, run.TaskID)
		if err != nil {
			return run, err
		}

		tags := models.Tags{
			models.NewTag([]byte(taskIDTag), []byte(run.TaskID.String())),
			models.NewTag([]byte(statusField), []byte(run.Status)),
		}

		fields := map[string]interface{}{}
		fields[statusField] = run.Status
		fields[runIDField] = run.ID.String()
		fields[startedAtField] = run.StartedAt
		fields[finishedAtField] = run.FinishedAt
		fields[scheduledForField] = run.ScheduledFor
		if run.RequestedAt != "" {
			fields[requestedAtField] = run.RequestedAt
		}

		startedAt, err := run.StartedAtTime()
		if err != nil {
			startedAt = time.Now()
		}

		logBytes, err := json.Marshal(run.Log)
		if err != nil {
			return run, err
		}
		fields[logField] = string(logBytes)

		point, err := models.NewPoint("runs", tags, fields, startedAt)
		if err != nil {
			return run, err
		}

		// use the tsdb explode points to convert to the new style.
		// We could split this on our own but its quite possible this could change.
		points, err := tsdb.ExplodePoints(task.OrganizationID, taskSystemBucketID, models.Points{point})
		if err != nil {
			return run, err
		}
		return run, as.pw.WritePoints(ctx, points)
	}
	return run, err
}

// FindLogs returns logs for a run.
// First attempt to use the TaskService, then append additional analytical's logs to the list
func (as *AnalyticalStorage) FindLogs(ctx context.Context, filter influxdb.LogFilter) ([]*influxdb.Log, int, error) {
	var logs []*influxdb.Log
	if filter.Run != nil {
		run, err := as.FindRunByID(ctx, filter.Task, *filter.Run)
		if err != nil {
			return nil, 0, err
		}
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
		return logs, len(logs), nil
	}

	// add historical logs to the transactional logs.
	runs, n, err := as.FindRuns(ctx, influxdb.RunFilter{Task: filter.Task})
	if err != nil {
		return nil, 0, err
	}

	for _, run := range runs {
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
	}

	return logs, n, err
}

// FindRuns returns a list of runs that match a filter and the total count of returned runs.
// First attempt to use the TaskService, then append additional analytical's runs to the list
func (as *AnalyticalStorage) FindRuns(ctx context.Context, filter influxdb.RunFilter) ([]*influxdb.Run, int, error) {
	if filter.Limit == 0 || filter.Limit > influxdb.TaskMaxPageSize {
		filter.Limit = influxdb.TaskMaxPageSize
	}

	runs, n, err := as.TaskService.FindRuns(ctx, filter)
	if err != nil {
		return runs, n, err
	}

	// if we reached the limit lets stop here
	if len(runs) >= filter.Limit {
		return runs, n, err
	}

	task, err := as.TaskService.FindTaskByID(ctx, filter.Task)
	if err != nil {
		return runs, n, err
	}

	filterPart := ""
	if filter.After != nil {
		filterPart = fmt.Sprintf(`|> filter(fn: (r) => r.runID > %q)`, filter.After.String())
	}

	// the data will be stored for 7 days in the system bucket so pulling 14d's is sufficient.
	runsScript := fmt.Sprintf(`from(bucketID: "000000000000000a")
	  |> range(start: -14d)
	  |> filter(fn: (r) => r._measurement == "runs" and r.taskID == %q)
	  %s
	  |> group(columns: ["taskID"])
	  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")

	  `, filter.Task.String(), filterPart)

	auth, err := pctx.GetAuthorizer(ctx)
	if err != nil {
		return nil, 0, err
	}
	if auth.Kind() != "authorization" {
		return nil, 0, influxdb.ErrAuthorizerNotSupported
	}
	request := &query.Request{Authorization: auth.(*influxdb.Authorization), OrganizationID: task.OrganizationID, Compiler: lang.FluxCompiler{Query: runsScript}}

	ittr, err := as.qs.Query(ctx, request)
	if err != nil {
		return nil, 0, err
	}
	defer ittr.Release()

	re := &runReader{}
	for ittr.More() {
		err := ittr.Next().Tables().Do(re.readTable)
		if err != nil {
			return runs, n, err
		}
	}

	runs = append(runs, re.runs...)

	return runs, n, err
}

// FindRunByID returns a single run.
// First see if it is in the existing TaskService. If not pull it from analytical storage.
func (as *AnalyticalStorage) FindRunByID(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	// check the taskService to see if the run is on its list
	run, err := as.TaskService.FindRunByID(ctx, taskID, runID)
	if err != nil {
		if err, ok := err.(*influxdb.Error); !ok || err.Msg != "run not found" {
			return run, err
		}
	}
	if run != nil {
		return run, err
	}

	task, err := as.TaskService.FindTaskByID(ctx, taskID)
	if err != nil {
		return run, err
	}

	// the data will be stored for 7 days in the system bucket so pulling 14d's is sufficient.
	findRunScript := fmt.Sprintf(`from(bucketID: "000000000000000a")
	|> range(start: -14d)
	|> filter(fn: (r) => r._measurement == "runs" and r.taskID == %q)
	|> group(columns: ["taskID"])
	|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
	|> filter(fn: (r) => r.runID == %q)
	  `, taskID.String(), runID.String())

	auth, err := pctx.GetAuthorizer(ctx)
	if err != nil {
		return nil, err
	}
	if auth.Kind() != "authorization" {
		return nil, influxdb.ErrAuthorizerNotSupported
	}
	request := &query.Request{Authorization: auth.(*influxdb.Authorization), OrganizationID: task.OrganizationID, Compiler: lang.FluxCompiler{Query: findRunScript}}

	ittr, err := as.qs.Query(ctx, request)
	if err != nil {
		return nil, err
	}
	defer ittr.Release()

	re := &runReader{}
	for ittr.More() {
		err := ittr.Next().Tables().Do(re.readTable)
		if err != nil {
			return nil, err
		}
	}

	if len(re.runs) == 0 {
		return nil, ErrRunNotFound

	}

	if len(re.runs) != 1 {
		return nil, &influxdb.Error{
			Msg:  "found multiple runs with id " + runID.String(),
			Code: influxdb.EInternal,
		}
	}

	return re.runs[0], err
}

func (as *AnalyticalStorage) RetryRun(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	run, err := as.TaskService.RetryRun(ctx, taskID, runID)
	if err != nil {
		if err, ok := err.(*influxdb.Error); !ok || err.Msg != "run not found" {
			return run, err
		}
	}

	if run != nil {
		return run, err
	}

	// try finding the run (in our system or underlieing)
	run, err = as.FindRunByID(ctx, taskID, runID)
	if err != nil {
		return run, err
	}

	sf, err := run.ScheduledForTime()
	if err != nil {
		return run, err
	}

	return as.ForceRun(ctx, taskID, sf.Unix())
}

type runReader struct {
	runs []*influxdb.Run
}

func (re *runReader) readTable(tbl flux.Table) error {
	return tbl.Do(re.readRuns)
}

func (re *runReader) readRuns(cr flux.ColReader) error {
	for i := 0; i < cr.Len(); i++ {
		var r influxdb.Run
		for j, col := range cr.Cols() {
			switch col.Label {
			case "runID":
				id, err := influxdb.IDFromString(cr.Strings(j).ValueString(i))
				if err != nil {
					return err
				}
				r.ID = *id
			case "taskID":
				id, err := influxdb.IDFromString(cr.Strings(j).ValueString(i))
				if err != nil {
					return err
				}
				r.TaskID = *id
			case startedAtField:
				r.StartedAt = cr.Strings(j).ValueString(i)
			case requestedAtField:
				r.RequestedAt = cr.Strings(j).ValueString(i)
			case scheduledForField:
				r.ScheduledFor = cr.Strings(j).ValueString(i)
			case statusField:
				r.Status = cr.Strings(j).ValueString(i)
			case finishedAtField:
				r.FinishedAt = cr.Strings(j).ValueString(i)
			case logField:
				logBytes := cr.Strings(j).Value(i)
				err := json.Unmarshal(logBytes, &r.Log)
				if err != nil {
					return err
				}
			}

		}

		if !r.ID.Valid() {
			return &influxdb.Error{
				Msg:  "failed to pull run id",
				Code: influxdb.EInternal,
			}
		}

		re.runs = append(re.runs, &r)
	}

	return nil
}
<commit_msg>fix(task): Apply grease to the analtic system (#14112)<commit_after>package backend

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/influxdata/flux"
	"github.com/influxdata/flux/lang"
	"github.com/influxdata/influxdb"
	platform "github.com/influxdata/influxdb"
	pctx "github.com/influxdata/influxdb/context"
	"github.com/influxdata/influxdb/models"
	"github.com/influxdata/influxdb/query"
	"github.com/influxdata/influxdb/storage"
	"github.com/influxdata/influxdb/tsdb"
)

const (
	runIDField        = "runID"
	scheduledForField = "scheduledFor"
	startedAtField    = "startedAt"
	finishedAtField   = "finishedAt"
	requestedAtField  = "requestedAt"
	statusField       = "status"
	logField          = "logs"

	taskIDTag = "taskID"

	// Fixed system bucket ID for task and run logs.
	taskSystemBucketID platform.ID = 10
)

var (
	// ErrTaskNotFound indicates no task could be found for given parameters.
	ErrTaskNotFound = errors.New("task not found")

	// ErrRunNotFound is returned when searching for a single run that doesn't exist.
	ErrRunNotFound = errors.New("run not found")
)

// NewAnalyticalStorage creates a new analytical store with access to the necessary systems for storing data and to act as a middleware
func NewAnalyticalStorage(ts influxdb.TaskService, tcs TaskControlService, pw storage.PointsWriter, qs query.QueryService) *AnalyticalStorage {
	return &AnalyticalStorage{
		TaskService:        ts,
		TaskControlService: tcs,
		pw:                 pw,
		qs:                 qs,
	}
}

type AnalyticalStorage struct {
	influxdb.TaskService
	TaskControlService

	pw storage.PointsWriter
	qs query.QueryService
}

func (as *AnalyticalStorage) FinishRun(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	run, err := as.TaskControlService.FinishRun(ctx, taskID, runID)
	if run != nil && run.ID.String() != "" {
		task, err := as.TaskService.FindTaskByID(ctx, run.TaskID)
		if err != nil {
			return run, err
		}

		tags := models.Tags{
			models.NewTag([]byte(taskIDTag), []byte(run.TaskID.String())),
			models.NewTag([]byte(statusField), []byte(run.Status)),
		}

		fields := map[string]interface{}{}
		fields[statusField] = run.Status
		fields[runIDField] = run.ID.String()
		fields[startedAtField] = run.StartedAt
		fields[finishedAtField] = run.FinishedAt
		fields[scheduledForField] = run.ScheduledFor
		if run.RequestedAt != "" {
			fields[requestedAtField] = run.RequestedAt
		}

		startedAt, err := run.StartedAtTime()
		if err != nil {
			startedAt = time.Now()
		}

		logBytes, err := json.Marshal(run.Log)
		if err != nil {
			return run, err
		}
		fields[logField] = string(logBytes)

		point, err := models.NewPoint("runs", tags, fields, startedAt)
		if err != nil {
			return run, err
		}

		// use the tsdb explode points to convert to the new style.
		// We could split this on our own but its quite possible this could change.
		points, err := tsdb.ExplodePoints(task.OrganizationID, taskSystemBucketID, models.Points{point})
		if err != nil {
			return run, err
		}
		return run, as.pw.WritePoints(ctx, points)
	}
	return run, err
}

// FindLogs returns logs for a run.
// First attempt to use the TaskService, then append additional analytical's logs to the list
func (as *AnalyticalStorage) FindLogs(ctx context.Context, filter influxdb.LogFilter) ([]*influxdb.Log, int, error) {
	var logs []*influxdb.Log
	if filter.Run != nil {
		run, err := as.FindRunByID(ctx, filter.Task, *filter.Run)
		if err != nil {
			return nil, 0, err
		}
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
		return logs, len(logs), nil
	}

	// add historical logs to the transactional logs.
	runs, n, err := as.FindRuns(ctx, influxdb.RunFilter{Task: filter.Task})
	if err != nil {
		return nil, 0, err
	}

	for _, run := range runs {
		for i := 0; i < len(run.Log); i++ {
			logs = append(logs, &run.Log[i])
		}
	}

	return logs, n, err
}

// FindRuns returns a list of runs that match a filter and the total count of returned runs.
// First attempt to use the TaskService, then append additional analytical's runs to the list
func (as *AnalyticalStorage) FindRuns(ctx context.Context, filter influxdb.RunFilter) ([]*influxdb.Run, int, error) {
	if filter.Limit == 0 || filter.Limit > influxdb.TaskMaxPageSize {
		filter.Limit = influxdb.TaskMaxPageSize
	}

	runs, n, err := as.TaskService.FindRuns(ctx, filter)
	if err != nil {
		return runs, n, err
	}

	// if we reached the limit lets stop here
	if len(runs) >= filter.Limit {
		return runs, n, err
	}

	task, err := as.TaskService.FindTaskByID(ctx, filter.Task)
	if err != nil {
		return runs, n, err
	}

	filterPart := ""
	if filter.After != nil {
		filterPart = fmt.Sprintf(`|> filter(fn: (r) => r.runID > %q)`, filter.After.String())
	}

	// the data will be stored for 7 days in the system bucket so pulling 14d's is sufficient.
	runsScript := fmt.Sprintf(`from(bucketID: "000000000000000a")
	  |> range(start: -14d)
	  |> filter(fn: (r) => r._measurement == "runs" and r.taskID == %q)
	  %s
	  |> group(columns: ["taskID"])
	  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")

	  `, filter.Task.String(), filterPart)

	auth, err := pctx.GetAuthorizer(ctx)
	if err != nil {
		return nil, 0, err
	}
	if auth.Kind() != "authorization" {
		return nil, 0, influxdb.ErrAuthorizerNotSupported
	}
	request := &query.Request{Authorization: auth.(*influxdb.Authorization), OrganizationID: task.OrganizationID, Compiler: lang.FluxCompiler{Query: runsScript}}

	ittr, err := as.qs.Query(ctx, request)
	if err != nil {
		return nil, 0, err
	}
	defer ittr.Release()

	re := &runReader{}
	for ittr.More() {
		err := ittr.Next().Tables().Do(re.readTable)
		if err != nil {
			return runs, n, err
		}
	}

	runs = append(runs, re.runs...)

	return runs, n, err
}

// FindRunByID returns a single run.
// First see if it is in the existing TaskService. If not pull it from analytical storage.
func (as *AnalyticalStorage) FindRunByID(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	// check the taskService to see if the run is on its list
	run, err := as.TaskService.FindRunByID(ctx, taskID, runID)
	if err != nil {
		if err, ok := err.(*influxdb.Error); !ok || err.Msg != "run not found" {
			return run, err
		}
	}
	if run != nil {
		return run, err
	}

	task, err := as.TaskService.FindTaskByID(ctx, taskID)
	if err != nil {
		return run, err
	}

	// the data will be stored for 7 days in the system bucket so pulling 14d's is sufficient.
	findRunScript := fmt.Sprintf(`from(bucketID: "000000000000000a")
	|> range(start: -14d)
	|> filter(fn: (r) => r._measurement == "runs" and r.taskID == %q)
	|> group(columns: ["taskID"])
	|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
	|> filter(fn: (r) => r.runID == %q)
	  `, taskID.String(), runID.String())

	auth, err := pctx.GetAuthorizer(ctx)
	if err != nil {
		return nil, err
	}
	if auth.Kind() != "authorization" {
		return nil, influxdb.ErrAuthorizerNotSupported
	}
	request := &query.Request{Authorization: auth.(*influxdb.Authorization), OrganizationID: task.OrganizationID, Compiler: lang.FluxCompiler{Query: findRunScript}}

	ittr, err := as.qs.Query(ctx, request)
	if err != nil {
		return nil, err
	}
	defer ittr.Release()

	re := &runReader{}
	for ittr.More() {
		err := ittr.Next().Tables().Do(re.readTable)
		if err != nil {
			return nil, err
		}
	}

	if len(re.runs) == 0 {
		return nil, ErrRunNotFound

	}

	if len(re.runs) != 1 {
		return nil, &influxdb.Error{
			Msg:  "found multiple runs with id " + runID.String(),
			Code: influxdb.EInternal,
		}
	}

	return re.runs[0], err
}

func (as *AnalyticalStorage) RetryRun(ctx context.Context, taskID, runID influxdb.ID) (*influxdb.Run, error) {
	run, err := as.TaskService.RetryRun(ctx, taskID, runID)
	if err != nil {
		if err, ok := err.(*influxdb.Error); !ok || err.Msg != "run not found" {
			return run, err
		}
	}

	if run != nil {
		return run, err
	}

	// try finding the run (in our system or underlieing)
	run, err = as.FindRunByID(ctx, taskID, runID)
	if err != nil {
		return run, err
	}

	sf, err := run.ScheduledForTime()
	if err != nil {
		return run, err
	}

	return as.ForceRun(ctx, taskID, sf.Unix())
}

type runReader struct {
	runs []*influxdb.Run
}

func (re *runReader) readTable(tbl flux.Table) error {
	return tbl.Do(re.readRuns)
}

func (re *runReader) readRuns(cr flux.ColReader) error {
	for i := 0; i < cr.Len(); i++ {
		var r influxdb.Run
		for j, col := range cr.Cols() {
			switch col.Label {
			case "runID":
				if cr.Strings(j).ValueString(i) != "" {
					id, err := influxdb.IDFromString(cr.Strings(j).ValueString(i))
					if err != nil {
						return err
					}
					r.ID = *id
				}
			case "taskID":
				if cr.Strings(j).ValueString(i) != "" {
					id, err := influxdb.IDFromString(cr.Strings(j).ValueString(i))
					if err != nil {
						return err
					}
					r.TaskID = *id
				}
			case startedAtField:
				r.StartedAt = cr.Strings(j).ValueString(i)
			case requestedAtField:
				r.RequestedAt = cr.Strings(j).ValueString(i)
			case scheduledForField:
				r.ScheduledFor = cr.Strings(j).ValueString(i)
			case statusField:
				r.Status = cr.Strings(j).ValueString(i)
			case finishedAtField:
				r.FinishedAt = cr.Strings(j).ValueString(i)
			case logField:
				logBytes := cr.Strings(j).Value(i)
				err := json.Unmarshal(logBytes, &r.Log)
				if err != nil {
					return err
				}
			}

		}

		// if we dont have a full enough data set we fail here.
		if r.ID.Valid() {
			re.runs = append(re.runs, &r)
		}

	}

	return nil
}
<|endoftext|>


<commit_before>package hydrocarbon

import (
	"context"
	"errors"
	"fmt"
	"net"
	"net/http"
	"strings"

	stripe "github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/client"
	"github.com/stripe/stripe-go/customer"
	"github.com/stripe/stripe-go/sub"
)

// A UserStore is an interface used to seperate the UserAPI from knowledge of the
// actual underlying database
type UserStore interface {
	CreateOrGetUser(ctx context.Context, email string) (string, bool, error)
	SetStripeIDs(ctx context.Context, userID, customerID, subscriptionID string) error

	CreateLoginToken(ctx context.Context, userID, userAgent, ip string) (string, error)
	ActivateLoginToken(ctx context.Context, token string) (string, error)

	CreateSession(ctx context.Context, userID, userAgent, ip string) (string, string, error)
	ListSessions(ctx context.Context, key string, page int) ([]*Session, error)
	DeactivateSession(ctx context.Context, key string) error
}

// UserAPI encapsulates everything related to user management
type UserAPI struct {
	paymentRequired bool
	stripePlanID    string
	sc              *client.API
	s               UserStore
	m               Mailer
	ks              *KeySigner
}

// NewUserAPI sets up a new UserAPI used for user/session management
func NewUserAPI(s UserStore, ks *KeySigner, m Mailer, stripePlanID, stripeKey string, paymentRequired bool) *UserAPI {
	var c *client.API
	if paymentRequired {
		c = &client.API{}
		c.Init(stripeKey, nil)
	}

	return &UserAPI{
		s:               s,
		ks:              ks,
		m:               m,
		sc:              c,
		stripePlanID:    stripePlanID,
		paymentRequired: paymentRequired,
	}
}

// RequestToken emails a token that can be exchanged for a session
func (ua *UserAPI) RequestToken(w http.ResponseWriter, r *http.Request) error {
	var registerData struct {
		Email string `json:"email"`
	}

	err := limitDecoder(r, &registerData)
	if err != nil {
		return err
	}

	if len(registerData.Email) == 0 || len(registerData.Email) > 128 || !strings.Contains(registerData.Email, "@") {
		return errors.New("invalid email")
	}

	userID, paid, err := ua.s.CreateOrGetUser(r.Context(), registerData.Email)
	if err != nil {
		return err
	}

	if ua.paymentRequired && !paid {
		return errors.New("payment is required")
	}

	lt, err := ua.s.CreateLoginToken(r.Context(), userID, r.UserAgent(), getRemoteIP(r))
	if err != nil {
		return err
	}

	err = ua.m.Send(registerData.Email, fmt.Sprintf("visit %s/callback?token=%s to login", ua.m.RootDomain(), lt))
	if err != nil {
		return err
	}

	return writeSuccess(w, "check your email for a login token, token expires in 24 hours")
}

// CreatePayment sets up the initial stripe stuff for a user
func (ua *UserAPI) CreatePayment(w http.ResponseWriter, r *http.Request) error {
	if !ua.paymentRequired {
		return errors.New("payments are not enabled on this instance")
	}

	var stripeData struct {
		Email  string `json:"email"`
		Coupon string `json:"coupon"`
		Token  string `json:"token"`
	}

	err := limitDecoder(r, &stripeData)
	if err != nil {
		return err
	}

	userID, paid, err := ua.s.CreateOrGetUser(r.Context(), stripeData.Email)
	if err != nil {
		return err
	}

	if paid {
		return errors.New("subscription already exists")
	}

	params := &stripe.CustomerParams{
		Email: stripeData.Email,
	}
	err = params.SetSource(stripeData.Token)
	if err != nil {
		return err
	}

	customer, err := customer.New(params)
	if err != nil {
		return err
	}

	sp := &stripe.SubParams{
		Customer: customer.ID,
		Items: []*stripe.SubItemsParams{
			{
				Plan: ua.stripePlanID,
			},
		},
	}
	if stripeData.Coupon != "" {
		sp.Coupon = stripeData.Coupon
	}

	s, err := sub.New(sp)
	if err != nil {
		return err
	}

	err = ua.s.SetStripeIDs(r.Context(), userID, customer.ID, s.ID)
	if err != nil {
		return err
	}

	return writeSuccess(w, "stripe subscription created")
}

// ListSessions writes out all of a users current / past sessions
func (ua *UserAPI) ListSessions(w http.ResponseWriter, r *http.Request) error {
	key, err := ua.ks.Verify(r.Header.Get("X-Hydrocarbon-Key"))
	if err != nil {
		return err
	}

	sess, err := ua.s.ListSessions(r.Context(), key, 0)
	if err != nil {
		return err
	}

	return writeSuccess(w, sess)
}

// Activate exchanges a token for a session key that can be used to make
// authenticated requests
func (ua *UserAPI) Activate(w http.ResponseWriter, r *http.Request) error {
	var activateData struct {
		Token string `json:"token"`
	}

	err := limitDecoder(r, &activateData)
	if err != nil {
		return err
	}

	userID, err := ua.s.ActivateLoginToken(r.Context(), activateData.Token)
	if err != nil {
		return err
	}

	email, key, err := ua.s.CreateSession(r.Context(), userID, r.UserAgent(), getRemoteIP(r))
	if err != nil {
		return err
	}

	key, err = ua.ks.Sign(key)
	if err != nil {
		return err
	}

	var activationData = struct {
		Email string `json:"email"`
		Key   string `json:"key"`
	}{
		email,
		key,
	}

	return writeSuccess(w, activationData)
}

// Deactivate disables a key that the user is currently using
func (ua *UserAPI) Deactivate(w http.ResponseWriter, r *http.Request) error {
	key, err := ua.ks.Verify(r.Header.Get("X-Hydrocarbon-Key"))
	if err != nil {
		return err
	}

	err = ua.s.DeactivateSession(r.Context(), key)
	if err != nil {
		return err
	}

	return writeSuccess(w, nil)
}

func getRemoteIP(r *http.Request) string {
	fwdIP := r.Header.Get("X-Forwarded-For")
	fwdSplit := strings.Split(fwdIP, ",")
	if fwdIP != "" {
		// pick the leftmost x-forwarded-for addr
		return fwdSplit[0]
	}

	// this literally can't fail on r.RemoteAddr
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return r.RemoteAddr
	}
	return ip
}
<commit_msg>stripe api bumps lol<commit_after>package hydrocarbon

import (
	"context"
	"errors"
	"fmt"
	"net"
	"net/http"
	"strings"

	stripe "github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/client"
	"github.com/stripe/stripe-go/customer"
	"github.com/stripe/stripe-go/sub"
)

// A UserStore is an interface used to seperate the UserAPI from knowledge of the
// actual underlying database
type UserStore interface {
	CreateOrGetUser(ctx context.Context, email string) (string, bool, error)
	SetStripeIDs(ctx context.Context, userID, customerID, subscriptionID string) error

	CreateLoginToken(ctx context.Context, userID, userAgent, ip string) (string, error)
	ActivateLoginToken(ctx context.Context, token string) (string, error)

	CreateSession(ctx context.Context, userID, userAgent, ip string) (string, string, error)
	ListSessions(ctx context.Context, key string, page int) ([]*Session, error)
	DeactivateSession(ctx context.Context, key string) error
}

// UserAPI encapsulates everything related to user management
type UserAPI struct {
	paymentRequired bool
	stripePlanID    string
	sc              *client.API
	s               UserStore
	m               Mailer
	ks              *KeySigner
}

// NewUserAPI sets up a new UserAPI used for user/session management
func NewUserAPI(s UserStore, ks *KeySigner, m Mailer, stripePlanID, stripeKey string, paymentRequired bool) *UserAPI {
	var c *client.API
	if paymentRequired {
		c = &client.API{}
		c.Init(stripeKey, nil)
	}

	return &UserAPI{
		s:               s,
		ks:              ks,
		m:               m,
		sc:              c,
		stripePlanID:    stripePlanID,
		paymentRequired: paymentRequired,
	}
}

// RequestToken emails a token that can be exchanged for a session
func (ua *UserAPI) RequestToken(w http.ResponseWriter, r *http.Request) error {
	var registerData struct {
		Email string `json:"email"`
	}

	err := limitDecoder(r, &registerData)
	if err != nil {
		return err
	}

	if len(registerData.Email) == 0 || len(registerData.Email) > 128 || !strings.Contains(registerData.Email, "@") {
		return errors.New("invalid email")
	}

	userID, paid, err := ua.s.CreateOrGetUser(r.Context(), registerData.Email)
	if err != nil {
		return err
	}

	if ua.paymentRequired && !paid {
		return errors.New("payment is required")
	}

	lt, err := ua.s.CreateLoginToken(r.Context(), userID, r.UserAgent(), getRemoteIP(r))
	if err != nil {
		return err
	}

	err = ua.m.Send(registerData.Email, fmt.Sprintf("visit %s/callback?token=%s to login", ua.m.RootDomain(), lt))
	if err != nil {
		return err
	}

	return writeSuccess(w, "check your email for a login token, token expires in 24 hours")
}

// CreatePayment sets up the initial stripe stuff for a user
func (ua *UserAPI) CreatePayment(w http.ResponseWriter, r *http.Request) error {
	if !ua.paymentRequired {
		return errors.New("payments are not enabled on this instance")
	}

	var stripeData struct {
		Email  string `json:"email"`
		Coupon string `json:"coupon"`
		Token  string `json:"token"`
	}

	err := limitDecoder(r, &stripeData)
	if err != nil {
		return err
	}

	userID, paid, err := ua.s.CreateOrGetUser(r.Context(), stripeData.Email)
	if err != nil {
		return err
	}

	if paid {
		return errors.New("subscription already exists")
	}

	params := &stripe.CustomerParams{
		Email: &stripeData.Email,
	}
	err = params.SetSource(stripeData.Token)
	if err != nil {
		return err
	}

	customer, err := customer.New(params)
	if err != nil {
		return err
	}

	sp := &stripe.SubscriptionParams{
		Customer: &customer.ID,
		Plan:     &ua.stripePlanID,
	}

	if stripeData.Coupon != "" {
		sp.Coupon = &stripeData.Coupon
	}

	s, err := sub.New(sp)
	if err != nil {
		return err
	}

	err = ua.s.SetStripeIDs(r.Context(), userID, customer.ID, s.ID)
	if err != nil {
		return err
	}

	return writeSuccess(w, "stripe subscription created")
}

// ListSessions writes out all of a users current / past sessions
func (ua *UserAPI) ListSessions(w http.ResponseWriter, r *http.Request) error {
	key, err := ua.ks.Verify(r.Header.Get("X-Hydrocarbon-Key"))
	if err != nil {
		return err
	}

	sess, err := ua.s.ListSessions(r.Context(), key, 0)
	if err != nil {
		return err
	}

	return writeSuccess(w, sess)
}

// Activate exchanges a token for a session key that can be used to make
// authenticated requests
func (ua *UserAPI) Activate(w http.ResponseWriter, r *http.Request) error {
	var activateData struct {
		Token string `json:"token"`
	}

	err := limitDecoder(r, &activateData)
	if err != nil {
		return err
	}

	userID, err := ua.s.ActivateLoginToken(r.Context(), activateData.Token)
	if err != nil {
		return err
	}

	email, key, err := ua.s.CreateSession(r.Context(), userID, r.UserAgent(), getRemoteIP(r))
	if err != nil {
		return err
	}

	key, err = ua.ks.Sign(key)
	if err != nil {
		return err
	}

	var activationData = struct {
		Email string `json:"email"`
		Key   string `json:"key"`
	}{
		email,
		key,
	}

	return writeSuccess(w, activationData)
}

// Deactivate disables a key that the user is currently using
func (ua *UserAPI) Deactivate(w http.ResponseWriter, r *http.Request) error {
	key, err := ua.ks.Verify(r.Header.Get("X-Hydrocarbon-Key"))
	if err != nil {
		return err
	}

	err = ua.s.DeactivateSession(r.Context(), key)
	if err != nil {
		return err
	}

	return writeSuccess(w, nil)
}

func getRemoteIP(r *http.Request) string {
	fwdIP := r.Header.Get("X-Forwarded-For")
	fwdSplit := strings.Split(fwdIP, ",")
	if fwdIP != "" {
		// pick the leftmost x-forwarded-for addr
		return fwdSplit[0]
	}

	// this literally can't fail on r.RemoteAddr
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return r.RemoteAddr
	}
	return ip
}
<|endoftext|>


<commit_before>// util/log.go
// Copyright(c) 2017 Matt Pharr
// BSD licensed; see LICENSE for details.

package util

import (
	"fmt"
	"io"
	"os"
	"path"
	"runtime"
	"strings"
	"sync"
)

// Logger provides a simple logging system with a few different log levels;
// debugging and verbose output may both be suppressed independently.
type Logger struct {
	NErrors int
	mu      sync.Mutex
	debug   io.Writer
	verbose io.Writer
	warning io.Writer
	err     io.Writer
}

func NewLogger(verbose, debug bool) *Logger {
	l := &Logger{}
	if verbose {
		l.verbose = os.Stderr
	}
	if debug {
		l.debug = os.Stderr
	}
	l.warning = os.Stderr
	l.err = os.Stderr
	return l
}

func (l *Logger) Print(f string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "%s", format(f, args...))
}

func (l *Logger) Debug(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	if l.debug == nil {
		return
	}
	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.debug, format(f, args...))
}

func (l *Logger) Verbose(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	if l.verbose == nil {
		return
	}
	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.verbose, format(f, args...))
}

func (l *Logger) Warning(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.warning, format(f, args...))
}

func (l *Logger) Error(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	l.NErrors++
	fmt.Fprint(l.err, format(f, args...))
}

func (l *Logger) Fatal(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	l.NErrors++
	fmt.Fprint(l.err, format(f, args...))
	os.Exit(1)
}

// Checks the provided condition and prints a fatal error if it's false.
// The error message includes the source file and line number where the
// check failed.  An optional message specified with printf-style
// formatting may be provided to print with the error message.
func (l *Logger) Check(v bool, msg ...interface{}) {
	if v {
		return
	}

	if l != nil {
		l.mu.Lock()
		defer l.mu.Unlock()
		l.NErrors++
	}

	if len(msg) == 0 {
		fmt.Fprint(l.err, format("Check failed\n"))
	} else {
		f := msg[0].(string)
		fmt.Fprint(l.err, format(f, msg[1:]...))
	}
	os.Exit(1)
}

// Similar to Check, CheckError prints a fatal error if the given error is
// non-nil.  It also takes an optional format string.
func (l *Logger) CheckError(err error, msg ...interface{}) {
	if err == nil {
		return
	}

	if l != nil {
		l.mu.Lock()
		defer l.mu.Unlock()
		l.NErrors++
	}

	if len(msg) == 0 {
		fmt.Fprint(l.err, format("Error: %+v\n", err))
	} else {
		f := msg[0].(string)
		fmt.Fprint(l.err, format(f, msg[1:]...))
	}
	os.Exit(1)
}

func format(f string, args ...interface{}) string {
	// Two levels up the call stack
	_, fn, line, _ := runtime.Caller(2)
	// Last two components of the path
	fnline := path.Base(path.Dir(fn)) + "/" + path.Base(fn) + fmt.Sprintf(":%d", line)
	s := fmt.Sprintf("%-25s: ", fnline)
	s += fmt.Sprintf(f, args...)
	if !strings.HasSuffix(s, "\n") {
		s += "\n"
	}
	return s
}
<commit_msg>Allow nil *Logger in Check methods<commit_after>// util/log.go
// Copyright(c) 2017 Matt Pharr
// BSD licensed; see LICENSE for details.

package util

import (
	"fmt"
	"io"
	"os"
	"path"
	"runtime"
	"strings"
	"sync"
)

// Logger provides a simple logging system with a few different log levels;
// debugging and verbose output may both be suppressed independently.
type Logger struct {
	NErrors int
	mu      sync.Mutex
	debug   io.Writer
	verbose io.Writer
	warning io.Writer
	err     io.Writer
}

func NewLogger(verbose, debug bool) *Logger {
	l := &Logger{}
	if verbose {
		l.verbose = os.Stderr
	}
	if debug {
		l.debug = os.Stderr
	}
	l.warning = os.Stderr
	l.err = os.Stderr
	return l
}

func (l *Logger) Print(f string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "%s", format(f, args...))
}

func (l *Logger) Debug(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	if l.debug == nil {
		return
	}
	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.debug, format(f, args...))
}

func (l *Logger) Verbose(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	if l.verbose == nil {
		return
	}
	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.verbose, format(f, args...))
}

func (l *Logger) Warning(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	fmt.Fprint(l.warning, format(f, args...))
}

func (l *Logger) Error(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	l.NErrors++
	fmt.Fprint(l.err, format(f, args...))
}

func (l *Logger) Fatal(f string, args ...interface{}) {
	if l == nil {
		fmt.Fprintf(os.Stderr, format(f, args...))
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()
	l.NErrors++
	fmt.Fprint(l.err, format(f, args...))
	os.Exit(1)
}

// Checks the provided condition and prints a fatal error if it's false.
// The error message includes the source file and line number where the
// check failed.  An optional message specified with printf-style
// formatting may be provided to print with the error message.
func (l *Logger) Check(v bool, msg ...interface{}) {
	if v {
		return
	}

	var w io.Writer
	if l != nil {
		l.mu.Lock()
		defer l.mu.Unlock()
		l.NErrors++
		w = l.err
	} else {
		w = os.Stderr
	}

	if len(msg) == 0 {
		fmt.Fprint(w, format("Check failed\n"))
	} else {
		f := msg[0].(string)
		fmt.Fprint(w, format(f, msg[1:]...))
	}
	os.Exit(1)
}

// Similar to Check, CheckError prints a fatal error if the given error is
// non-nil.  It also takes an optional format string.
func (l *Logger) CheckError(err error, msg ...interface{}) {
	if err == nil {
		return
	}

	var w io.Writer
	if l != nil {
		l.mu.Lock()
		defer l.mu.Unlock()
		l.NErrors++
		w = l.err
	} else {
		w = os.Stderr
	}

	if len(msg) == 0 {
		fmt.Fprint(w, format("Error: %+v\n", err))
	} else {
		f := msg[0].(string)
		fmt.Fprint(w, format(f, msg[1:]...))
	}
	panic(err)
	os.Exit(1)
}

func format(f string, args ...interface{}) string {
	// Two levels up the call stack
	_, fn, line, _ := runtime.Caller(2)
	// Last two components of the path
	fnline := path.Base(path.Dir(fn)) + "/" + path.Base(fn) + fmt.Sprintf(":%d", line)
	s := fmt.Sprintf("%-25s: ", fnline)
	s += fmt.Sprintf(f, args...)
	if !strings.HasSuffix(s, "\n") {
		s += "\n"
	}
	return s
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"testing"

	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMLoadBalancerNatPool_basic(t *testing.T) {
	var lb network.LoadBalancer
	ri := acctest.RandInt()
	natPoolName := fmt.Sprintf("NatPool-%d", ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
				),
			},
		},
	})
}

func TestAccAzureRMLoadBalancerNatPool_removal(t *testing.T) {
	var lb network.LoadBalancer
	ri := acctest.RandInt()
	natPoolName := fmt.Sprintf("NatPool-%d", ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
				),
			},
			{
				Config: testAccAzureRMLoadBalancerNatPool_removal(ri),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName, &lb),
				),
			},
		},
	})
}

func testCheckAzureRMLoadBalancerNatPoolExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
		if !exists {
			return fmt.Errorf("A NAT Pool with name %q cannot be found.", natPoolName)
		}

		return nil
	}
}

func testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
		if exists {
			return fmt.Errorf("A NAT Pool with name %q has been found.", natPoolName)
		}

		return nil
	}
}

func testAccAzureRMLoadBalancerNatPool_basic(rInt int, natPoolName string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
    name = "acctestrg-%d"
    location = "West US"
}

resource "azurerm_public_ip" "test" {
    name = "test-ip-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"
    public_ip_address_allocation = "static"
}

resource "azurerm_lb" "test" {
    name = "arm-test-loadbalancer-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"

    frontend_ip_configuration {
      name = "one-%d"
      public_ip_address_id = "${azurerm_public_ip.test.id}"
    }
}

resource "azurerm_lb_nat_pool" "test" {
  location = "West US"
  resource_group_name = "${azurerm_resource_group.test.name}"
  loadbalancer_id = "${azurerm_lb.test.id}"
  name = "%s"
  protocol = "Tcp"
  frontend_port_start = 80
  frontend_port_end = 81
  backend_port = 3389
  frontend_ip_configuration_name = "one-%d"
}

`, rInt, rInt, rInt, rInt, natPoolName, rInt)
}

func testAccAzureRMLoadBalancerNatPool_removal(rInt int) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
    name = "acctestrg-%d"
    location = "West US"
}

resource "azurerm_public_ip" "test" {
    name = "test-ip-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"
    public_ip_address_allocation = "static"
}

resource "azurerm_lb" "test" {
    name = "arm-test-loadbalancer-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"

    frontend_ip_configuration {
      name = "one-%d"
      public_ip_address_id = "${azurerm_public_ip.test.id}"
    }
}
`, rInt, rInt, rInt, rInt)
}
<commit_msg>Update test for azurerm_lb_nat_pool id.<commit_after>package azurerm

import (
	"fmt"
	"os"
	"testing"

	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMLoadBalancerNatPool_basic(t *testing.T) {
	var lb network.LoadBalancer
	ri := acctest.RandInt()
	natPoolName := fmt.Sprintf("NatPool-%d", ri)

	testAccPreCheck(t)
	subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID")
	natPool_id := fmt.Sprintf(
		"/subscriptions/%s/resourceGroups/acctestrg-%d/providers/Microsoft.Network/loadBalancers/arm-test-loadbalancer-%d/inboundNatPools/%s",
		subscriptionID, ri, ri, natPoolName)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
					resource.TestCheckResourceAttr(
						"azurerm_lb_nat_pool.test", "id", natPool_id),
				),
			},
		},
	})
}

func TestAccAzureRMLoadBalancerNatPool_removal(t *testing.T) {
	var lb network.LoadBalancer
	ri := acctest.RandInt()
	natPoolName := fmt.Sprintf("NatPool-%d", ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMLoadBalancerDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAzureRMLoadBalancerNatPool_basic(ri, natPoolName),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolExists(natPoolName, &lb),
				),
			},
			{
				Config: testAccAzureRMLoadBalancerNatPool_removal(ri),
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMLoadBalancerExists("azurerm_lb.test", &lb),
					testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName, &lb),
				),
			},
		},
	})
}

func testCheckAzureRMLoadBalancerNatPoolExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
		if !exists {
			return fmt.Errorf("A NAT Pool with name %q cannot be found.", natPoolName)
		}

		return nil
	}
}

func testCheckAzureRMLoadBalancerNatPoolNotExists(natPoolName string, lb *network.LoadBalancer) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, _, exists := findLoadBalancerNatPoolByName(lb, natPoolName)
		if exists {
			return fmt.Errorf("A NAT Pool with name %q has been found.", natPoolName)
		}

		return nil
	}
}

func testAccAzureRMLoadBalancerNatPool_basic(rInt int, natPoolName string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
    name = "acctestrg-%d"
    location = "West US"
}

resource "azurerm_public_ip" "test" {
    name = "test-ip-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"
    public_ip_address_allocation = "static"
}

resource "azurerm_lb" "test" {
    name = "arm-test-loadbalancer-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"

    frontend_ip_configuration {
      name = "one-%d"
      public_ip_address_id = "${azurerm_public_ip.test.id}"
    }
}

resource "azurerm_lb_nat_pool" "test" {
  location = "West US"
  resource_group_name = "${azurerm_resource_group.test.name}"
  loadbalancer_id = "${azurerm_lb.test.id}"
  name = "%s"
  protocol = "Tcp"
  frontend_port_start = 80
  frontend_port_end = 81
  backend_port = 3389
  frontend_ip_configuration_name = "one-%d"
}

`, rInt, rInt, rInt, rInt, natPoolName, rInt)
}

func testAccAzureRMLoadBalancerNatPool_removal(rInt int) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
    name = "acctestrg-%d"
    location = "West US"
}

resource "azurerm_public_ip" "test" {
    name = "test-ip-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"
    public_ip_address_allocation = "static"
}

resource "azurerm_lb" "test" {
    name = "arm-test-loadbalancer-%d"
    location = "West US"
    resource_group_name = "${azurerm_resource_group.test.name}"

    frontend_ip_configuration {
      name = "one-%d"
      public_ip_address_id = "${azurerm_public_ip.test.id}"
    }
}
`, rInt, rInt, rInt, rInt)
}
<|endoftext|>


<commit_before>package captain // import "github.com/harbur/captain/captain"

import (
	"fmt"
	"os"

	"github.com/fsouza/go-dockerclient"
)

var endpoint = "unix:///var/run/docker.sock"
var client, _ = docker.NewClient(endpoint)

func buildImage(dockerfile string, image string, tag string) error {
	info("Building image %s:%s", image, tag)

	// Nasty issue with CircleCI https://github.com/docker/docker/issues/4897
	if os.Getenv("CIRCLECI") == "true" {
		info("Running at %s environment...", "CIRCLECI")
		execute("docker", "build", "-t", image+":"+tag, ".")
		return nil
	} else {
		opts := docker.BuildImageOptions{
			Name:                image + ":" + tag,
			Dockerfile:          dockerfile,
			NoCache:             options.force,
			SuppressOutput:      false,
			RmTmpContainer:      true,
			ForceRmTmpContainer: true,
			OutputStream:        os.Stdout,
			ContextDir:          ".",
		}
		err := client.BuildImage(opts)
		if err != nil {
			fmt.Printf("%s", err)
		}
		return err
	}
}

func tagImage(repo string, origin string, tag string) error {
	if tag != "" {
		info("Tagging image %s:%s as %s:%s", repo, origin, repo, tag)
		// var imageID = getImageID(repo, origin)
		opts := docker.TagImageOptions{Repo: repo, Tag: tag, Force: true}
		err := client.TagImage(repo, opts)
		if err != nil {
			fmt.Printf("%s", err)
		}
		return err
	} else {
		debug("Skipping tag of %s - no git repository", repo)
	}
	return nil
}

func getImageID(repo string, tag string) string {
	images, _ := client.ListImages(docker.ListImagesOptions{})
	for _, image := range images {
		for _, b := range image.RepoTags {
			if b == repo+":"+tag {
				return image.ID
			}
		}
	}
	return ""
}

func imageExist(repo string, tag string) bool {
	images, _ := client.ListImages(docker.ListImagesOptions{})
	for _, image := range images {
		for _, b := range image.RepoTags {
			if b == repo+":"+tag {
				return true
			}
		}
	}
	return false
}
<commit_msg>Dockerfiles inside subdirectories now have the correct contextDir<commit_after>package captain // import "github.com/harbur/captain/captain"

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/fsouza/go-dockerclient"
)

var endpoint = "unix:///var/run/docker.sock"
var client, _ = docker.NewClient(endpoint)

func buildImage(dockerfile string, image string, tag string) error {
	info("Building image %s:%s", image, tag)

	// Nasty issue with CircleCI https://github.com/docker/docker/issues/4897
	if os.Getenv("CIRCLECI") == "true" {
		info("Running at %s environment...", "CIRCLECI")
		execute("docker", "build", "-t", image+":"+tag, ".")
		return nil
	} else {
		opts := docker.BuildImageOptions{
			Name:                image + ":" + tag,
			Dockerfile:          filepath.Base(dockerfile),
			NoCache:             options.force,
			SuppressOutput:      false,
			RmTmpContainer:      true,
			ForceRmTmpContainer: true,
			OutputStream:        os.Stdout,
			ContextDir:          filepath.Dir(dockerfile),
		}
		err := client.BuildImage(opts)
		if err != nil {
			fmt.Printf("%s", err)
		}
		return err
	}
}

func tagImage(repo string, origin string, tag string) error {
	if tag != "" {
		info("Tagging image %s:%s as %s:%s", repo, origin, repo, tag)
		// var imageID = getImageID(repo, origin)
		opts := docker.TagImageOptions{Repo: repo, Tag: tag, Force: true}
		err := client.TagImage(repo, opts)
		if err != nil {
			fmt.Printf("%s", err)
		}
		return err
	} else {
		debug("Skipping tag of %s - no git repository", repo)
	}
	return nil
}

func getImageID(repo string, tag string) string {
	images, _ := client.ListImages(docker.ListImagesOptions{})
	for _, image := range images {
		for _, b := range image.RepoTags {
			if b == repo+":"+tag {
				return image.ID
			}
		}
	}
	return ""
}

func imageExist(repo string, tag string) bool {
	images, _ := client.ListImages(docker.ListImagesOptions{})
	for _, image := range images {
		for _, b := range image.RepoTags {
			if b == repo+":"+tag {
				return true
			}
		}
	}
	return false
}
<|endoftext|>


<commit_before>package openstack

import (
	"fmt"
	"log"
	"time"

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

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

func resourceNetworkingRouterV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingRouterV2Create,
		Read:   resourceNetworkingRouterV2Read,
		Update: resourceNetworkingRouterV2Update,
		Delete: resourceNetworkingRouterV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"admin_state_up": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: false,
				Computed: true,
			},
			"distributed": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"external_gateway": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"tenant_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
		},
	}
}

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

	createOpts := routers.CreateOpts{
		Name:     d.Get("name").(string),
		TenantID: d.Get("tenant_id").(string),
	}

	if asuRaw, ok := d.GetOk("admin_state_up"); ok {
		asu := asuRaw.(bool)
		createOpts.AdminStateUp = &asu
	}

	if dRaw, ok := d.GetOk("distributed"); ok {
		d := dRaw.(bool)
		createOpts.Distributed = &d
	}

	externalGateway := d.Get("external_gateway").(string)
	if externalGateway != "" {
		gatewayInfo := routers.GatewayInfo{
			NetworkID: externalGateway,
		}
		createOpts.GatewayInfo = &gatewayInfo
	}

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

	log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID)
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
		Target:     []string{"ACTIVE"},
		Refresh:    waitForRouterActive(networkingClient, n.ID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(n.ID)

	return resourceNetworkingRouterV2Read(d, meta)
}

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

	n, err := routers.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		httpError, ok := err.(*gophercloud.UnexpectedResponseCodeError)
		if !ok {
			return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err)
		}

		if httpError.Actual == 404 {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err)
	}

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

	d.Set("name", n.Name)
	d.Set("admin_state_up", n.AdminStateUp)
	d.Set("distributed", n.Distributed)
	d.Set("tenant_id", n.TenantID)
	d.Set("external_gateway", n.GatewayInfo.NetworkID)

	return nil
}

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

	var updateOpts routers.UpdateOpts
	if d.HasChange("name") {
		updateOpts.Name = d.Get("name").(string)
	}
	if d.HasChange("admin_state_up") {
		asu := d.Get("admin_state_up").(bool)
		updateOpts.AdminStateUp = &asu
	}

	log.Printf("[DEBUG] Updating Router %s with options: %+v", d.Id(), updateOpts)

	_, err = routers.Update(networkingClient, d.Id(), updateOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error updating OpenStack Neutron Router: %s", err)
	}

	return resourceNetworkingRouterV2Read(d, meta)
}

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

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

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

	d.SetId("")
	return nil
}

func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		r, err := routers.Get(networkingClient, routerId).Extract()
		if err != nil {
			return nil, r.Status, err
		}

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

func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId)

		r, err := routers.Get(networkingClient, routerId).Extract()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return r, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
				return r, "DELETED", nil
			}
		}

		err = routers.Delete(networkingClient, routerId).ExtractErr()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return r, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
				return r, "DELETED", nil
			}
		}

		log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId)
		return r, "ACTIVE", nil
	}
}
<commit_msg>provider/openstack: Add value_specs for routers<commit_after>package openstack

import (
	"fmt"
	"log"
	"time"

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

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

func resourceNetworkingRouterV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingRouterV2Create,
		Read:   resourceNetworkingRouterV2Read,
		Update: resourceNetworkingRouterV2Update,
		Delete: resourceNetworkingRouterV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"admin_state_up": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: false,
				Computed: true,
			},
			"distributed": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"external_gateway": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"tenant_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"value_specs": &schema.Schema{
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

// routerCreateOpts contains all the values needed to create a new router. There are
// no required values.
type RouterCreateOpts struct {
	Name         string
	AdminStateUp *bool
	Distributed  *bool
	TenantID     string
	GatewayInfo  *routers.GatewayInfo
	ValueSpecs   map[string]string
}

// ToRouterCreateMap casts a routerCreateOpts struct to a map.
func (opts RouterCreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
	r := make(map[string]interface{})

	if gophercloud.MaybeString(opts.Name) != nil {
		r["name"] = opts.Name
	}

	if opts.AdminStateUp != nil {
		r["admin_state_up"] = opts.AdminStateUp
	}

	if opts.Distributed != nil {
		r["distributed"] = opts.Distributed
	}

	if gophercloud.MaybeString(opts.TenantID) != nil {
		r["tenant_id"] = opts.TenantID
	}

	if opts.GatewayInfo != nil {
		r["external_gateway_info"] = opts.GatewayInfo
	}

	if opts.ValueSpecs != nil {
		for k, v := range opts.ValueSpecs {
			r[k] = v
		}
	}

	return map[string]interface{}{"router": r}, nil
}

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

	createOpts := RouterCreateOpts{
		Name:       d.Get("name").(string),
		TenantID:   d.Get("tenant_id").(string),
		ValueSpecs: routerValueSpecs(d),
	}

	if asuRaw, ok := d.GetOk("admin_state_up"); ok {
		asu := asuRaw.(bool)
		createOpts.AdminStateUp = &asu
	}

	if dRaw, ok := d.GetOk("distributed"); ok {
		d := dRaw.(bool)
		createOpts.Distributed = &d
	}

	externalGateway := d.Get("external_gateway").(string)
	if externalGateway != "" {
		gatewayInfo := routers.GatewayInfo{
			NetworkID: externalGateway,
		}
		createOpts.GatewayInfo = &gatewayInfo
	}

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

	log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID)
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
		Target:     []string{"ACTIVE"},
		Refresh:    waitForRouterActive(networkingClient, n.ID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(n.ID)

	return resourceNetworkingRouterV2Read(d, meta)
}

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

	n, err := routers.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		httpError, ok := err.(*gophercloud.UnexpectedResponseCodeError)
		if !ok {
			return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err)
		}

		if httpError.Actual == 404 {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err)
	}

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

	d.Set("name", n.Name)
	d.Set("admin_state_up", n.AdminStateUp)
	d.Set("distributed", n.Distributed)
	d.Set("tenant_id", n.TenantID)
	d.Set("external_gateway", n.GatewayInfo.NetworkID)

	return nil
}

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

	var updateOpts routers.UpdateOpts
	if d.HasChange("name") {
		updateOpts.Name = d.Get("name").(string)
	}
	if d.HasChange("admin_state_up") {
		asu := d.Get("admin_state_up").(bool)
		updateOpts.AdminStateUp = &asu
	}

	log.Printf("[DEBUG] Updating Router %s with options: %+v", d.Id(), updateOpts)

	_, err = routers.Update(networkingClient, d.Id(), updateOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error updating OpenStack Neutron Router: %s", err)
	}

	return resourceNetworkingRouterV2Read(d, meta)
}

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

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

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

	d.SetId("")
	return nil
}

func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		r, err := routers.Get(networkingClient, routerId).Extract()
		if err != nil {
			return nil, r.Status, err
		}

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

func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId)

		r, err := routers.Get(networkingClient, routerId).Extract()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return r, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
				return r, "DELETED", nil
			}
		}

		err = routers.Delete(networkingClient, routerId).ExtractErr()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return r, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
				return r, "DELETED", nil
			}
		}

		log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId)
		return r, "ACTIVE", nil
	}
}

func routerValueSpecs(d *schema.ResourceData) map[string]string {
	m := make(map[string]string)
	for key, val := range d.Get("value_specs").(map[string]interface{}) {
		m[key] = val.(string)
	}
	return m
}
<|endoftext|>


<commit_before>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package vcl

import (
	"fmt"
	"os"
	"runtime"

	. "github.com/ying32/govcl/vcl/api"
)

const (
	// CN: 要求最小liblcl或者libvcl二进制版本为2.0.1
	// EN: Requires a minimum liblcl or libvcl binary version of 2.0.1.
	requireMinBinaryVersion = 0x02000100
)

var (
	// 几个实例类，不需要Create即可访问，同时也不需要手动Free

	Application *TApplication // 应用程序管理
	Screen      *TScreen      // 屏幕
	Mouse       *TMouse       // 鼠标
	Clipboard   *TClipboard   // 剪切板
	Printer     *TPrinter     // 打印机
)

func toVersionString(ver uint32) string {
	if byte(ver) == 0 {
		return fmt.Sprintf("%d.%d.%d", byte(ver>>24), byte(ver>>16), byte(ver>>8))
	}
	return fmt.Sprintf("%d.%d.%d.%d", byte(ver>>24), byte(ver>>16), byte(ver>>8), byte(ver))
}

func init() {
	defer func() {
		if err := recover(); err != nil {
			showError(err)
			os.Exit(1)
		}
	}()
	libVersion := DLibVersion()
	fmt.Println("Library Version:", toVersionString(libVersion))
	if libVersion < requireMinBinaryVersion {
		panic("Require liblcl binary version >=2.0.1. Please go to \"https://github.com/ying32/govcl\" to download the latest binary.")
	}
	// 这个似乎得默认加上，锁定主线程，防止中间被改变
	runtime.LockOSThread()
	// 设置事件的回调函数，因go中callback数量有限，只好折中处理
	SetEventCallback(eventCallback)
	// 消息回调
	SetMessageCallback(messageCallback)
	// 线程同步回调
	SetThreadSyncCallback(threadSyncCallback)

	// 导入几个实例类
	Application = AsApplication(Application_Instance())
	Screen = AsScreen(Screen_Instance())
	Mouse = AsMouse(Mouse_Instance())
	Clipboard = AsClipboard(Clipboard_Instance())
	Printer = AsPrinter(Printer_Instance())

	// 尝试加载ICON，仅Windows下有效，尝试加载名为MAINICON的图标
	tryLoadAppIcon()
}
<commit_msg> Requires a minimum liblcl or libvcl binary version of 2.0.2.<commit_after>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package vcl

import (
	"fmt"
	"os"
	"runtime"

	. "github.com/ying32/govcl/vcl/api"
)

const (
	// CN: 要求最小liblcl或者libvcl二进制版本为2.0.2
	// EN: Requires a minimum liblcl or libvcl binary version of 2.0.2.
	requireMinBinaryVersion = 0x02000200
)

var (
	// 几个实例类，不需要Create即可访问，同时也不需要手动Free

	Application *TApplication // 应用程序管理
	Screen      *TScreen      // 屏幕
	Mouse       *TMouse       // 鼠标
	Clipboard   *TClipboard   // 剪切板
	Printer     *TPrinter     // 打印机
)

func toVersionString(ver uint32) string {
	if byte(ver) == 0 {
		return fmt.Sprintf("%d.%d.%d", byte(ver>>24), byte(ver>>16), byte(ver>>8))
	}
	return fmt.Sprintf("%d.%d.%d.%d", byte(ver>>24), byte(ver>>16), byte(ver>>8), byte(ver))
}

func init() {
	defer func() {
		if err := recover(); err != nil {
			showError(err)
			os.Exit(1)
		}
	}()
	libVersion := DLibVersion()
	fmt.Println("Library Version:", toVersionString(libVersion))
	if libVersion < requireMinBinaryVersion {
		panic("Require liblcl binary version >=2.0.2. Please go to \"https://github.com/ying32/govcl\" to download the latest binary.")
	}
	// 这个似乎得默认加上，锁定主线程，防止中间被改变
	runtime.LockOSThread()
	// 设置事件的回调函数，因go中callback数量有限，只好折中处理
	SetEventCallback(eventCallback)
	// 消息回调
	SetMessageCallback(messageCallback)
	// 线程同步回调
	SetThreadSyncCallback(threadSyncCallback)

	// 导入几个实例类
	Application = AsApplication(Application_Instance())
	Screen = AsScreen(Screen_Instance())
	Mouse = AsMouse(Mouse_Instance())
	Clipboard = AsClipboard(Clipboard_Instance())
	Printer = AsPrinter(Printer_Instance())

	// 尝试加载ICON，仅Windows下有效，尝试加载名为MAINICON的图标
	tryLoadAppIcon()
}
<|endoftext|>


<commit_before>package main

import (
	"git.ianfross.com/ifross/expensetracker/auth"
	"git.ianfross.com/ifross/expensetracker/env"
	"git.ianfross.com/ifross/expensetracker/handlers"
	"git.ianfross.com/ifross/expensetracker/models"
	"git.ianfross.com/ifross/expensetracker/models/postgrestore"

	"github.com/jmoiron/sqlx"
	"github.com/julienschmidt/httprouter"

	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

type actionsMap map[string]func() error

func (a actionsMap) available() string {
	var actions []string
	for k, _ := range a {
		actions = append(actions, k)
	}
	return "[" + strings.Join(actions, ", ") + "]"
}

func (a actionsMap) validAction(action string) bool {
	_, ok := a[action]
	return ok
}

func (a actionsMap) perform(action string) {
	err := a[action]()
	if err != nil {
		panic(err)
	}
}

var (
	dbUser = flag.String("db_user", "expensetracker", "database user to connect with")
	dbName = flag.String("db_name", "expensetracker", "name of the database to connect to")
	dbPw   = flag.String("db_pw", "", "user's database password")
	port   = flag.Int("port", 8181, "HTTP port to listen on")
	action = flag.String("action", "start", "action to perform. Available: "+actions.available())
)

func DBConn() *sqlx.DB {
	return sqlx.MustOpen("postgres", fmt.Sprintf("user=%s dbname=%s password=%s sslmode=disable", *dbUser, *dbName, *dbPw))
}

func start() error {
	db := DBConn()
	store := postgrestore.MustCreate(db)
	sessionStore := auth.NewCookieSessionStore(
		[]byte("new-authentication-key"),
		[]byte("new-encryption-key"))

	um := auth.NewUserManager(nil, store, nil, sessionStore)
	m := models.NewManager(store)

	e := &env.Env{
		m,
		um,
		env.Config{
			Port: *port,
		},
	}

	router := httprouter.New()
	// Main React route
	router.GET("/", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		f, _ := os.Open("html/index.html")
		io.Copy(w, f)
		f.Close()
	})

	// CSS, JS, etc
	router.ServeFiles("/static/*filepath", http.Dir("static"))

	// Admin Routes
	router.GET("/admin/users", CreateHandlerWithEnv(e, handlers.CreateAdminUsersGETHandler))
	router.POST("/admin/user", CreateHandlerWithEnv(e, handlers.CreateAdminUsersPOSTHandler))
	router.DELETE("/admin/user/:user_id", CreateHandlerWithEnv(e, handlers.CreateAdminUserDELETEHandler))

	fmt.Println("Server started on port", e.Conf.Port)
	return http.ListenAndServe(fmt.Sprintf(":%d", e.Conf.Port), router)
}

func createSchema() error {
	db := DBConn()
	store := postgrestore.MustCreate(db)

	store.MustCreateTypes()
	store.MustCreateTables()
	return nil
}

func dropSchema() error {
	db := DBConn()
	store := postgrestore.MustCreate(db)

	store.MustDropTables()
	store.MustDropTypes()
	return nil
}

func addAdmin() error {
	fmt.Println("Adding admin")
	return nil
}

var actions = actionsMap{
	"start":         start,
	"create_schema": createSchema,
	"drop_schema":   dropSchema,
	"add_admin":     addAdmin,
}

func main() {
	flag.Parse()
	if !actions.validAction(*action) {
		fmt.Println("Please choose a valid action. Available: " + actions.available())
		os.Exit(1)
	}

	actions.perform(*action)
}

type InitHandler func(*env.Env, http.ResponseWriter, *http.Request, httprouter.Params) (http.Handler, int, error)

func CreateHandlerWithEnv(e *env.Env, ih InitHandler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		start := time.Now()
		h, status, err := ih(e, w, r, ps)
		fmt.Printf("HTTP %d: %v\n", status, err)
		if err != nil {
			switch status {
			case http.StatusNotFound:
				http.NotFound(w, r)
			case http.StatusInternalServerError:
				http.Error(w, http.StatusText(status), status)
			default:
				http.Error(w, http.StatusText(status), status)
			}
		}

		h.ServeHTTP(w, r)
		fmt.Printf("Request server in %v\n", time.Since(start))
	}
}
<commit_msg>Added in database host and port to command line flags. Also fixed bug with statements not being prepared when the server starts<commit_after>package main

import (
	"git.ianfross.com/ifross/expensetracker/auth"
	"git.ianfross.com/ifross/expensetracker/env"
	"git.ianfross.com/ifross/expensetracker/handlers"
	"git.ianfross.com/ifross/expensetracker/models"
	"git.ianfross.com/ifross/expensetracker/models/postgrestore"

	"github.com/jmoiron/sqlx"
	"github.com/julienschmidt/httprouter"

	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

type actionsMap map[string]func() error

func (a actionsMap) available() string {
	var actions []string
	for k, _ := range a {
		actions = append(actions, k)
	}
	return "[" + strings.Join(actions, ", ") + "]"
}

func (a actionsMap) validAction(action string) bool {
	_, ok := a[action]
	return ok
}

func (a actionsMap) perform(action string) {
	err := a[action]()
	if err != nil {
		panic(err)
	}
}

var (
	dbUser = flag.String("db_user", "expensetracker", "database user to connect with")
	dbName = flag.String("db_name", "expensetracker", "name of the database to connect to")
	dbPw   = flag.String("db_pw", "", "user's database password")
	dbHost = flag.String("db_host", "localhost", "host the database is running on")
	dbPort = flag.Int("db_port", 5432, "port the database is listening on")
	port   = flag.Int("port", 8181, "HTTP port to listen on")
	action = flag.String("action", "start", "action to perform. Available: "+actions.available())
)

func DBConn() *sqlx.DB {
	return sqlx.MustOpen("postgres",
		fmt.Sprintf("user=%s dbname=%s password=%s host=%s port=%d sslmode=disable",
			*dbUser, *dbName, *dbPw, *dbHost, *dbPort))
}

func start() error {
	db := DBConn()

	store := postgrestore.MustCreate(db)
	store.MustPrepareStmts()
	sessionStore := auth.NewCookieSessionStore(
		[]byte("new-authentication-key"),
		[]byte("new-encryption-key"))

	um := auth.NewUserManager(nil, store, nil, sessionStore)
	m := models.NewManager(store)

	e := &env.Env{
		m,
		um,
		env.Config{
			Port: *port,
		},
	}

	router := httprouter.New()
	// Main React route
	router.GET("/", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		f, _ := os.Open("html/index.html")
		io.Copy(w, f)
		f.Close()
	})

	// CSS, JS, etc
	router.ServeFiles("/static/*filepath", http.Dir("static"))

	// Admin Routes
	router.GET("/admin/users", CreateHandlerWithEnv(e, handlers.CreateAdminUsersGETHandler))
	router.POST("/admin/user", CreateHandlerWithEnv(e, handlers.CreateAdminUsersPOSTHandler))
	router.DELETE("/admin/user/:user_id", CreateHandlerWithEnv(e, handlers.CreateAdminUserDELETEHandler))

	fmt.Println("Server started on port", e.Conf.Port)
	return http.ListenAndServe(fmt.Sprintf(":%d", e.Conf.Port), router)
}

func createSchema() error {
	db := DBConn()
	store := postgrestore.MustCreate(db)

	store.MustCreateTypes()
	store.MustCreateTables()
	return nil
}

func dropSchema() error {
	db := DBConn()
	store := postgrestore.MustCreate(db)

	store.MustDropTables()
	store.MustDropTypes()
	return nil
}

func addAdmin() error {
	fmt.Println("Adding admin")
	return nil
}

var actions = actionsMap{
	"start":         start,
	"create_schema": createSchema,
	"drop_schema":   dropSchema,
	"add_admin":     addAdmin,
}

func main() {
	flag.Parse()
	if !actions.validAction(*action) {
		fmt.Println("Please choose a valid action. Available: " + actions.available())
		os.Exit(1)
	}

	actions.perform(*action)
}

type InitHandler func(*env.Env, http.ResponseWriter, *http.Request, httprouter.Params) (http.Handler, int, error)

func CreateHandlerWithEnv(e *env.Env, ih InitHandler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		start := time.Now()
		h, status, err := ih(e, w, r, ps)
		fmt.Printf("HTTP %d: %v\n", status, err)
		if err != nil {
			switch status {
			case http.StatusNotFound:
				http.NotFound(w, r)
			case http.StatusInternalServerError:
				http.Error(w, http.StatusText(status), status)
			default:
				http.Error(w, http.StatusText(status), status)
			}
		}

		h.ServeHTTP(w, r)
		fmt.Printf("Request server in %v\n", time.Since(start))
	}
}
<|endoftext|>


<commit_before>package geometry

import (
	"math"
)

type Vector2D struct {
	X, Y float64
}

func DotProduct2D(v1, v2 Vector2D) float64 {
	return v1.X*v2.X + v1.Y*v2.Y
}

func (v Vector2D) ToLine2D() Line2D {
	return Line2D{Point2D{0, 0}, Point2D(v)}
}

func (v1 Vector2D) Plus(v2 Vector2D) Vector2D {
	return Vector2D{v1.X + v2.X, v1.Y + v2.Y}
}

func (v1 *Vector2D) Add(v2 Vector2D) {
	v1.X += v2.X
	v2.Y += v2.Y
}

func (v1 Vector2D) Minus(v2 Vector2D) Vector2D {
	return Vector2D{v1.X - v2.X, v1.Y - v2.Y}
}

func (v1 *Vector2D) Subtract(v2 Vector2D) {
	v1.X -= v2.X
	v1.Y -= v2.Y
}

func (v1 Vector2D) Times(v2 Vector2D) Vector2D {
	return Vector2D{v1.X * v2.X, v1.Y * v2.Y}
}

func (v1 *Vector2D) Multiply(v2 Vector2D) {
	v1.X *= v2.X
	v2.Y *= v2.X
}

func (v1 Vector2D) Divided(v2 Vector2D) Vector2D {
	return Vector2D{v1.X / v2.X, v1.Y / v2.Y}
}

func (v1 *Vector2D) Divide(v2 Vector2D) {
	v1.X /= v2.X
	v1.Y /= v2.Y
}

func (p Vector2D) Scaled(s float64) Vector2D {
	return Vector2D{p.X * s, p.Y * s}
}

func (p *Vector2D) Scale(s float64) {
	p.X *= s
	p.Y *= s
}

func (v Vector2D) Length() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v Vector2D) LengthSquared() float64 {
	return v.X*v.X + v.Y*v.Y
}

func (v Vector2D) Normalized() Vector2D {
	l := 1 / math.Sqrt(v.X*v.X+v.Y*v.Y)
	return Vector2D{v.X * l, v.Y * l}
}

func (v *Vector2D) Normalize() {
	l := 1 / math.Sqrt(v.X*v.X+v.Y*v.Y)
	v.X *= l
	v.Y *= l
}

func (v1 Vector2D) ScalarProjectionOnto(v2 Vector2D) float64 {
	return (v1.X*v2.X + v1.Y*v2.Y) / (v2.X*v2.X + v2.Y*v2.Y)
}

func (v1 Vector2D) VectorProjectionOnto(v2 Vector2D) Vector2D {
	s := (v1.X*v2.X + v1.Y*v2.Y) / (v2.X*v2.X + v2.Y*v2.Y)
	return Vector2D{v2.X * s, v2.Y * s}
}

func (v1 Vector2D) FuzzyEqual(v2 Vector2D) bool {
	return FuzzyEqual(v1.X, v2.X) && FuzzyEqual(v1.Y, v2.Y)
}
<commit_msg>Added check for divide by zero.<commit_after>package geometry

import (
	"math"
)

type Vector2D struct {
	X, Y float64
}

func DotProduct2D(v1, v2 Vector2D) float64 {
	return v1.X*v2.X + v1.Y*v2.Y
}

func (v Vector2D) ToLine2D() Line2D {
	return Line2D{Point2D{0, 0}, Point2D(v)}
}

func (v1 Vector2D) Plus(v2 Vector2D) Vector2D {
	return Vector2D{v1.X + v2.X, v1.Y + v2.Y}
}

func (v1 *Vector2D) Add(v2 Vector2D) {
	v1.X += v2.X
	v2.Y += v2.Y
}

func (v1 Vector2D) Minus(v2 Vector2D) Vector2D {
	return Vector2D{v1.X - v2.X, v1.Y - v2.Y}
}

func (v1 *Vector2D) Subtract(v2 Vector2D) {
	v1.X -= v2.X
	v1.Y -= v2.Y
}

func (v1 Vector2D) Times(v2 Vector2D) Vector2D {
	return Vector2D{v1.X * v2.X, v1.Y * v2.Y}
}

func (v1 *Vector2D) Multiply(v2 Vector2D) {
	v1.X *= v2.X
	v2.Y *= v2.X
}

func (v1 Vector2D) Divided(v2 Vector2D) Vector2D {
	return Vector2D{v1.X / v2.X, v1.Y / v2.Y}
}

func (v1 *Vector2D) Divide(v2 Vector2D) {
	v1.X /= v2.X
	v1.Y /= v2.Y
}

func (p Vector2D) Scaled(s float64) Vector2D {
	return Vector2D{p.X * s, p.Y * s}
}

func (p *Vector2D) Scale(s float64) {
	p.X *= s
	p.Y *= s
}

func (v Vector2D) Length() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v Vector2D) LengthSquared() float64 {
	return v.X*v.X + v.Y*v.Y
}

func (v Vector2D) Normalized() Vector2D {
	if v.X == 0 && v.Y == 0 {
		return v
	}
	l := 1 / math.Sqrt(v.X*v.X+v.Y*v.Y)
	return Vector2D{v.X * l, v.Y * l}
}

func (v *Vector2D) Normalize() {
	if v.X == 0 && v.Y == 0 {
		return
	}
	l := 1 / math.Sqrt(v.X*v.X+v.Y*v.Y)
	v.X *= l
	v.Y *= l
}

func (v1 Vector2D) ScalarProjectionOnto(v2 Vector2D) float64 {
	return (v1.X*v2.X + v1.Y*v2.Y) / (v2.X*v2.X + v2.Y*v2.Y)
}

func (v1 Vector2D) VectorProjectionOnto(v2 Vector2D) Vector2D {
	s := (v1.X*v2.X + v1.Y*v2.Y) / (v2.X*v2.X + v2.Y*v2.Y)
	return Vector2D{v2.X * s, v2.Y * s}
}

func (v1 Vector2D) FuzzyEqual(v2 Vector2D) bool {
	return FuzzyEqual(v1.X, v2.X) && FuzzyEqual(v1.Y, v2.Y)
}
<|endoftext|>