<commit_before>package pdf

import (
	"testing"

	"github.com/jelmersnoeck/noscito/mocks"
	"github.com/jelmersnoeck/noscito/pdf"
	"github.com/stretchr/testify/suite"
)

type AddPageBlockSuite struct {
	suite.Suite
}

func TestAddPageBlockSuite(t *testing.T) {
	suite.Run(t, new(AddPageBlockSuite))
}

func (s *AddPageBlockSuite) TestParse() {
	doc := &mocks.Document{}
	page := &pdf.AddPage{pdf.Margin{5, 10, 15, 20}}

	doc.On("AddPage").Return()
	doc.On("SetMargins", 5.0, 10.0, 15.0).Return()
	doc.On("SetAutoPageBreak", true, 20.0).Return()

	page.Parse(doc)

	doc.AssertExpectations(s.T())
}
<commit_msg>AddPage: correct package name.<commit_after>package pdf_test

import (
	"testing"

	"github.com/jelmersnoeck/noscito/mocks"
	"github.com/jelmersnoeck/noscito/pdf"
	"github.com/stretchr/testify/suite"
)

type AddPageBlockSuite struct {
	suite.Suite
}

func TestAddPageBlockSuite(t *testing.T) {
	suite.Run(t, new(AddPageBlockSuite))
}

func (s *AddPageBlockSuite) TestParse() {
	doc := &mocks.Document{}
	page := &pdf.AddPage{pdf.Margin{5, 10, 15, 20}}

	doc.On("AddPage").Return()
	doc.On("SetMargins", 5.0, 10.0, 15.0).Return()
	doc.On("SetAutoPageBreak", true, 20.0).Return()

	page.Parse(doc)

	doc.AssertExpectations(s.T())
}
<|endoftext|>


<commit_before>//
// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
//

package command

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/packer/plugin"

	alicloudecsbuilder "github.com/hashicorp/packer/builder/alicloud/ecs"
	amazonchrootbuilder "github.com/hashicorp/packer/builder/amazon/chroot"
	amazonebsbuilder "github.com/hashicorp/packer/builder/amazon/ebs"
	amazonebssurrogatebuilder "github.com/hashicorp/packer/builder/amazon/ebssurrogate"
	amazonebsvolumebuilder "github.com/hashicorp/packer/builder/amazon/ebsvolume"
	amazoninstancebuilder "github.com/hashicorp/packer/builder/amazon/instance"
	azurearmbuilder "github.com/hashicorp/packer/builder/azure/arm"
	cloudstackbuilder "github.com/hashicorp/packer/builder/cloudstack"
	digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
	dockerbuilder "github.com/hashicorp/packer/builder/docker"
	filebuilder "github.com/hashicorp/packer/builder/file"
	googlecomputebuilder "github.com/hashicorp/packer/builder/googlecompute"
	hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
	hyperonebuilder "github.com/hashicorp/packer/builder/hyperone"
	hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
	hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
	lxcbuilder "github.com/hashicorp/packer/builder/lxc"
	lxdbuilder "github.com/hashicorp/packer/builder/lxd"
	ncloudbuilder "github.com/hashicorp/packer/builder/ncloud"
	nullbuilder "github.com/hashicorp/packer/builder/null"
	oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
	openstackbuilder "github.com/hashicorp/packer/builder/openstack"
	oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic"
	oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
	parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
	parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
	profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks"
	qemubuilder "github.com/hashicorp/packer/builder/qemu"
	scalewaybuilder "github.com/hashicorp/packer/builder/scaleway"
	tencentcloudcvmbuilder "github.com/hashicorp/packer/builder/tencentcloud/cvm"
	tritonbuilder "github.com/hashicorp/packer/builder/triton"
	vagrantbuilder "github.com/hashicorp/packer/builder/vagrant"
	virtualboxisobuilder "github.com/hashicorp/packer/builder/virtualbox/iso"
	virtualboxovfbuilder "github.com/hashicorp/packer/builder/virtualbox/ovf"
	vmwareisobuilder "github.com/hashicorp/packer/builder/vmware/iso"
	vmwarevmxbuilder "github.com/hashicorp/packer/builder/vmware/vmx"
	alicloudimportpostprocessor "github.com/hashicorp/packer/post-processor/alicloud-import"
	amazonimportpostprocessor "github.com/hashicorp/packer/post-processor/amazon-import"
	artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice"
	checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum"
	compresspostprocessor "github.com/hashicorp/packer/post-processor/compress"
	digitaloceanimportpostprocessor "github.com/hashicorp/packer/post-processor/digitalocean-import"
	dockerimportpostprocessor "github.com/hashicorp/packer/post-processor/docker-import"
	dockerpushpostprocessor "github.com/hashicorp/packer/post-processor/docker-push"
	dockersavepostprocessor "github.com/hashicorp/packer/post-processor/docker-save"
	dockertagpostprocessor "github.com/hashicorp/packer/post-processor/docker-tag"
	googlecomputeexportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-export"
	googlecomputeimportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-import"
	manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
	shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
	vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
	vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
	vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
	vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
	ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible"
	ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local"
	breakpointprovisioner "github.com/hashicorp/packer/provisioner/breakpoint"
	chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client"
	chefsoloprovisioner "github.com/hashicorp/packer/provisioner/chef-solo"
	convergeprovisioner "github.com/hashicorp/packer/provisioner/converge"
	fileprovisioner "github.com/hashicorp/packer/provisioner/file"
	inspecprovisioner "github.com/hashicorp/packer/provisioner/inspec"
	powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
	puppetmasterlessprovisioner "github.com/hashicorp/packer/provisioner/puppet-masterless"
	puppetserverprovisioner "github.com/hashicorp/packer/provisioner/puppet-server"
	saltmasterlessprovisioner "github.com/hashicorp/packer/provisioner/salt-masterless"
	shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
	shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
	sleepprovisioner "github.com/hashicorp/packer/provisioner/sleep"
	windowsrestartprovisioner "github.com/hashicorp/packer/provisioner/windows-restart"
	windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"
)

type PluginCommand struct {
	Meta
}

var Builders = map[string]packer.Builder{
	"alicloud-ecs":        new(alicloudecsbuilder.Builder),
	"amazon-chroot":       new(amazonchrootbuilder.Builder),
	"amazon-ebs":          new(amazonebsbuilder.Builder),
	"amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
	"amazon-ebsvolume":    new(amazonebsvolumebuilder.Builder),
	"amazon-instance":     new(amazoninstancebuilder.Builder),
	"azure-arm":           new(azurearmbuilder.Builder),
	"cloudstack":          new(cloudstackbuilder.Builder),
	"digitalocean":        new(digitaloceanbuilder.Builder),
	"docker":              new(dockerbuilder.Builder),
	"file":                new(filebuilder.Builder),
	"googlecompute":       new(googlecomputebuilder.Builder),
	"hcloud":              new(hcloudbuilder.Builder),
	"hyperone":            new(hyperonebuilder.Builder),
	"hyperv-iso":          new(hypervisobuilder.Builder),
	"hyperv-vmcx":         new(hypervvmcxbuilder.Builder),
	"lxc":                 new(lxcbuilder.Builder),
	"lxd":                 new(lxdbuilder.Builder),
	"ncloud":              new(ncloudbuilder.Builder),
	"null":                new(nullbuilder.Builder),
	"oneandone":           new(oneandonebuilder.Builder),
	"openstack":           new(openstackbuilder.Builder),
	"oracle-classic":      new(oracleclassicbuilder.Builder),
	"oracle-oci":          new(oracleocibuilder.Builder),
	"parallels-iso":       new(parallelsisobuilder.Builder),
	"parallels-pvm":       new(parallelspvmbuilder.Builder),
	"profitbricks":        new(profitbricksbuilder.Builder),
	"qemu":                new(qemubuilder.Builder),
	"scaleway":            new(scalewaybuilder.Builder),
	"tencentcloud-cvm":    new(tencentcloudcvmbuilder.Builder),
	"triton":              new(tritonbuilder.Builder),
	"vagrant":             new(vagrantbuilder.Builder),
	"virtualbox-iso":      new(virtualboxisobuilder.Builder),
	"virtualbox-ovf":      new(virtualboxovfbuilder.Builder),
	"vmware-iso":          new(vmwareisobuilder.Builder),
	"vmware-vmx":          new(vmwarevmxbuilder.Builder),
}

var Provisioners = map[string]packer.Provisioner{
	"ansible":           new(ansibleprovisioner.Provisioner),
	"ansible-local":     new(ansiblelocalprovisioner.Provisioner),
	"breakpoint":        new(breakpointprovisioner.Provisioner),
	"chef-client":       new(chefclientprovisioner.Provisioner),
	"chef-solo":         new(chefsoloprovisioner.Provisioner),
	"converge":          new(convergeprovisioner.Provisioner),
	"file":              new(fileprovisioner.Provisioner),
	"inspec":            new(inspecprovisioner.Provisioner),
	"powershell":        new(powershellprovisioner.Provisioner),
	"puppet-masterless": new(puppetmasterlessprovisioner.Provisioner),
	"puppet-server":     new(puppetserverprovisioner.Provisioner),
	"salt-masterless":   new(saltmasterlessprovisioner.Provisioner),
	"shell":             new(shellprovisioner.Provisioner),
	"shell-local":       new(shelllocalprovisioner.Provisioner),
	"sleep":             new(sleepprovisioner.Provisioner),
	"windows-restart":   new(windowsrestartprovisioner.Provisioner),
	"windows-shell":     new(windowsshellprovisioner.Provisioner),
}

var PostProcessors = map[string]packer.PostProcessor{
	"alicloud-import":      new(alicloudimportpostprocessor.PostProcessor),
	"amazon-import":        new(amazonimportpostprocessor.PostProcessor),
	"artifice":             new(artificepostprocessor.PostProcessor),
	"checksum":             new(checksumpostprocessor.PostProcessor),
	"compress":             new(compresspostprocessor.PostProcessor),
	"digitalocean-import":  new(digitaloceanimportpostprocessor.PostProcessor),
	"docker-import":        new(dockerimportpostprocessor.PostProcessor),
	"docker-push":          new(dockerpushpostprocessor.PostProcessor),
	"docker-save":          new(dockersavepostprocessor.PostProcessor),
	"docker-tag":           new(dockertagpostprocessor.PostProcessor),
	"googlecompute-export": new(googlecomputeexportpostprocessor.PostProcessor),
	"googlecompute-import": new(googlecomputeimportpostprocessor.PostProcessor),
	"manifest":             new(manifestpostprocessor.PostProcessor),
	"shell-local":          new(shelllocalpostprocessor.PostProcessor),
	"vagrant":              new(vagrantpostprocessor.PostProcessor),
	"vagrant-cloud":        new(vagrantcloudpostprocessor.PostProcessor),
	"vsphere":              new(vspherepostprocessor.PostProcessor),
	"vsphere-template":     new(vspheretemplatepostprocessor.PostProcessor),
}

var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")

func (c *PluginCommand) Run(args []string) int {
	// This is an internal call (users should not call this directly) so we're
	// not going to do much input validation. If there's a problem we'll often
	// just crash. Error handling should be added to facilitate debugging.
	log.Printf("args: %#v", args)
	if len(args) != 1 {
		c.Ui.Error("Wrong number of args")
		return 1
	}

	// Plugin will match something like "packer-builder-amazon-ebs"
	parts := pluginRegexp.FindStringSubmatch(args[0])
	if len(parts) != 3 {
		c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
		return 1
	}
	pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
	pluginName := parts[2] // capture group 2 (.+)

	server, err := plugin.Server()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
		return 1
	}

	switch pluginType {
	case "builder":
		builder, found := Builders[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
			return 1
		}
		server.RegisterBuilder(builder)
	case "provisioner":
		provisioner, found := Provisioners[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
			return 1
		}
		server.RegisterProvisioner(provisioner)
	case "post-processor":
		postProcessor, found := PostProcessors[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
			return 1
		}
		server.RegisterPostProcessor(postProcessor)
	}

	server.Serve()

	return 0
}

func (*PluginCommand) Help() string {
	helpText := `
Usage: packer plugin PLUGIN

  Runs an internally-compiled version of a plugin from the packer binary.

  NOTE: this is an internal command and you should not call it yourself.
`

	return strings.TrimSpace(helpText)
}

func (c *PluginCommand) Synopsis() string {
	return "internal plugin command"
}
<commit_msg>Add 'yandex' plugin as Builder<commit_after>//
// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
//

package command

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/packer/plugin"

	alicloudecsbuilder "github.com/hashicorp/packer/builder/alicloud/ecs"
	amazonchrootbuilder "github.com/hashicorp/packer/builder/amazon/chroot"
	amazonebsbuilder "github.com/hashicorp/packer/builder/amazon/ebs"
	amazonebssurrogatebuilder "github.com/hashicorp/packer/builder/amazon/ebssurrogate"
	amazonebsvolumebuilder "github.com/hashicorp/packer/builder/amazon/ebsvolume"
	amazoninstancebuilder "github.com/hashicorp/packer/builder/amazon/instance"
	azurearmbuilder "github.com/hashicorp/packer/builder/azure/arm"
	cloudstackbuilder "github.com/hashicorp/packer/builder/cloudstack"
	digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
	dockerbuilder "github.com/hashicorp/packer/builder/docker"
	filebuilder "github.com/hashicorp/packer/builder/file"
	googlecomputebuilder "github.com/hashicorp/packer/builder/googlecompute"
	hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
	hyperonebuilder "github.com/hashicorp/packer/builder/hyperone"
	hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
	hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
	lxcbuilder "github.com/hashicorp/packer/builder/lxc"
	lxdbuilder "github.com/hashicorp/packer/builder/lxd"
	ncloudbuilder "github.com/hashicorp/packer/builder/ncloud"
	nullbuilder "github.com/hashicorp/packer/builder/null"
	oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
	openstackbuilder "github.com/hashicorp/packer/builder/openstack"
	oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic"
	oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
	parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
	parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
	profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks"
	qemubuilder "github.com/hashicorp/packer/builder/qemu"
	scalewaybuilder "github.com/hashicorp/packer/builder/scaleway"
	tencentcloudcvmbuilder "github.com/hashicorp/packer/builder/tencentcloud/cvm"
	tritonbuilder "github.com/hashicorp/packer/builder/triton"
	vagrantbuilder "github.com/hashicorp/packer/builder/vagrant"
	virtualboxisobuilder "github.com/hashicorp/packer/builder/virtualbox/iso"
	virtualboxovfbuilder "github.com/hashicorp/packer/builder/virtualbox/ovf"
	vmwareisobuilder "github.com/hashicorp/packer/builder/vmware/iso"
	vmwarevmxbuilder "github.com/hashicorp/packer/builder/vmware/vmx"
	yandexbuilder "github.com/hashicorp/packer/builder/yandex"
	alicloudimportpostprocessor "github.com/hashicorp/packer/post-processor/alicloud-import"
	amazonimportpostprocessor "github.com/hashicorp/packer/post-processor/amazon-import"
	artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice"
	checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum"
	compresspostprocessor "github.com/hashicorp/packer/post-processor/compress"
	digitaloceanimportpostprocessor "github.com/hashicorp/packer/post-processor/digitalocean-import"
	dockerimportpostprocessor "github.com/hashicorp/packer/post-processor/docker-import"
	dockerpushpostprocessor "github.com/hashicorp/packer/post-processor/docker-push"
	dockersavepostprocessor "github.com/hashicorp/packer/post-processor/docker-save"
	dockertagpostprocessor "github.com/hashicorp/packer/post-processor/docker-tag"
	googlecomputeexportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-export"
	googlecomputeimportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-import"
	manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
	shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
	vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
	vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
	vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
	vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
	ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible"
	ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local"
	breakpointprovisioner "github.com/hashicorp/packer/provisioner/breakpoint"
	chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client"
	chefsoloprovisioner "github.com/hashicorp/packer/provisioner/chef-solo"
	convergeprovisioner "github.com/hashicorp/packer/provisioner/converge"
	fileprovisioner "github.com/hashicorp/packer/provisioner/file"
	inspecprovisioner "github.com/hashicorp/packer/provisioner/inspec"
	powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
	puppetmasterlessprovisioner "github.com/hashicorp/packer/provisioner/puppet-masterless"
	puppetserverprovisioner "github.com/hashicorp/packer/provisioner/puppet-server"
	saltmasterlessprovisioner "github.com/hashicorp/packer/provisioner/salt-masterless"
	shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
	shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
	sleepprovisioner "github.com/hashicorp/packer/provisioner/sleep"
	windowsrestartprovisioner "github.com/hashicorp/packer/provisioner/windows-restart"
	windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"
)

type PluginCommand struct {
	Meta
}

var Builders = map[string]packer.Builder{
	"alicloud-ecs":        new(alicloudecsbuilder.Builder),
	"amazon-chroot":       new(amazonchrootbuilder.Builder),
	"amazon-ebs":          new(amazonebsbuilder.Builder),
	"amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
	"amazon-ebsvolume":    new(amazonebsvolumebuilder.Builder),
	"amazon-instance":     new(amazoninstancebuilder.Builder),
	"azure-arm":           new(azurearmbuilder.Builder),
	"cloudstack":          new(cloudstackbuilder.Builder),
	"digitalocean":        new(digitaloceanbuilder.Builder),
	"docker":              new(dockerbuilder.Builder),
	"file":                new(filebuilder.Builder),
	"googlecompute":       new(googlecomputebuilder.Builder),
	"hcloud":              new(hcloudbuilder.Builder),
	"hyperone":            new(hyperonebuilder.Builder),
	"hyperv-iso":          new(hypervisobuilder.Builder),
	"hyperv-vmcx":         new(hypervvmcxbuilder.Builder),
	"lxc":                 new(lxcbuilder.Builder),
	"lxd":                 new(lxdbuilder.Builder),
	"ncloud":              new(ncloudbuilder.Builder),
	"null":                new(nullbuilder.Builder),
	"oneandone":           new(oneandonebuilder.Builder),
	"openstack":           new(openstackbuilder.Builder),
	"oracle-classic":      new(oracleclassicbuilder.Builder),
	"oracle-oci":          new(oracleocibuilder.Builder),
	"parallels-iso":       new(parallelsisobuilder.Builder),
	"parallels-pvm":       new(parallelspvmbuilder.Builder),
	"profitbricks":        new(profitbricksbuilder.Builder),
	"qemu":                new(qemubuilder.Builder),
	"scaleway":            new(scalewaybuilder.Builder),
	"tencentcloud-cvm":    new(tencentcloudcvmbuilder.Builder),
	"triton":              new(tritonbuilder.Builder),
	"vagrant":             new(vagrantbuilder.Builder),
	"virtualbox-iso":      new(virtualboxisobuilder.Builder),
	"virtualbox-ovf":      new(virtualboxovfbuilder.Builder),
	"vmware-iso":          new(vmwareisobuilder.Builder),
	"vmware-vmx":          new(vmwarevmxbuilder.Builder),
	"yandex":              new(yandexbuilder.Builder),
}

var Provisioners = map[string]packer.Provisioner{
	"ansible":           new(ansibleprovisioner.Provisioner),
	"ansible-local":     new(ansiblelocalprovisioner.Provisioner),
	"breakpoint":        new(breakpointprovisioner.Provisioner),
	"chef-client":       new(chefclientprovisioner.Provisioner),
	"chef-solo":         new(chefsoloprovisioner.Provisioner),
	"converge":          new(convergeprovisioner.Provisioner),
	"file":              new(fileprovisioner.Provisioner),
	"inspec":            new(inspecprovisioner.Provisioner),
	"powershell":        new(powershellprovisioner.Provisioner),
	"puppet-masterless": new(puppetmasterlessprovisioner.Provisioner),
	"puppet-server":     new(puppetserverprovisioner.Provisioner),
	"salt-masterless":   new(saltmasterlessprovisioner.Provisioner),
	"shell":             new(shellprovisioner.Provisioner),
	"shell-local":       new(shelllocalprovisioner.Provisioner),
	"sleep":             new(sleepprovisioner.Provisioner),
	"windows-restart":   new(windowsrestartprovisioner.Provisioner),
	"windows-shell":     new(windowsshellprovisioner.Provisioner),
}

var PostProcessors = map[string]packer.PostProcessor{
	"alicloud-import":      new(alicloudimportpostprocessor.PostProcessor),
	"amazon-import":        new(amazonimportpostprocessor.PostProcessor),
	"artifice":             new(artificepostprocessor.PostProcessor),
	"checksum":             new(checksumpostprocessor.PostProcessor),
	"compress":             new(compresspostprocessor.PostProcessor),
	"digitalocean-import":  new(digitaloceanimportpostprocessor.PostProcessor),
	"docker-import":        new(dockerimportpostprocessor.PostProcessor),
	"docker-push":          new(dockerpushpostprocessor.PostProcessor),
	"docker-save":          new(dockersavepostprocessor.PostProcessor),
	"docker-tag":           new(dockertagpostprocessor.PostProcessor),
	"googlecompute-export": new(googlecomputeexportpostprocessor.PostProcessor),
	"googlecompute-import": new(googlecomputeimportpostprocessor.PostProcessor),
	"manifest":             new(manifestpostprocessor.PostProcessor),
	"shell-local":          new(shelllocalpostprocessor.PostProcessor),
	"vagrant":              new(vagrantpostprocessor.PostProcessor),
	"vagrant-cloud":        new(vagrantcloudpostprocessor.PostProcessor),
	"vsphere":              new(vspherepostprocessor.PostProcessor),
	"vsphere-template":     new(vspheretemplatepostprocessor.PostProcessor),
}

var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")

func (c *PluginCommand) Run(args []string) int {
	// This is an internal call (users should not call this directly) so we're
	// not going to do much input validation. If there's a problem we'll often
	// just crash. Error handling should be added to facilitate debugging.
	log.Printf("args: %#v", args)
	if len(args) != 1 {
		c.Ui.Error("Wrong number of args")
		return 1
	}

	// Plugin will match something like "packer-builder-amazon-ebs"
	parts := pluginRegexp.FindStringSubmatch(args[0])
	if len(parts) != 3 {
		c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
		return 1
	}
	pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
	pluginName := parts[2] // capture group 2 (.+)

	server, err := plugin.Server()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
		return 1
	}

	switch pluginType {
	case "builder":
		builder, found := Builders[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
			return 1
		}
		server.RegisterBuilder(builder)
	case "provisioner":
		provisioner, found := Provisioners[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
			return 1
		}
		server.RegisterProvisioner(provisioner)
	case "post-processor":
		postProcessor, found := PostProcessors[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
			return 1
		}
		server.RegisterPostProcessor(postProcessor)
	}

	server.Serve()

	return 0
}

func (*PluginCommand) Help() string {
	helpText := `
Usage: packer plugin PLUGIN

  Runs an internally-compiled version of a plugin from the packer binary.

  NOTE: this is an internal command and you should not call it yourself.
`

	return strings.TrimSpace(helpText)
}

func (c *PluginCommand) Synopsis() string {
	return "internal plugin command"
}
<|endoftext|>


<commit_before>package command

import (
	"bytes"
	"fmt"
	"os"
	"strings"

	"github.com/jrasell/levant/helper"
	"github.com/jrasell/levant/levant"
)

// RenderCommand is the command implementation that allows users to render a
// Nomad job template based on passed templates and variables.
type RenderCommand struct {
	args []string
	Meta
}

// Help provides the help information for the template command.
func (c *RenderCommand) Help() string {
	helpText := `
Usage: levant render [options] [TEMPLATE]

  Render a Nomad job template, useful for debugging.

Arguments:

  TEMPLATE  nomad job template
    If no argument is given we look for a single *.nomad file

General Options:

  -out=<file>
    Specify the path to write the rendered template out to, if a file exists at
    the specified path it will be truncated before rendering. The template will be
    rendered to stdout if this is not set.

  -var-file=<file>
    The variables file to render the template with. [default: levant.(yaml|yml|tf)]
`
	return strings.TrimSpace(helpText)
}

// Synopsis is provides a brief summary of the template command.
func (c *RenderCommand) Synopsis() string {
	return "Render a Nomad job from a template"
}

// Run triggers a run of the Levant template functions.
func (c *RenderCommand) Run(args []string) int {

	var variables, outPath, templateFile string
	var err error
	var tpl *bytes.Buffer

	flags := c.Meta.FlagSet("render", FlagSetVars)
	flags.Usage = func() { c.UI.Output(c.Help()) }

	flags.StringVar(&variables, "var-file", "", "")
	flags.StringVar(&outPath, "out", "", "")

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

	args = flags.Args()

	if len(args) == 1 {
		templateFile = args[0]
	} else if len(args) == 0 {
		if templateFile = helper.GetDefaultTmplFile(); templateFile == "" {
			c.UI.Error(c.Help())
			return 1
		}
	} else {
		c.UI.Error(c.Help())
		return 1
	}

	tpl, err = levant.RenderTemplate(templateFile, variables, &c.Meta.flagVars)
	if err != nil {
		c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
		return 1
	}

	out := os.Stdout
	if outPath != "" {
		out, err = os.Create(outPath)
		if err != nil {
			c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
			return 1
		}
	}

	_, err = tpl.WriteTo(out)
	if err != nil {
		c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
		return 1
	}

	return 0
}
<commit_msg>Add error msg if no arg is given and no default template is found<commit_after>package command

import (
	"bytes"
	"fmt"
	"os"
	"strings"

	"github.com/jrasell/levant/helper"
	"github.com/jrasell/levant/levant"
)

// RenderCommand is the command implementation that allows users to render a
// Nomad job template based on passed templates and variables.
type RenderCommand struct {
	args []string
	Meta
}

// Help provides the help information for the template command.
func (c *RenderCommand) Help() string {
	helpText := `
Usage: levant render [options] [TEMPLATE]

  Render a Nomad job template, useful for debugging.

Arguments:

  TEMPLATE  nomad job template
    If no argument is given we look for a single *.nomad file

General Options:

  -out=<file>
    Specify the path to write the rendered template out to, if a file exists at
    the specified path it will be truncated before rendering. The template will be
    rendered to stdout if this is not set.

  -var-file=<file>
    The variables file to render the template with. [default: levant.(yaml|yml|tf)]
`
	return strings.TrimSpace(helpText)
}

// Synopsis is provides a brief summary of the template command.
func (c *RenderCommand) Synopsis() string {
	return "Render a Nomad job from a template"
}

// Run triggers a run of the Levant template functions.
func (c *RenderCommand) Run(args []string) int {

	var variables, outPath, templateFile string
	var err error
	var tpl *bytes.Buffer

	flags := c.Meta.FlagSet("render", FlagSetVars)
	flags.Usage = func() { c.UI.Output(c.Help()) }

	flags.StringVar(&variables, "var-file", "", "")
	flags.StringVar(&outPath, "out", "", "")

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

	args = flags.Args()

	if len(args) == 1 {
		templateFile = args[0]
	} else if len(args) == 0 {
		if templateFile = helper.GetDefaultTmplFile(); templateFile == "" {
			c.UI.Error(c.Help())
			c.UI.Error("\nERROR: Template arg missing and no default template found")
			return 1
		}
	} else {
		c.UI.Error(c.Help())
		return 1
	}

	tpl, err = levant.RenderTemplate(templateFile, variables, &c.Meta.flagVars)
	if err != nil {
		c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
		return 1
	}

	out := os.Stdout
	if outPath != "" {
		out, err = os.Create(outPath)
		if err != nil {
			c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
			return 1
		}
	}

	_, err = tpl.WriteTo(out)
	if err != nil {
		c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
		return 1
	}

	return 0
}
<|endoftext|>


<commit_before>package persister

import (
	"fmt"
	"hash/crc32"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/lomik/go-whisper"

	"github.com/lomik/go-carbon/points"
)

// Whisper write data to *.wsp files
type Whisper struct {
	updateOperations    uint32
	commitedPoints      uint32
	in                  chan *points.Points
	exit                chan bool
	schemas             *WhisperSchemas
	aggregation         *WhisperAggregation
	metricInterval      time.Duration // checkpoint interval
	workersCount        int
	rootPath            string
	graphPrefix         string
	created             uint32 // counter
	maxUpdatesPerSecond int
}

// NewWhisper create instance of Whisper
func NewWhisper(rootPath string, schemas *WhisperSchemas, aggregation *WhisperAggregation, in chan *points.Points) *Whisper {
	return &Whisper{
		in:                  in,
		exit:                make(chan bool),
		schemas:             schemas,
		aggregation:         aggregation,
		metricInterval:      time.Minute,
		workersCount:        1,
		rootPath:            rootPath,
		maxUpdatesPerSecond: 0,
	}
}

// SetGraphPrefix for internal cache metrics
func (p *Whisper) SetGraphPrefix(prefix string) {
	p.graphPrefix = prefix
}

// SetMaxUpdatesPerSecond enable throttling
func (p *Whisper) SetMaxUpdatesPerSecond(maxUpdatesPerSecond int) {
	p.maxUpdatesPerSecond = maxUpdatesPerSecond
}

// SetWorkers count
func (p *Whisper) SetWorkers(count int) {
	p.workersCount = count
}

// SetMetricInterval sets doChekpoint interval
func (p *Whisper) SetMetricInterval(interval time.Duration) {
	p.metricInterval = interval
}

// Stat sends internal statistics to cache
func (p *Whisper) Stat(metric string, value float64) {
	p.in <- points.OnePoint(
		fmt.Sprintf("%spersister.%s", p.graphPrefix, metric),
		value,
		time.Now().Unix(),
	)
}

func (p *Whisper) store(values *points.Points) {
	path := filepath.Join(p.rootPath, strings.Replace(values.Metric, ".", "/", -1)+".wsp")

	w, err := whisper.Open(path)
	if err != nil {
		schema := p.schemas.match(values.Metric)
		if schema == nil {
			logrus.Errorf("[persister] No storage schema defined for %s", values.Metric)
			return
		}

		aggr := p.aggregation.match(values.Metric)
		if aggr == nil {
			logrus.Errorf("[persister] No storage aggregation defined for %s", values.Metric)
			return
		}

		logrus.WithFields(logrus.Fields{
			"retention":    schema.retentionStr,
			"schema":       schema.name,
			"aggregation":  aggr.name,
			"xFilesFactor": aggr.xFilesFactor,
			"method":       aggr.aggregationMethodStr,
		}).Debugf("[persister] Creating %s", path)

		if err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm); err != nil {
			logrus.Error(err)
			return
		}

		w, err = whisper.Create(path, schema.retentions, aggr.aggregationMethod, float32(aggr.xFilesFactor))
		if err != nil {
			logrus.Errorf("[persister] Failed to create new whisper file %s: %s", path, err.Error())
			return
		}

		atomic.AddUint32(&p.created, 1)
	}

	points := make([]*whisper.TimeSeriesPoint, len(values.Data))
	for i, r := range values.Data {
		points[i] = &whisper.TimeSeriesPoint{Time: int(r.Timestamp), Value: r.Value}
	}

	atomic.AddUint32(&p.commitedPoints, uint32(len(values.Data)))
	atomic.AddUint32(&p.updateOperations, 1)

	defer w.Close()

	defer func() {
		if r := recover(); r != nil {
			logrus.Errorf("[persister] UpdateMany %s recovered: %s", path, r)
		}
	}()
	w.UpdateMany(points)
}

func (p *Whisper) worker(in chan *points.Points) {
LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case values := <-in:
			p.store(values)
		}
	}
}

func (p *Whisper) shuffler(in chan *points.Points, out [](chan *points.Points)) {
	workers := uint32(len(out))

LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case values := <-in:
			index := crc32.ChecksumIEEE([]byte(values.Metric)) % workers
			out[index] <- values
		}
	}
}

// save stat
func (p *Whisper) doCheckpoint() {
	updateOperations := atomic.LoadUint32(&p.updateOperations)
	commitedPoints := atomic.LoadUint32(&p.commitedPoints)
	atomic.AddUint32(&p.updateOperations, -updateOperations)
	atomic.AddUint32(&p.commitedPoints, -commitedPoints)

	created := atomic.LoadUint32(&p.created)
	atomic.AddUint32(&p.created, -created)

	logrus.WithFields(logrus.Fields{
		"updateOperations": float64(updateOperations),
		"commitedPoints":   float64(commitedPoints),
		"created":          created,
	}).Info("[persister] doCheckpoint()")

	p.Stat("updateOperations", float64(updateOperations))
	p.Stat("commitedPoints", float64(commitedPoints))
	if updateOperations > 0 {
		p.Stat("pointsPerUpdate", float64(commitedPoints)/float64(updateOperations))
	} else {
		p.Stat("pointsPerUpdate", 0.0)
	}

	p.Stat("created", float64(created))

}

// stat timer
func (p *Whisper) statWorker() {
	ticker := time.NewTicker(p.metricInterval)
	defer ticker.Stop()

LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case <-ticker.C:
			go p.doCheckpoint()
		}
	}
}

// Start worker
func (p *Whisper) Start() {
	go p.statWorker()

	inChan := p.in
	if p.maxUpdatesPerSecond > 0 {
		inChan = points.ThrottleChan(inChan, p.maxUpdatesPerSecond)
	}

	if p.workersCount <= 1 { // solo worker
		go p.worker(inChan)
	} else {
		var channels [](chan *points.Points)

		for i := 0; i < p.workersCount; i++ {
			ch := make(chan *points.Points, 32)
			channels = append(channels, ch)
			go p.worker(ch)
		}

		go p.shuffler(inChan, channels)
	}
}

// Stop worker
func (p *Whisper) Stop() {
	close(p.exit)
}
<commit_msg>Mockable persister store function<commit_after>package persister

import (
	"fmt"
	"hash/crc32"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/lomik/go-whisper"

	"github.com/lomik/go-carbon/points"
)

// Whisper write data to *.wsp files
type Whisper struct {
	updateOperations    uint32
	commitedPoints      uint32
	in                  chan *points.Points
	exit                chan bool
	schemas             *WhisperSchemas
	aggregation         *WhisperAggregation
	metricInterval      time.Duration // checkpoint interval
	workersCount        int
	rootPath            string
	graphPrefix         string
	created             uint32 // counter
	maxUpdatesPerSecond int
	mockStore           func(p *Whisper, values *points.Points)
}

// NewWhisper create instance of Whisper
func NewWhisper(rootPath string, schemas *WhisperSchemas, aggregation *WhisperAggregation, in chan *points.Points) *Whisper {
	return &Whisper{
		in:                  in,
		exit:                make(chan bool),
		schemas:             schemas,
		aggregation:         aggregation,
		metricInterval:      time.Minute,
		workersCount:        1,
		rootPath:            rootPath,
		maxUpdatesPerSecond: 0,
	}
}

// SetGraphPrefix for internal cache metrics
func (p *Whisper) SetGraphPrefix(prefix string) {
	p.graphPrefix = prefix
}

// SetMaxUpdatesPerSecond enable throttling
func (p *Whisper) SetMaxUpdatesPerSecond(maxUpdatesPerSecond int) {
	p.maxUpdatesPerSecond = maxUpdatesPerSecond
}

// SetWorkers count
func (p *Whisper) SetWorkers(count int) {
	p.workersCount = count
}

// SetMetricInterval sets doChekpoint interval
func (p *Whisper) SetMetricInterval(interval time.Duration) {
	p.metricInterval = interval
}

// Stat sends internal statistics to cache
func (p *Whisper) Stat(metric string, value float64) {
	p.in <- points.OnePoint(
		fmt.Sprintf("%spersister.%s", p.graphPrefix, metric),
		value,
		time.Now().Unix(),
	)
}

func store(p *Whisper, values *points.Points) {
	path := filepath.Join(p.rootPath, strings.Replace(values.Metric, ".", "/", -1)+".wsp")

	w, err := whisper.Open(path)
	if err != nil {
		schema := p.schemas.match(values.Metric)
		if schema == nil {
			logrus.Errorf("[persister] No storage schema defined for %s", values.Metric)
			return
		}

		aggr := p.aggregation.match(values.Metric)
		if aggr == nil {
			logrus.Errorf("[persister] No storage aggregation defined for %s", values.Metric)
			return
		}

		logrus.WithFields(logrus.Fields{
			"retention":    schema.retentionStr,
			"schema":       schema.name,
			"aggregation":  aggr.name,
			"xFilesFactor": aggr.xFilesFactor,
			"method":       aggr.aggregationMethodStr,
		}).Debugf("[persister] Creating %s", path)

		if err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm); err != nil {
			logrus.Error(err)
			return
		}

		w, err = whisper.Create(path, schema.retentions, aggr.aggregationMethod, float32(aggr.xFilesFactor))
		if err != nil {
			logrus.Errorf("[persister] Failed to create new whisper file %s: %s", path, err.Error())
			return
		}

		atomic.AddUint32(&p.created, 1)
	}

	points := make([]*whisper.TimeSeriesPoint, len(values.Data))
	for i, r := range values.Data {
		points[i] = &whisper.TimeSeriesPoint{Time: int(r.Timestamp), Value: r.Value}
	}

	atomic.AddUint32(&p.commitedPoints, uint32(len(values.Data)))
	atomic.AddUint32(&p.updateOperations, 1)

	defer w.Close()

	defer func() {
		if r := recover(); r != nil {
			logrus.Errorf("[persister] UpdateMany %s recovered: %s", path, r)
		}
	}()
	w.UpdateMany(points)
}

func (p *Whisper) worker(in chan *points.Points) {
	storeFunc := store
	if p.mockStore != nil {
		storeFunc = p.mockStore
	}

LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case values := <-in:
			storeFunc(p, values)
		}
	}
}

func (p *Whisper) shuffler(in chan *points.Points, out [](chan *points.Points)) {
	workers := uint32(len(out))

LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case values := <-in:
			index := crc32.ChecksumIEEE([]byte(values.Metric)) % workers
			out[index] <- values
		}
	}
}

// save stat
func (p *Whisper) doCheckpoint() {
	updateOperations := atomic.LoadUint32(&p.updateOperations)
	commitedPoints := atomic.LoadUint32(&p.commitedPoints)
	atomic.AddUint32(&p.updateOperations, -updateOperations)
	atomic.AddUint32(&p.commitedPoints, -commitedPoints)

	created := atomic.LoadUint32(&p.created)
	atomic.AddUint32(&p.created, -created)

	logrus.WithFields(logrus.Fields{
		"updateOperations": float64(updateOperations),
		"commitedPoints":   float64(commitedPoints),
		"created":          created,
	}).Info("[persister] doCheckpoint()")

	p.Stat("updateOperations", float64(updateOperations))
	p.Stat("commitedPoints", float64(commitedPoints))
	if updateOperations > 0 {
		p.Stat("pointsPerUpdate", float64(commitedPoints)/float64(updateOperations))
	} else {
		p.Stat("pointsPerUpdate", 0.0)
	}

	p.Stat("created", float64(created))

}

// stat timer
func (p *Whisper) statWorker() {
	ticker := time.NewTicker(p.metricInterval)
	defer ticker.Stop()

LOOP:
	for {
		select {
		case <-p.exit:
			break LOOP
		case <-ticker.C:
			go p.doCheckpoint()
		}
	}
}

// Start worker
func (p *Whisper) Start() {
	go p.statWorker()

	inChan := p.in
	if p.maxUpdatesPerSecond > 0 {
		inChan = points.ThrottleChan(inChan, p.maxUpdatesPerSecond)
	}

	if p.workersCount <= 1 { // solo worker
		go p.worker(inChan)
	} else {
		var channels [](chan *points.Points)

		for i := 0; i < p.workersCount; i++ {
			ch := make(chan *points.Points, 32)
			channels = append(channels, ch)
			go p.worker(ch)
		}

		go p.shuffler(inChan, channels)
	}
}

// Stop worker
func (p *Whisper) Stop() {
	close(p.exit)
}
<|endoftext|>


<commit_before>// Copyright 2017 Mathew Robinson <chasinglogic@gmail.com>. All rights reserved.
// Use of this source code is governed by the AGPLv3 license that can be found in
// the LICENSE file.

// Package commands holds all the logic for the CLI of Praelatus
package commands

import (
	"log"
	"net/http"
	"time"

	// Allows us to run profiling when flag is given
	_ "net/http/pprof"

	"github.com/praelatus/praelatus/api"
	"github.com/praelatus/praelatus/config"
	"github.com/praelatus/praelatus/events"
	"github.com/spf13/cobra"
	"github.com/tylerb/graceful"
)

var (
	disableCORS bool
	profile     bool
)

func init() {
	server.Flags().BoolVar(&disableCORS, "nocors", false,
		"If given all Access-Control headers will be set to *")
	server.Flags().BoolVar(&profile, "profile", false,
		"Enables server performance profiling on localhost:6060")
}

var server = &cobra.Command{
	Use:   "serve",
	Short: "Run the praelatus API and UI server.",
	Run: func(cmd *cobra.Command, args []string) {
		log.SetOutput(config.LogWriter())
		log.SetPrefix("[MAIN] ")

		log.Println("Starting Praelatus...")
		log.Println("Connecting to database...")
		rpo := loadRepo()

		api.Version = Version
		api.Commit = Commit

		r := api.New(rpo, nil)

		if profile {
			go func() {
				log.Println(http.ListenAndServe("localhost:6060", nil))
			}()
		}

		log.Println("Staring event manager...")
		go events.Run()

		log.Println("Listening on", config.Port())
		err := graceful.RunWithErr(config.Port(), time.Minute, r)
		if err != nil {
			log.Println("Exited with error:", err)
		}
	},
}
<commit_msg>Add previously missing middleware to serve command<commit_after>// Copyright 2017 Mathew Robinson <chasinglogic@gmail.com>. All rights reserved.
// Use of this source code is governed by the AGPLv3 license that can be found in
// the LICENSE file.

// Package commands holds all the logic for the CLI of Praelatus
package commands

import (
	"log"
	"net/http"
	"time"

	// Allows us to run profiling when flag is given
	_ "net/http/pprof"

	"github.com/praelatus/praelatus/api"
	"github.com/praelatus/praelatus/api/middleware"
	"github.com/praelatus/praelatus/config"
	"github.com/praelatus/praelatus/events"
	"github.com/spf13/cobra"
	"github.com/tylerb/graceful"
)

var (
	disableCORS bool
	profile     bool
)

func init() {
	server.Flags().BoolVar(&disableCORS, "nocors", false,
		"If given all Access-Control headers will be set to *")
	server.Flags().BoolVar(&profile, "profile", false,
		"Enables server performance profiling on localhost:6060")
}

var server = &cobra.Command{
	Use:   "serve",
	Short: "Run the praelatus API and UI server.",
	Run: func(cmd *cobra.Command, args []string) {
		log.SetOutput(config.LogWriter())
		log.SetPrefix("[MAIN] ")

		log.Println("Starting Praelatus...")
		log.Println("Connecting to database...")
		rpo := loadRepo()

		api.Version = Version
		api.Commit = Commit

		r := api.New(rpo, middleware.Default)

		if profile {
			go func() {
				log.Println(http.ListenAndServe("localhost:6060", nil))
			}()
		}

		log.Println("Staring event manager...")
		go events.Run()

		log.Println("Listening on", config.Port())
		err := graceful.RunWithErr(config.Port(), time.Minute, r)
		if err != nil {
			log.Println("Exited with error:", err)
		}
	},
}
<|endoftext|>


<commit_before>package sm_yamux

import (
	"io/ioutil"
	"net"
	"time"

	yamux "github.com/hashicorp/yamux"
	smux "github.com/jbenet/go-stream-muxer"
)

// stream implements smux.Stream using a ss.Stream
type stream yamux.Stream

func (s *stream) yamuxStream() *yamux.Stream {
	return (*yamux.Stream)(s)
}

func (s *stream) Read(buf []byte) (int, error) {
	return s.yamuxStream().Read(buf)
}

func (s *stream) Write(buf []byte) (int, error) {
	return s.yamuxStream().Write(buf)
}

func (s *stream) Close() error {
	return s.yamuxStream().Close()
}

// Conn is a connection to a remote peer.
type conn yamux.Session

func (c *conn) yamuxSession() *yamux.Session {
	return (*yamux.Session)(c)
}

func (c *conn) Close() error {
	return c.yamuxSession().Close()
}

func (c *conn) IsClosed() bool {
	return c.yamuxSession().IsClosed()
}

// OpenStream creates a new stream.
func (c *conn) OpenStream() (smux.Stream, error) {
	s, err := c.yamuxSession().OpenStream()
	if err != nil {
		return nil, err
	}

	return (*stream)(s), nil
}

// AcceptStream accepts a stream opened by the other side.
func (c *conn) AcceptStream() (smux.Stream, error) {
	s, err := c.yamuxSession().AcceptStream()
	return (*stream)(s), err
}

// Serve starts listening for incoming requests and handles them
// using given StreamHandler
func (c *conn) Serve(handler smux.StreamHandler) {
	for { // accept loop
		s, err := c.AcceptStream()
		if err != nil {
			return // err always means closed.
		}
		go handler(s)
	}
}

// Transport is a go-peerstream transport that constructs
// yamux-backed connections.
type Transport yamux.Config

// DefaultTransport has default settings for yamux
var DefaultTransport = (*Transport)(&yamux.Config{
	AcceptBacklog:          256,                // from yamux.DefaultConfig
	EnableKeepAlive:        true,               // from yamux.DefaultConfig
	KeepAliveInterval:      30 * time.Second,   // from yamux.DefaultConfig
	ConnectionWriteTimeout: 10 * time.Second,   // from yamux.DefaultConfig
	MaxStreamWindowSize:    uint32(256 * 1024), // from yamux.DefaultConfig
	LogOutput:              ioutil.Discard,
})

func (t *Transport) NewConn(nc net.Conn, isServer bool) (smux.Conn, error) {
	var s *yamux.Session
	var err error
	if isServer {
		s, err = yamux.Server(nc, t.Config())
	} else {
		s, err = yamux.Client(nc, t.Config())
	}
	return (*conn)(s), err
}

func (t *Transport) Config() *yamux.Config {
	return (*yamux.Config)(t)
}
<commit_msg>add deadline methods to stream<commit_after>package sm_yamux

import (
	"io/ioutil"
	"net"
	"time"

	yamux "github.com/hashicorp/yamux"
	smux "github.com/jbenet/go-stream-muxer"
)

// stream implements smux.Stream using a ss.Stream
// TODO: do we actually need a wrapper here?
type stream yamux.Stream

func (s *stream) yamuxStream() *yamux.Stream {
	return (*yamux.Stream)(s)
}

func (s *stream) Read(buf []byte) (int, error) {
	return s.yamuxStream().Read(buf)
}

func (s *stream) Write(buf []byte) (int, error) {
	return s.yamuxStream().Write(buf)
}

func (s *stream) Close() error {
	return s.yamuxStream().Close()
}

func (s *stream) SetDeadline(t time.Time) error {
	return s.yamuxStream().SetDeadline(t)
}

func (s *stream) SetReadDeadline(t time.Time) error {
	return s.yamuxStream().SetReadDeadline(t)
}

func (s *stream) SetWriteDeadline(t time.Time) error {
	return s.yamuxStream().SetWriteDeadline(t)
}

// Conn is a connection to a remote peer.
type conn yamux.Session

func (c *conn) yamuxSession() *yamux.Session {
	return (*yamux.Session)(c)
}

func (c *conn) Close() error {
	return c.yamuxSession().Close()
}

func (c *conn) IsClosed() bool {
	return c.yamuxSession().IsClosed()
}

// OpenStream creates a new stream.
func (c *conn) OpenStream() (smux.Stream, error) {
	s, err := c.yamuxSession().OpenStream()
	if err != nil {
		return nil, err
	}

	return (*stream)(s), nil
}

// AcceptStream accepts a stream opened by the other side.
func (c *conn) AcceptStream() (smux.Stream, error) {
	s, err := c.yamuxSession().AcceptStream()
	return (*stream)(s), err
}

// Serve starts listening for incoming requests and handles them
// using given StreamHandler
func (c *conn) Serve(handler smux.StreamHandler) {
	for { // accept loop
		s, err := c.AcceptStream()
		if err != nil {
			return // err always means closed.
		}
		go handler(s)
	}
}

// Transport is a go-peerstream transport that constructs
// yamux-backed connections.
type Transport yamux.Config

// DefaultTransport has default settings for yamux
var DefaultTransport = (*Transport)(&yamux.Config{
	AcceptBacklog:          256,                // from yamux.DefaultConfig
	EnableKeepAlive:        true,               // from yamux.DefaultConfig
	KeepAliveInterval:      30 * time.Second,   // from yamux.DefaultConfig
	ConnectionWriteTimeout: 10 * time.Second,   // from yamux.DefaultConfig
	MaxStreamWindowSize:    uint32(256 * 1024), // from yamux.DefaultConfig
	LogOutput:              ioutil.Discard,
})

func (t *Transport) NewConn(nc net.Conn, isServer bool) (smux.Conn, error) {
	var s *yamux.Session
	var err error
	if isServer {
		s, err = yamux.Server(nc, t.Config())
	} else {
		s, err = yamux.Client(nc, t.Config())
	}
	return (*conn)(s), err
}

func (t *Transport) Config() *yamux.Config {
	return (*yamux.Config)(t)
}
<|endoftext|>


<commit_before>package pipeline

import (
	"bytes"
	"fmt"
	"time"

	"github.com/influxdata/kapacitor/tick"
	"github.com/influxdata/kapacitor/tick/stateful"
)

// Information relavant to configuring a deadman's swith
type DeadmanService interface {
	Interval() time.Duration
	Threshold() float64
	Id() string
	Message() string
	Global() bool
}

// Create a template pipeline
// tick:ignore
func CreateTemplatePipeline(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
) (*TemplatePipeline, error) {
	p, vars, err := createPipelineAndVars(script, sourceEdge, scope, deadman, nil, true)
	if err != nil {
		return nil, err
	}
	tp := &TemplatePipeline{
		p:    p,
		vars: vars,
	}
	return tp, nil
}

// Create a pipeline from a given script.
// tick:ignore
func CreatePipeline(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
	predefinedVars map[string]tick.Var,
) (*Pipeline, error) {
	p, _, err := createPipelineAndVars(script, sourceEdge, scope, deadman, predefinedVars, false)
	if err != nil {
		return nil, err
	}
	return p, nil
}

func createPipelineAndVars(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
	predefinedVars map[string]tick.Var,
	ignoreMissingVars bool,
) (*Pipeline, map[string]tick.Var, error) {
	p := &Pipeline{
		deadman: deadman,
	}
	var src Node
	switch sourceEdge {
	case StreamEdge:
		src = newStreamNode()
		scope.Set("stream", src)
	case BatchEdge:
		src = newBatchNode()
		scope.Set("batch", src)
	default:
		return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
	}
	p.addSource(src)

	vars, err := tick.Evaluate(script, scope, predefinedVars, ignoreMissingVars)
	if err != nil {
		return nil, nil, err
	}
	if deadman.Global() {
		switch s := src.(type) {
		case *StreamNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		case *BatchNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		default:
			return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
		}
	}
	if err = p.Walk(
		func(n Node) error {
			return n.validate()
		}); err != nil {
		return nil, nil, err
	}
	return p, vars, nil
}

// A complete data processing pipeline. Starts with a single source.
// tick:ignore
type Pipeline struct {
	sources []Node
	id      ID
	sorted  []Node

	deadman DeadmanService
}

func (p *Pipeline) addSource(src Node) {
	src.setPipeline(p)
	p.assignID(src)
	p.sources = append(p.sources, src)
}

func (p *Pipeline) assignID(n Node) error {
	n.setID(p.id)
	p.id++
	return nil
}

// Walks the entire pipeline and calls func f on each node exactly once.
// f will be called on a node n only after all of its parents have already had f called.
// tick:ignore
func (p *Pipeline) Walk(f func(n Node) error) error {
	if p.sorted == nil {
		p.sort()
	}
	for _, n := range p.sorted {
		err := f(n)
		if err != nil {
			return err
		}
	}
	return nil
}

func (p *Pipeline) sort() {
	// Iterate the sources in reverse order
	for i := len(p.sources) - 1; i >= 0; i-- {
		p.visit(p.sources[i])
	}
	//reverse p.sorted
	s := p.sorted
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

// Depth first search topological sorting of a DAG.
// https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
func (p *Pipeline) visit(n Node) {
	if n.tMark() {
		panic("pipeline contains a cycle")
	}
	if !n.pMark() {
		n.setTMark(true)
		for _, c := range n.Children() {
			p.visit(c)
		}
		n.setPMark(true)
		n.setTMark(false)
		p.sorted = append(p.sorted, n)
	}
}

// Return a graphviz .dot formatted byte array.
// tick:ignore
func (p *Pipeline) Dot(name string) []byte {

	var buf bytes.Buffer

	buf.Write([]byte("digraph "))
	buf.Write([]byte(name))
	buf.Write([]byte(" {\n"))
	p.Walk(func(n Node) error {
		n.dot(&buf)
		return nil
	})
	buf.Write([]byte("}"))

	return buf.Bytes()
}

type TemplatePipeline struct {
	p    *Pipeline
	vars map[string]tick.Var
}

// Return the set of vars defined by the TICKscript with their defaults
// tick:ignore
func (t *TemplatePipeline) Vars() map[string]tick.Var {
	return t.vars
}

// Return a graphviz .dot formatted byte array.
// tick:ignore
func (t *TemplatePipeline) Dot(name string) []byte {
	return t.p.Dot(name)
}
<commit_msg>fix tick docs<commit_after>package pipeline

import (
	"bytes"
	"fmt"
	"time"

	"github.com/influxdata/kapacitor/tick"
	"github.com/influxdata/kapacitor/tick/stateful"
)

// Information relavant to configuring a deadman's swith
type DeadmanService interface {
	Interval() time.Duration
	Threshold() float64
	Id() string
	Message() string
	Global() bool
}

// Create a template pipeline
// tick:ignore
func CreateTemplatePipeline(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
) (*TemplatePipeline, error) {
	p, vars, err := createPipelineAndVars(script, sourceEdge, scope, deadman, nil, true)
	if err != nil {
		return nil, err
	}
	tp := &TemplatePipeline{
		p:    p,
		vars: vars,
	}
	return tp, nil
}

// Create a pipeline from a given script.
// tick:ignore
func CreatePipeline(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
	predefinedVars map[string]tick.Var,
) (*Pipeline, error) {
	p, _, err := createPipelineAndVars(script, sourceEdge, scope, deadman, predefinedVars, false)
	if err != nil {
		return nil, err
	}
	return p, nil
}

func createPipelineAndVars(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
	predefinedVars map[string]tick.Var,
	ignoreMissingVars bool,
) (*Pipeline, map[string]tick.Var, error) {
	p := &Pipeline{
		deadman: deadman,
	}
	var src Node
	switch sourceEdge {
	case StreamEdge:
		src = newStreamNode()
		scope.Set("stream", src)
	case BatchEdge:
		src = newBatchNode()
		scope.Set("batch", src)
	default:
		return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
	}
	p.addSource(src)

	vars, err := tick.Evaluate(script, scope, predefinedVars, ignoreMissingVars)
	if err != nil {
		return nil, nil, err
	}
	if deadman.Global() {
		switch s := src.(type) {
		case *StreamNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		case *BatchNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		default:
			return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
		}
	}
	if err = p.Walk(
		func(n Node) error {
			return n.validate()
		}); err != nil {
		return nil, nil, err
	}
	return p, vars, nil
}

// A complete data processing pipeline. Starts with a single source.
// tick:ignore
type Pipeline struct {
	sources []Node
	id      ID
	sorted  []Node

	deadman DeadmanService
}

func (p *Pipeline) addSource(src Node) {
	src.setPipeline(p)
	p.assignID(src)
	p.sources = append(p.sources, src)
}

func (p *Pipeline) assignID(n Node) error {
	n.setID(p.id)
	p.id++
	return nil
}

// Walks the entire pipeline and calls func f on each node exactly once.
// f will be called on a node n only after all of its parents have already had f called.
// tick:ignore
func (p *Pipeline) Walk(f func(n Node) error) error {
	if p.sorted == nil {
		p.sort()
	}
	for _, n := range p.sorted {
		err := f(n)
		if err != nil {
			return err
		}
	}
	return nil
}

func (p *Pipeline) sort() {
	// Iterate the sources in reverse order
	for i := len(p.sources) - 1; i >= 0; i-- {
		p.visit(p.sources[i])
	}
	//reverse p.sorted
	s := p.sorted
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

// Depth first search topological sorting of a DAG.
// https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
func (p *Pipeline) visit(n Node) {
	if n.tMark() {
		panic("pipeline contains a cycle")
	}
	if !n.pMark() {
		n.setTMark(true)
		for _, c := range n.Children() {
			p.visit(c)
		}
		n.setPMark(true)
		n.setTMark(false)
		p.sorted = append(p.sorted, n)
	}
}

// Return a graphviz .dot formatted byte array.
// tick:ignore
func (p *Pipeline) Dot(name string) []byte {

	var buf bytes.Buffer

	buf.Write([]byte("digraph "))
	buf.Write([]byte(name))
	buf.Write([]byte(" {\n"))
	p.Walk(func(n Node) error {
		n.dot(&buf)
		return nil
	})
	buf.Write([]byte("}"))

	return buf.Bytes()
}

//tick:ignore
type TemplatePipeline struct {
	p    *Pipeline
	vars map[string]tick.Var
}

// Return the set of vars defined by the TICKscript with their defaults
// tick:ignore
func (t *TemplatePipeline) Vars() map[string]tick.Var {
	return t.vars
}

// Return a graphviz .dot formatted byte array.
// tick:ignore
func (t *TemplatePipeline) Dot(name string) []byte {
	return t.p.Dot(name)
}
<|endoftext|>


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

package client

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	clientapi "github.com/cilium/cilium/api/v1/client"
	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/daemon/defaults"
	"github.com/cilium/cilium/pkg/ip"

	runtime_client "github.com/go-openapi/runtime/client"
	"github.com/go-openapi/strfmt"
)

type Client struct {
	clientapi.Cilium
}

func configureTransport(tr *http.Transport, proto, addr string) *http.Transport {
	if tr == nil {
		tr = &http.Transport{}
	}

	if proto == "unix" {
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.Dial(proto, addr)
		}
	} else {
		tr.Proxy = http.ProxyFromEnvironment
		tr.Dial = (&net.Dialer{}).Dial
	}

	return tr
}

// NewDefaultClient creates a client with default parameters connecting to UNIX domain socket.
func NewDefaultClient() (*Client, error) {
	return NewClient("")
}

// NewClient creates a client for the given `host`.
func NewClient(host string) (*Client, error) {
	if host == "" {
		// Check if environment variable points to socket
		e := os.Getenv(defaults.SockPathEnv)
		if e == "" {
			// If unset, fall back to default value
			e = defaults.SockPath
		}
		host = "unix://" + e
	}
	tmp := strings.SplitN(host, "://", 2)
	if len(tmp) != 2 {
		return nil, fmt.Errorf("invalid host format '%s'", host)
	}

	switch tmp[0] {
	case "tcp":
		if _, err := url.Parse("tcp://" + tmp[1]); err != nil {
			return nil, err
		}
		host = "http://" + tmp[1]
	case "unix":
		host = tmp[1]
	}

	transport := configureTransport(nil, tmp[0], host)
	httpClient := &http.Client{Transport: transport}
	clientTrans := runtime_client.NewWithClient(tmp[1], clientapi.DefaultBasePath,
		clientapi.DefaultSchemes, httpClient)
	return &Client{*clientapi.New(clientTrans, strfmt.Default)}, nil
}

// Hint tries to improve the error message displayed to the user.
func Hint(err error) error {
	if err == nil {
		return err
	}
	e, _ := url.PathUnescape(err.Error())
	if strings.Contains(err.Error(), defaults.SockPath) {
		return fmt.Errorf("%s\nIs the agent running?", e)
	}
	return fmt.Errorf("%s", e)
}

func timeSince(since time.Time) string {
	out := "never"
	if !since.IsZero() {
		// Poor man's implementtion of time.Truncate(). Can be refined
		// when we rebase to go 1.9
		t := time.Since(since)
		t -= t % time.Second
		out = t.String() + " ago"
	}

	return out
}

func stateUnhealthy(state string) bool {
	return state == models.StatusStateWarning ||
		state == models.StatusStateFailure
}

func statusUnhealthy(s *models.Status) bool {
	if s != nil {
		return stateUnhealthy(s.State)
	}
	return false
}

// FormatStatusResponseBrief writes a one-line status to the writer. If
// everything ok, this is "ok", otherwise a message of the form "error in ..."
func FormatStatusResponseBrief(w io.Writer, sr *models.StatusResponse) {
	msg := ""

	switch {
	case statusUnhealthy(sr.Cilium):
		msg = fmt.Sprintf("cilium: %s", sr.Cilium.Msg)
	case statusUnhealthy(sr.ContainerRuntime):
		msg = fmt.Sprintf("container runtime: %s", sr.ContainerRuntime.Msg)
	case statusUnhealthy(sr.Kvstore):
		msg = fmt.Sprintf("kvstore: %s", sr.Kvstore.Msg)
	case sr.Kubernetes != nil && stateUnhealthy(sr.Kubernetes.State):
		msg = fmt.Sprintf("kubernetes: %s", sr.Kubernetes.Msg)
	case sr.Cluster != nil && statusUnhealthy(sr.Cluster.CiliumHealth):
		msg = fmt.Sprintf("cilium-health: %s", sr.Cluster.CiliumHealth.Msg)
	}

	// Only bother looking at controller failures if everything else is ok
	if msg == "" {
		for _, ctrl := range sr.Controllers {
			if ctrl.Status == nil {
				continue
			}
			if ctrl.Status.LastFailureMsg != "" {
				msg = fmt.Sprintf("controller %s: %s",
					ctrl.Name, ctrl.Status.LastFailureMsg)
				break
			}
		}
	}

	if msg == "" {
		fmt.Fprintf(w, "OK\n")
	} else {
		fmt.Fprintf(w, "error in %s\n", msg)
	}
}

// FormatStatusResponse writes a StatusResponse as a string to the writer.
//
// The parameters 'allAddresses', 'allControllers', 'allNodes', respectively,
// cause all details about that aspect of the status to be printed to the
// terminal. For each of these, if they are false then only a summary will be
// printed, with perhaps some detail if there are errors.
func FormatStatusResponse(w io.Writer, sr *models.StatusResponse, allAddresses, allControllers, allNodes, allRedirects bool) {
	if sr.Kvstore != nil {
		fmt.Fprintf(w, "KVStore:\t%s\t%s\n", sr.Kvstore.State, sr.Kvstore.Msg)
	}
	if sr.ContainerRuntime != nil {
		fmt.Fprintf(w, "ContainerRuntime:\t%s\t%s\n",
			sr.ContainerRuntime.State, sr.ContainerRuntime.Msg)
	}
	if sr.Kubernetes != nil {
		fmt.Fprintf(w, "Kubernetes:\t%s\t%s\n", sr.Kubernetes.State, sr.Kubernetes.Msg)
		if sr.Kubernetes.State != models.K8sStatusStateDisabled {
			fmt.Fprintf(w, "Kubernetes APIs:\t[\"%s\"]\n", strings.Join(sr.Kubernetes.K8sAPIVersions, "\", \""))
		}
	}
	if sr.Cilium != nil {
		fmt.Fprintf(w, "Cilium:\t%s\t%s\n", sr.Cilium.State, sr.Cilium.Msg)
	}

	if nm := sr.NodeMonitor; nm != nil {
		fmt.Fprintf(w, "NodeMonitor:\tListening for events on %d CPUs with %dx%d of shared memory\n",
			nm.Cpus, nm.Npages, nm.Pagesize)
		if nm.Lost != 0 || nm.Unknown != 0 {
			fmt.Fprintf(w, "\t%d events lost, %d unknown notifications\n", nm.Lost, nm.Unknown)
		}
	} else {
		fmt.Fprintf(w, "NodeMonitor:\tDisabled\n")
	}

	var localNode *models.NodeElement
	if sr.Cluster != nil {
		if sr.Cluster.CiliumHealth != nil {
			ch := sr.Cluster.CiliumHealth
			fmt.Fprintf(w, "Cilium health daemon:\t%s\t%s\n", ch.State, ch.Msg)
		}
		for _, node := range sr.Cluster.Nodes {
			if node.Name == sr.Cluster.Self {
				localNode = node
			} else {
				continue
			}
		}
	}

	if sr.IPAM != nil {
		var v4CIDR, v6CIDR string
		if localNode != nil {
			if nIPs := ip.CountIPsInCIDR(localNode.PrimaryAddress.IPV4.AllocRange); nIPs > 0 {
				v4CIDR = fmt.Sprintf("/%d", nIPs)
			}
			if nIPs := ip.CountIPsInCIDR(localNode.PrimaryAddress.IPV6.AllocRange); nIPs > 0 {
				v6CIDR = fmt.Sprintf("/%d", nIPs)
			}
		}
		fmt.Fprintf(w, "IPv4 address pool:\t%d%s allocated\n", len(sr.IPAM.IPV4), v4CIDR)
		if allAddresses {
			for _, ipv4 := range sr.IPAM.IPV4 {
				fmt.Fprintf(w, "  %s\n", ipv4)
			}
		}
		fmt.Fprintf(w, "IPv6 address pool:\t%d%s allocated\n", len(sr.IPAM.IPV6), v6CIDR)
		if allAddresses {
			for _, ipv6 := range sr.IPAM.IPV6 {
				fmt.Fprintf(w, "  %s\n", ipv6)
			}
		}
	}

	if sr.Controllers != nil {
		nFailing, out := 0, []string{"  Name\tLast success\tLast error\tCount\tMessage\n"}
		for _, ctrl := range sr.Controllers {
			status := ctrl.Status
			if status == nil {
				continue
			}

			if status.ConsecutiveFailureCount > 0 {
				nFailing++
			} else if !allControllers {
				continue
			}

			failSince := timeSince(time.Time(status.LastFailureTimestamp))
			successSince := timeSince(time.Time(status.LastSuccessTimestamp))

			err := "no error"
			if status.LastFailureMsg != "" {
				err = status.LastFailureMsg
			}

			out = append(out, fmt.Sprintf("  %s\t%s\t%s\t%d\t%s\t\n",
				ctrl.Name, successSince, failSince, status.ConsecutiveFailureCount, err))
		}

		nOK := len(sr.Controllers) - nFailing
		fmt.Fprintf(w, "Controller Status:\t%d/%d healthy\n", nOK, len(sr.Controllers))
		if len(out) > 1 {
			tab := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
			for _, s := range out {
				fmt.Fprint(tab, s)
			}
			tab.Flush()
		}

	}

	if sr.Proxy != nil {
		fmt.Fprintf(w, "Proxy Status:\tOK, ip %s, port-range %s\n",
			sr.Proxy.IP, sr.Proxy.PortRange)
	} else {
		fmt.Fprintf(w, "Proxy Status:\tNo managed proxy redirect\n")
	}
}
<commit_msg>Sorting controller output by name (alphabetical) in status command<commit_after>// Copyright 2016-2017 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package client

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strings"
	"text/tabwriter"
	"time"

	clientapi "github.com/cilium/cilium/api/v1/client"
	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/daemon/defaults"
	"github.com/cilium/cilium/pkg/ip"

	runtime_client "github.com/go-openapi/runtime/client"
	"github.com/go-openapi/strfmt"
)

type Client struct {
	clientapi.Cilium
}

func configureTransport(tr *http.Transport, proto, addr string) *http.Transport {
	if tr == nil {
		tr = &http.Transport{}
	}

	if proto == "unix" {
		// No need for compression in local communications.
		tr.DisableCompression = true
		tr.Dial = func(_, _ string) (net.Conn, error) {
			return net.Dial(proto, addr)
		}
	} else {
		tr.Proxy = http.ProxyFromEnvironment
		tr.Dial = (&net.Dialer{}).Dial
	}

	return tr
}

// NewDefaultClient creates a client with default parameters connecting to UNIX domain socket.
func NewDefaultClient() (*Client, error) {
	return NewClient("")
}

// NewClient creates a client for the given `host`.
func NewClient(host string) (*Client, error) {
	if host == "" {
		// Check if environment variable points to socket
		e := os.Getenv(defaults.SockPathEnv)
		if e == "" {
			// If unset, fall back to default value
			e = defaults.SockPath
		}
		host = "unix://" + e
	}
	tmp := strings.SplitN(host, "://", 2)
	if len(tmp) != 2 {
		return nil, fmt.Errorf("invalid host format '%s'", host)
	}

	switch tmp[0] {
	case "tcp":
		if _, err := url.Parse("tcp://" + tmp[1]); err != nil {
			return nil, err
		}
		host = "http://" + tmp[1]
	case "unix":
		host = tmp[1]
	}

	transport := configureTransport(nil, tmp[0], host)
	httpClient := &http.Client{Transport: transport}
	clientTrans := runtime_client.NewWithClient(tmp[1], clientapi.DefaultBasePath,
		clientapi.DefaultSchemes, httpClient)
	return &Client{*clientapi.New(clientTrans, strfmt.Default)}, nil
}

// Hint tries to improve the error message displayed to the user.
func Hint(err error) error {
	if err == nil {
		return err
	}
	e, _ := url.PathUnescape(err.Error())
	if strings.Contains(err.Error(), defaults.SockPath) {
		return fmt.Errorf("%s\nIs the agent running?", e)
	}
	return fmt.Errorf("%s", e)
}

func timeSince(since time.Time) string {
	out := "never"
	if !since.IsZero() {
		// Poor man's implementtion of time.Truncate(). Can be refined
		// when we rebase to go 1.9
		t := time.Since(since)
		t -= t % time.Second
		out = t.String() + " ago"
	}

	return out
}

func stateUnhealthy(state string) bool {
	return state == models.StatusStateWarning ||
		state == models.StatusStateFailure
}

func statusUnhealthy(s *models.Status) bool {
	if s != nil {
		return stateUnhealthy(s.State)
	}
	return false
}

// FormatStatusResponseBrief writes a one-line status to the writer. If
// everything ok, this is "ok", otherwise a message of the form "error in ..."
func FormatStatusResponseBrief(w io.Writer, sr *models.StatusResponse) {
	msg := ""

	switch {
	case statusUnhealthy(sr.Cilium):
		msg = fmt.Sprintf("cilium: %s", sr.Cilium.Msg)
	case statusUnhealthy(sr.ContainerRuntime):
		msg = fmt.Sprintf("container runtime: %s", sr.ContainerRuntime.Msg)
	case statusUnhealthy(sr.Kvstore):
		msg = fmt.Sprintf("kvstore: %s", sr.Kvstore.Msg)
	case sr.Kubernetes != nil && stateUnhealthy(sr.Kubernetes.State):
		msg = fmt.Sprintf("kubernetes: %s", sr.Kubernetes.Msg)
	case sr.Cluster != nil && statusUnhealthy(sr.Cluster.CiliumHealth):
		msg = fmt.Sprintf("cilium-health: %s", sr.Cluster.CiliumHealth.Msg)
	}

	// Only bother looking at controller failures if everything else is ok
	if msg == "" {
		for _, ctrl := range sr.Controllers {
			if ctrl.Status == nil {
				continue
			}
			if ctrl.Status.LastFailureMsg != "" {
				msg = fmt.Sprintf("controller %s: %s",
					ctrl.Name, ctrl.Status.LastFailureMsg)
				break
			}
		}
	}

	if msg == "" {
		fmt.Fprintf(w, "OK\n")
	} else {
		fmt.Fprintf(w, "error in %s\n", msg)
	}
}

// FormatStatusResponse writes a StatusResponse as a string to the writer.
//
// The parameters 'allAddresses', 'allControllers', 'allNodes', respectively,
// cause all details about that aspect of the status to be printed to the
// terminal. For each of these, if they are false then only a summary will be
// printed, with perhaps some detail if there are errors.
func FormatStatusResponse(w io.Writer, sr *models.StatusResponse, allAddresses, allControllers, allNodes, allRedirects bool) {
	if sr.Kvstore != nil {
		fmt.Fprintf(w, "KVStore:\t%s\t%s\n", sr.Kvstore.State, sr.Kvstore.Msg)
	}
	if sr.ContainerRuntime != nil {
		fmt.Fprintf(w, "ContainerRuntime:\t%s\t%s\n",
			sr.ContainerRuntime.State, sr.ContainerRuntime.Msg)
	}
	if sr.Kubernetes != nil {
		fmt.Fprintf(w, "Kubernetes:\t%s\t%s\n", sr.Kubernetes.State, sr.Kubernetes.Msg)
		if sr.Kubernetes.State != models.K8sStatusStateDisabled {
			fmt.Fprintf(w, "Kubernetes APIs:\t[\"%s\"]\n", strings.Join(sr.Kubernetes.K8sAPIVersions, "\", \""))
		}
	}
	if sr.Cilium != nil {
		fmt.Fprintf(w, "Cilium:\t%s\t%s\n", sr.Cilium.State, sr.Cilium.Msg)
	}

	if nm := sr.NodeMonitor; nm != nil {
		fmt.Fprintf(w, "NodeMonitor:\tListening for events on %d CPUs with %dx%d of shared memory\n",
			nm.Cpus, nm.Npages, nm.Pagesize)
		if nm.Lost != 0 || nm.Unknown != 0 {
			fmt.Fprintf(w, "\t%d events lost, %d unknown notifications\n", nm.Lost, nm.Unknown)
		}
	} else {
		fmt.Fprintf(w, "NodeMonitor:\tDisabled\n")
	}

	var localNode *models.NodeElement
	if sr.Cluster != nil {
		if sr.Cluster.CiliumHealth != nil {
			ch := sr.Cluster.CiliumHealth
			fmt.Fprintf(w, "Cilium health daemon:\t%s\t%s\n", ch.State, ch.Msg)
		}
		for _, node := range sr.Cluster.Nodes {
			if node.Name == sr.Cluster.Self {
				localNode = node
			} else {
				continue
			}
		}
	}

	if sr.IPAM != nil {
		var v4CIDR, v6CIDR string
		if localNode != nil {
			if nIPs := ip.CountIPsInCIDR(localNode.PrimaryAddress.IPV4.AllocRange); nIPs > 0 {
				v4CIDR = fmt.Sprintf("/%d", nIPs)
			}
			if nIPs := ip.CountIPsInCIDR(localNode.PrimaryAddress.IPV6.AllocRange); nIPs > 0 {
				v6CIDR = fmt.Sprintf("/%d", nIPs)
			}
		}
		fmt.Fprintf(w, "IPv4 address pool:\t%d%s allocated\n", len(sr.IPAM.IPV4), v4CIDR)
		if allAddresses {
			for _, ipv4 := range sr.IPAM.IPV4 {
				fmt.Fprintf(w, "  %s\n", ipv4)
			}
		}
		fmt.Fprintf(w, "IPv6 address pool:\t%d%s allocated\n", len(sr.IPAM.IPV6), v6CIDR)
		if allAddresses {
			for _, ipv6 := range sr.IPAM.IPV6 {
				fmt.Fprintf(w, "  %s\n", ipv6)
			}
		}
	}

	if sr.Controllers != nil {
		nFailing, out := 0, []string{"  Name\tLast success\tLast error\tCount\tMessage\n"}
		for _, ctrl := range sr.Controllers {
			status := ctrl.Status
			if status == nil {
				continue
			}

			if status.ConsecutiveFailureCount > 0 {
				nFailing++
			} else if !allControllers {
				continue
			}

			failSince := timeSince(time.Time(status.LastFailureTimestamp))
			successSince := timeSince(time.Time(status.LastSuccessTimestamp))

			err := "no error"
			if status.LastFailureMsg != "" {
				err = status.LastFailureMsg
			}

			out = append(out, fmt.Sprintf("  %s\t%s\t%s\t%d\t%s\t\n",
				ctrl.Name, successSince, failSince, status.ConsecutiveFailureCount, err))
		}

		nOK := len(sr.Controllers) - nFailing
		fmt.Fprintf(w, "Controller Status:\t%d/%d healthy\n", nOK, len(sr.Controllers))
		if len(out) > 1 {
			tab := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
			sort.Strings(out)
			for _, s := range out {
				fmt.Fprint(tab, s)
			}
			tab.Flush()
		}

	}

	if sr.Proxy != nil {
		fmt.Fprintf(w, "Proxy Status:\tOK, ip %s, port-range %s\n",
			sr.Proxy.IP, sr.Proxy.PortRange)
	} else {
		fmt.Fprintf(w, "Proxy Status:\tNo managed proxy redirect\n")
	}
}
<|endoftext|>


<commit_before>package client

import (
	"doozer/proto"
	"doozer/util"
	"log"
	"net"
	"os"
	"sync"
)

var ErrInvalidResponse = os.NewError("invalid response")

type Client struct {
	pr *proto.Conn
	lg *log.Logger
	lk sync.Mutex
}

func Dial(addr string) (*Client, os.Error) {
	c, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}
	pr := proto.NewConn(c)
	go pr.ReadResponses()
	return &Client{pr: pr, lg: util.NewLogger(addr)}, nil
}

// This is a little subtle. We want to follow redirects while still pipelining
// requests, and we want to allow as many requests as possible to succeed
// without retrying unnecessarily.
//
// In particular, reads never need to redirect, and writes must always go to
// the leader. So we want that read requests never retry, and write requests
// retry if and only if necessary. Here's how it works:
//
// In the proto.Conn, when we get a redirect response, we raise a flag noting
// the new address. This flag only goes up, never down. This flag effectively
// means the connection is deprecated. Any pending requests can go ahead, but
// new requests should use the new address.
//
// In the Client, when we notice that a redirect has occurred (i.e. the flag is
// set), we establish a new connection to the new address. Calls in the future
// will use the new connection. But we also allow the old connection to
// continue functioning as it was. Any writes on the old connection will retry,
// and then they are guaranteed to pick up the new connection. Any reads on the
// old connection will just succeed directly.
func (cl *Client) proto() (*proto.Conn, os.Error) {
	cl.lk.Lock()
	defer cl.lk.Unlock()

	if cl.pr.RedirectAddr != "" {
		conn, err := net.Dial("tcp", "", cl.pr.RedirectAddr)
		if err != nil {
			return nil, err
		}
		cl.lg = util.NewLogger(cl.pr.RedirectAddr)
		cl.pr = proto.NewConn(conn)
		go cl.pr.ReadResponses()
	}

	return cl.pr, nil
}

func (cl *Client) callWithoutRedirect(verb string, args, slot interface{}) os.Error {
	pr, err := cl.proto()
	if err != nil {
		return err
	}

	req, err := pr.SendRequest(verb, args)
	if err != nil {
		return err
	}

	return req.Get(slot)
}

func (cl *Client) call(verb string, data, slot interface{}) (err os.Error) {
	for err = os.EAGAIN; err == os.EAGAIN; {
		err = cl.callWithoutRedirect(verb, data, slot)
	}

	if err != nil {
		cl.lg.Println(err)
	}

	return err
}

func (cl *Client) Join(id, addr string) (seqn uint64, snapshot string, err os.Error) {
	var res proto.ResJoin
	err = cl.call("join", proto.ReqJoin{id, addr}, &res)
	if err != nil {
		return
	}

	return res.Seqn, res.Snapshot, nil
}

func (cl *Client) Set(path, body, oldCas string) (newCas string, err os.Error) {
	err = cl.call("SET", proto.ReqSet{path, body, oldCas}, &newCas)
	return
}

func (cl *Client) Del(path, cas string) os.Error {
	return cl.call("DEL", proto.ReqDel{path, cas}, nil)
}

func (cl *Client) Noop() os.Error {
	return cl.call("NOOP", nil, nil)
}

func (cl *Client) Checkin(id, cas string) (int64, string, os.Error) {
	var res proto.ResCheckin
	err := cl.call("checkin", proto.ReqCheckin{id, cas}, &res)
	if err != nil {
		return 0, "", err
	}

	return res.Exp, res.Cas, nil
}

func (cl *Client) Sett(path string, n int64, cas string) (int64, string, os.Error) {
	var res proto.ResSett
	err := cl.call("SETT", proto.ReqSett{path, n, cas}, &res)
	if err != nil {
		return 0, "", err
	}

	return res.Exp, res.Cas, nil
}
<commit_msg>client: fix nil pointer err in Noop<commit_after>package client

import (
	"doozer/proto"
	"doozer/util"
	"log"
	"net"
	"os"
	"sync"
)

var ErrInvalidResponse = os.NewError("invalid response")

type Client struct {
	pr *proto.Conn
	lg *log.Logger
	lk sync.Mutex
}

func Dial(addr string) (*Client, os.Error) {
	c, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}
	pr := proto.NewConn(c)
	go pr.ReadResponses()
	return &Client{pr: pr, lg: util.NewLogger(addr)}, nil
}

// This is a little subtle. We want to follow redirects while still pipelining
// requests, and we want to allow as many requests as possible to succeed
// without retrying unnecessarily.
//
// In particular, reads never need to redirect, and writes must always go to
// the leader. So we want that read requests never retry, and write requests
// retry if and only if necessary. Here's how it works:
//
// In the proto.Conn, when we get a redirect response, we raise a flag noting
// the new address. This flag only goes up, never down. This flag effectively
// means the connection is deprecated. Any pending requests can go ahead, but
// new requests should use the new address.
//
// In the Client, when we notice that a redirect has occurred (i.e. the flag is
// set), we establish a new connection to the new address. Calls in the future
// will use the new connection. But we also allow the old connection to
// continue functioning as it was. Any writes on the old connection will retry,
// and then they are guaranteed to pick up the new connection. Any reads on the
// old connection will just succeed directly.
func (cl *Client) proto() (*proto.Conn, os.Error) {
	cl.lk.Lock()
	defer cl.lk.Unlock()

	if cl.pr.RedirectAddr != "" {
		conn, err := net.Dial("tcp", "", cl.pr.RedirectAddr)
		if err != nil {
			return nil, err
		}
		cl.lg = util.NewLogger(cl.pr.RedirectAddr)
		cl.pr = proto.NewConn(conn)
		go cl.pr.ReadResponses()
	}

	return cl.pr, nil
}

func (cl *Client) callWithoutRedirect(verb string, args, slot interface{}) os.Error {
	pr, err := cl.proto()
	if err != nil {
		return err
	}

	req, err := pr.SendRequest(verb, args)
	if err != nil {
		return err
	}

	return req.Get(slot)
}

func (cl *Client) call(verb string, data, slot interface{}) (err os.Error) {
	for err = os.EAGAIN; err == os.EAGAIN; {
		err = cl.callWithoutRedirect(verb, data, slot)
	}

	if err != nil {
		cl.lg.Println(err)
	}

	return err
}

func (cl *Client) Join(id, addr string) (seqn uint64, snapshot string, err os.Error) {
	var res proto.ResJoin
	err = cl.call("join", proto.ReqJoin{id, addr}, &res)
	if err != nil {
		return
	}

	return res.Seqn, res.Snapshot, nil
}

func (cl *Client) Set(path, body, oldCas string) (newCas string, err os.Error) {
	err = cl.call("SET", proto.ReqSet{path, body, oldCas}, &newCas)
	return
}

func (cl *Client) Del(path, cas string) os.Error {
	return cl.call("DEL", proto.ReqDel{path, cas}, nil)
}

func (cl *Client) Noop() os.Error {
	var res string
	return cl.call("NOOP", nil, &res)
}

func (cl *Client) Checkin(id, cas string) (int64, string, os.Error) {
	var res proto.ResCheckin
	err := cl.call("checkin", proto.ReqCheckin{id, cas}, &res)
	if err != nil {
		return 0, "", err
	}

	return res.Exp, res.Cas, nil
}

func (cl *Client) Sett(path string, n int64, cas string) (int64, string, os.Error) {
	var res proto.ResSett
	err := cl.call("SETT", proto.ReqSett{path, n, cas}, &res)
	if err != nil {
		return 0, "", err
	}

	return res.Exp, res.Cas, nil
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: ISC
// Copyright (c) 2014-2020 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package reservoir

import (
	"time"

	"github.com/bitmark-inc/bitmarkd/asset"
	"github.com/bitmark-inc/bitmarkd/constants"
	"github.com/bitmark-inc/bitmarkd/messagebus"
	"github.com/bitmark-inc/bitmarkd/transactionrecord"
	"github.com/bitmark-inc/logger"
)

type rebroadcaster struct {
	log *logger.L
}

func (r *rebroadcaster) Run(args interface{}, shutdown <-chan struct{}) {

	r.log = logger.New("rebroadcaster")
	log := r.log

	log.Info("starting…")

loop:
	for {
		log.Debug("waiting…")
		select {
		case <-shutdown:
			log.Info("shutting down…")
			break loop
		case <-time.After(constants.RebroadcastInterval): // timeout
			r.process()
		}
	}

	log.Info("stopped")
}

// process all pending and verified transactions
func (r *rebroadcaster) process() {
	log := r.log
	globalData.RLock()

	log.Info("Start rebroadcasting local transactions…")

	// pending

	for _, item := range globalData.pendingTransactions {
		broadcastTransaction(item.tx)
	}
	for _, item := range globalData.pendingFreeIssues {
		broadcastFreeIssue(item)
	}
	for _, item := range globalData.pendingPaidIssues {
		broadcastPaidIssue(item)
	}

	// verified

	for _, item := range globalData.verifiedTransactions {
		broadcastTransaction(item)
	}
	for _, item := range globalData.verifiedFreeIssues {
		broadcastFreeIssue(item)
	}
	for _, item := range globalData.verifiedPaidIssues {
		broadcastPaidIssue(item)
	}

	globalData.RUnlock()
}

// send the transaction
func broadcastTransaction(item *transactionData) {
	messagebus.Bus.Broadcast.Send("transfer", item.packed)
}

// concatenate all transactions and send
func broadcastPaidIssue(item *issuePaymentData) {
	packedIssues := []byte{}
	for _, tx := range item.txs {
		packedIssues = append(packedIssues, tx.packed...)
	}
	messagebus.Bus.Broadcast.Send("issues", packedIssues)
}

// concatenate pending assets and issues, then send
// note there should not be any duplicate assets, i.e.
// 1. all issues are for the same asset
// 2. all issues are for different assets
func broadcastFreeIssue(item *issueFreeData) {

	packedAssets := []byte{}
	packedIssues := []byte{}

	for _, tx := range item.txs {
		assetId := tx.transaction.(*transactionrecord.BitmarkIssue).AssetId
		packedAsset := asset.Get(assetId)
		if nil != packedAsset {
			packedAssets = append(packedAssets, packedAsset...)
		}
		packedIssues = append(packedIssues, tx.packed...)
	}
	if len(packedAssets) > 0 {
		messagebus.Bus.Broadcast.Send("assets", packedAssets)
	}
	messagebus.Bus.Broadcast.Send("issues", packedIssues)

	// if the issue is a free issue, broadcast the proof
	if nil != item.difficulty {
		packed := make([]byte, len(item.payId), len(item.payId)+len(item.nonce))
		copy(packed, item.payId[:])
		packed = append(packed, item.nonce[:]...)
		messagebus.Bus.Broadcast.Send("proof", packed)
	}
}
<commit_msg>[reservoir] comment out pending rebroadcast<commit_after>// SPDX-License-Identifier: ISC
// Copyright (c) 2014-2020 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package reservoir

import (
	"time"

	"github.com/bitmark-inc/bitmarkd/asset"
	"github.com/bitmark-inc/bitmarkd/constants"
	"github.com/bitmark-inc/bitmarkd/messagebus"
	"github.com/bitmark-inc/bitmarkd/transactionrecord"
	"github.com/bitmark-inc/logger"
)

type rebroadcaster struct {
	log *logger.L
}

func (r *rebroadcaster) Run(args interface{}, shutdown <-chan struct{}) {

	r.log = logger.New("rebroadcaster")
	log := r.log

	log.Info("starting…")

loop:
	for {
		log.Debug("waiting…")
		select {
		case <-shutdown:
			log.Info("shutting down…")
			break loop
		case <-time.After(constants.RebroadcastInterval): // timeout
			r.process()
		}
	}

	log.Info("stopped")
}

// process transactions for rebroadcasting
func (r *rebroadcaster) process() {
	log := r.log
	globalData.RLock()

	log.Info("Start rebroadcasting local transactions…")

	//+ *** start: just comment out for further testing ***
	//
	// // pending
	//
	// for _, item := range globalData.pendingTransactions {
	// 	broadcastTransaction(item.tx)
	// }
	// for _, item := range globalData.pendingFreeIssues {
	// 	broadcastFreeIssue(item)
	// }
	// for _, item := range globalData.pendingPaidIssues {
	// 	broadcastPaidIssue(item)
	// }
	//- *** end ***

	// verified

	for _, item := range globalData.verifiedTransactions {
		broadcastTransaction(item)
	}
	for _, item := range globalData.verifiedFreeIssues {
		broadcastFreeIssue(item)
	}
	for _, item := range globalData.verifiedPaidIssues {
		broadcastPaidIssue(item)
	}

	globalData.RUnlock()
}

// send the transaction
func broadcastTransaction(item *transactionData) {
	messagebus.Bus.Broadcast.Send("transfer", item.packed)
}

// concatenate all transactions and send
func broadcastPaidIssue(item *issuePaymentData) {
	packedIssues := []byte{}
	for _, tx := range item.txs {
		packedIssues = append(packedIssues, tx.packed...)
	}
	messagebus.Bus.Broadcast.Send("issues", packedIssues)
}

// concatenate pending assets and issues, then send
// note there should not be any duplicate assets, i.e.
// 1. all issues are for the same asset
// 2. all issues are for different assets
func broadcastFreeIssue(item *issueFreeData) {

	packedAssets := []byte{}
	packedIssues := []byte{}

	for _, tx := range item.txs {
		assetId := tx.transaction.(*transactionrecord.BitmarkIssue).AssetId
		packedAsset := asset.Get(assetId)
		if nil != packedAsset {
			packedAssets = append(packedAssets, packedAsset...)
		}
		packedIssues = append(packedIssues, tx.packed...)
	}
	if len(packedAssets) > 0 {
		messagebus.Bus.Broadcast.Send("assets", packedAssets)
	}
	messagebus.Bus.Broadcast.Send("issues", packedIssues)

	// if the issue is a free issue, broadcast the proof
	if nil != item.difficulty {
		packed := make([]byte, len(item.payId), len(item.payId)+len(item.nonce))
		copy(packed, item.payId[:])
		packed = append(packed, item.nonce[:]...)
		messagebus.Bus.Broadcast.Send("proof", packed)
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Scaleway. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.md file.

package commands

import (
	"fmt"
	"os"
	"runtime"

	"github.com/scaleway/scaleway-cli/vendor/github.com/kardianos/osext"

	"github.com/scaleway/scaleway-cli/pkg/config"
	"github.com/scaleway/scaleway-cli/pkg/utils"
)

// InfoArgs are flags for the `RunInfo` function
type InfoArgs struct{}

// RunInfo is the handler for 'scw info'
func RunInfo(ctx CommandContext, args InfoArgs) error {
	// FIXME: fmt.Fprintf(ctx.Stdout, "Servers: %s\n", "quantity")
	// FIXME: fmt.Fprintf(ctx.Stdout, "Images: %s\n", "quantity")
	fmt.Fprintf(ctx.Stdout, "Debug mode (client):\t%v\n", ctx.Getenv("DEBUG") != "")

	fmt.Fprintf(ctx.Stdout, "Organization:\t\t%s\n", ctx.API.Organization)
	// FIXME: add partially-masked token
	fmt.Fprintf(ctx.Stdout, "API Endpoint:\t\t%s\n", ctx.Getenv("scaleway_api_endpoint"))
	configPath, _ := config.GetConfigFilePath()
	fmt.Fprintf(ctx.Stdout, "RC file:\t\t%s\n", configPath)
	fmt.Fprintf(ctx.Stdout, "User:\t\t\t%s\n", ctx.Getenv("USER"))
	fmt.Fprintf(ctx.Stdout, "CPUs:\t\t\t%d\n", runtime.NumCPU())
	hostname, _ := os.Hostname()
	fmt.Fprintf(ctx.Stdout, "Hostname:\t\t%s\n", hostname)
	cliPath, _ := osext.Executable()
	fmt.Fprintf(ctx.Stdout, "CLI Path:\t\t%s\n", cliPath)

	fmt.Fprintln(ctx.Stdout, "")
	fmt.Fprintf(ctx.Stdout, "Cache:\t\t\t%s\n", ctx.API.Cache.Path)
	fmt.Fprintf(ctx.Stdout, "  Servers:\t\t%d\n", ctx.API.Cache.GetNbServers())
	fmt.Fprintf(ctx.Stdout, "  Images:\t\t%d\n", ctx.API.Cache.GetNbImages())
	fmt.Fprintf(ctx.Stdout, "  Snapshots:\t\t%d\n", ctx.API.Cache.GetNbSnapshots())
	fmt.Fprintf(ctx.Stdout, "  Volumes:\t\t%d\n", ctx.API.Cache.GetNbVolumes())
	fmt.Fprintf(ctx.Stdout, "  Bootscripts:\t\t%d\n", ctx.API.Cache.GetNbBootscripts())

	user, err := ctx.API.GetUser()
	if err != nil {
		return fmt.Errorf("Unable to get your SSH Keys")
	}

	if len(user.SSHPublicKeys) == 0 {
		fmt.Fprintln(ctx.Stdout, "You have no ssh keys")
	} else {
		fmt.Fprintln(ctx.Stdout, "")
		fmt.Fprintln(ctx.Stdout, "SSH Keys:")
		for id, key := range user.SSHPublicKeys {
			fingerprint, err := utils.SSHGetFingerprint(key.Key)
			if err != nil {
				return err
			} else {
				fmt.Fprintf(ctx.Stdout, "  [%d] %s", id, fingerprint)
			}
		}
		fmt.Fprintf(ctx.Stdout, "\n")
	}

	dashboard, err := ctx.API.GetDashboard()
	if err != nil {
		return fmt.Errorf("Unable to get your dashboard")
	}
	fmt.Fprintln(ctx.Stdout, "Dashboard:")
	fmt.Fprintf(ctx.Stdout, "  Volumes:\t\t%d\n", dashboard.VolumesCount)
	fmt.Fprintf(ctx.Stdout, "  Running servers:\t%d\n", dashboard.RunningServersCount)
	fmt.Fprintf(ctx.Stdout, "  Images:\t\t%d\n", dashboard.ImagesCount)
	fmt.Fprintf(ctx.Stdout, "  Snapshots:\t\t%d\n", dashboard.SnapshotsCount)
	fmt.Fprintf(ctx.Stdout, "  Servers:\t\t%d\n", dashboard.ServersCount)
	fmt.Fprintf(ctx.Stdout, "  Ips:\t\t\t%d\n\n", dashboard.IPsCount)

	permissions, err := ctx.API.GetPermissions()
	if err != nil {
		return fmt.Errorf("Unable to get your permisssions")
	}
	fmt.Fprintln(ctx.Stdout, "Permissions:")
	for _, service := range permissions.Permissions {
		for key, serviceName := range service {
			fmt.Fprintf(ctx.Stdout, "  %s\n", key)
			for _, perm := range serviceName {
				fmt.Fprintf(ctx.Stdout, "    %s\n", perm)
			}
		}
	}
	return nil
}
<commit_msg>Added permissions `scw info`<commit_after>// Copyright (C) 2015 Scaleway. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.md file.

package commands

import (
	"fmt"
	"os"
	"runtime"

	"github.com/scaleway/scaleway-cli/vendor/github.com/kardianos/osext"

	"github.com/scaleway/scaleway-cli/pkg/config"
	"github.com/scaleway/scaleway-cli/pkg/utils"
)

// InfoArgs are flags for the `RunInfo` function
type InfoArgs struct{}

// RunInfo is the handler for 'scw info'
func RunInfo(ctx CommandContext, args InfoArgs) error {
	// FIXME: fmt.Fprintf(ctx.Stdout, "Servers: %s\n", "quantity")
	// FIXME: fmt.Fprintf(ctx.Stdout, "Images: %s\n", "quantity")
	fmt.Fprintf(ctx.Stdout, "Debug mode (client):\t%v\n", ctx.Getenv("DEBUG") != "")

	fmt.Fprintf(ctx.Stdout, "Organization:\t\t%s\n", ctx.API.Organization)
	// FIXME: add partially-masked token
	fmt.Fprintf(ctx.Stdout, "API Endpoint:\t\t%s\n", ctx.Getenv("scaleway_api_endpoint"))
	configPath, _ := config.GetConfigFilePath()
	fmt.Fprintf(ctx.Stdout, "RC file:\t\t%s\n", configPath)
	fmt.Fprintf(ctx.Stdout, "User:\t\t\t%s\n", ctx.Getenv("USER"))
	fmt.Fprintf(ctx.Stdout, "CPUs:\t\t\t%d\n", runtime.NumCPU())
	hostname, _ := os.Hostname()
	fmt.Fprintf(ctx.Stdout, "Hostname:\t\t%s\n", hostname)
	cliPath, _ := osext.Executable()
	fmt.Fprintf(ctx.Stdout, "CLI Path:\t\t%s\n", cliPath)

	fmt.Fprintln(ctx.Stdout, "")
	fmt.Fprintf(ctx.Stdout, "Cache:\t\t\t%s\n", ctx.API.Cache.Path)
	fmt.Fprintf(ctx.Stdout, "  Servers:\t\t%d\n", ctx.API.Cache.GetNbServers())
	fmt.Fprintf(ctx.Stdout, "  Images:\t\t%d\n", ctx.API.Cache.GetNbImages())
	fmt.Fprintf(ctx.Stdout, "  Snapshots:\t\t%d\n", ctx.API.Cache.GetNbSnapshots())
	fmt.Fprintf(ctx.Stdout, "  Volumes:\t\t%d\n", ctx.API.Cache.GetNbVolumes())
	fmt.Fprintf(ctx.Stdout, "  Bootscripts:\t\t%d\n", ctx.API.Cache.GetNbBootscripts())

	user, err := ctx.API.GetUser()
	if err != nil {
		return fmt.Errorf("Unable to get your SSH Keys")
	}

	if len(user.SSHPublicKeys) == 0 {
		fmt.Fprintln(ctx.Stdout, "You have no ssh keys")
	} else {
		fmt.Fprintln(ctx.Stdout, "")
		fmt.Fprintln(ctx.Stdout, "SSH Keys:")
		for id, key := range user.SSHPublicKeys {
			fingerprint, err := utils.SSHGetFingerprint(key.Key)
			if err != nil {
				return err
			} else {
				fmt.Fprintf(ctx.Stdout, "  [%d] %s", id, fingerprint)
			}
		}
		fmt.Fprintf(ctx.Stdout, "\n")
	}

	dashboard, err := ctx.API.GetDashboard()
	if err != nil {
		return fmt.Errorf("Unable to get your dashboard")
	}
	fmt.Fprintln(ctx.Stdout, "Dashboard:")
	fmt.Fprintf(ctx.Stdout, "  Volumes:\t\t%d\n", dashboard.VolumesCount)
	fmt.Fprintf(ctx.Stdout, "  Running servers:\t%d\n", dashboard.RunningServersCount)
	fmt.Fprintf(ctx.Stdout, "  Images:\t\t%d\n", dashboard.ImagesCount)
	fmt.Fprintf(ctx.Stdout, "  Snapshots:\t\t%d\n", dashboard.SnapshotsCount)
	fmt.Fprintf(ctx.Stdout, "  Servers:\t\t%d\n", dashboard.ServersCount)
	fmt.Fprintf(ctx.Stdout, "  Ips:\t\t\t%d\n", dashboard.IPsCount)

	fmt.Fprintf(ctx.Stdout, "\n")
	permissions, err := ctx.API.GetPermissions()
	if err != nil {
		return fmt.Errorf("Unable to get your permisssions")
	}
	fmt.Fprintln(ctx.Stdout, "Permissions:")
	for _, service := range permissions.Permissions {
		for key, serviceName := range service {
			fmt.Fprintf(ctx.Stdout, "  %s\n", key)
			for _, perm := range serviceName {
				fmt.Fprintf(ctx.Stdout, "    %s\n", perm)
			}
		}
	}
	return nil
}
<|endoftext|>