<commit_before>package cosmic

import (
	"fmt"
	"strings"

	"github.com/MissionCriticalCloud/go-cosmic/cosmic"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceCosmicDisk() *schema.Resource {
	return &schema.Resource{
		Create: resourceCosmicDiskCreate,
		Read:   resourceCosmicDiskRead,
		Update: resourceCosmicDiskUpdate,
		Delete: resourceCosmicDiskDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"disk_offering": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"attach": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"device_id": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"size": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"shrink_ok": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"disk_controller": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"virtual_machine_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceCosmicDiskCreate(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)
	d.Partial(true)

	name := d.Get("name").(string)

	// Create a new parameter struct
	p := cs.Volume.NewCreateVolumeParams()
	p.SetName(name)

	// Retrieve the disk_offering ID
	diskofferingid, e := retrieveID(cs, "disk_offering", d.Get("disk_offering").(string))
	if e != nil {
		return e.Error()
	}
	// Set the disk_offering ID
	p.SetDiskofferingid(diskofferingid)

	if d.Get("size").(int) != 0 {
		// Set the volume size
		p.SetSize(int64(d.Get("size").(int)))
	}

	// Set the disk_controller type if configured
	if diskcontroller := strings.ToUpper(d.Get("disk_controller").(string)); diskcontroller != "" {

		if diskcontroller == "IDE" || diskcontroller == "SCSI" || diskcontroller == "VIRTIO" {
			p.SetDiskcontroller(diskcontroller)
		}
	}

	// If there is a project supplied, we retrieve and set the project id
	if err := setProjectid(p, cs, d); err != nil {
		return err
	}

	// Retrieve the zone ID
	zoneid, e := retrieveID(cs, "zone", d.Get("zone").(string))
	if e != nil {
		return e.Error()
	}
	// Set the zone ID
	p.SetZoneid(zoneid)

	// Create the new volume
	r, err := cs.Volume.CreateVolume(p)
	if err != nil {
		return fmt.Errorf("Error creating the new disk %s: %s", name, err)
	}

	// Set the volume ID and partials
	d.SetId(r.Id)
	d.SetPartial("name")
	d.SetPartial("device_id")
	d.SetPartial("disk_offering")
	d.SetPartial("size")
	d.SetPartial("disk_controller")
	d.SetPartial("virtual_machine_id")
	d.SetPartial("project")
	d.SetPartial("zone")

	if d.Get("attach").(bool) {
		err := resourceCosmicDiskAttach(d, meta)
		if err != nil {
			return fmt.Errorf("Error attaching the new disk %s to virtual machine: %s", name, err)
		}

		// Set the additional partial
		d.SetPartial("attach")
	}

	d.Partial(false)
	return resourceCosmicDiskRead(d, meta)
}

func resourceCosmicDiskRead(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Get the volume details
	v, count, err := cs.Volume.GetVolumeByID(
		d.Id(),
		cosmic.WithProject(d.Get("project").(string)),
	)
	if err != nil {
		if count == 0 {
			d.SetId("")
			return nil
		}

		return err
	}

	d.Set("name", v.Name)
	d.Set("attach", v.Attached != "")           // If attached this contains a timestamp when attached
	d.Set("size", int(v.Size/(1024*1024*1024))) // Needed to get GB's again
	d.Set("disk_controller", v.Diskcontroller)

	setValueOrID(d, "disk_offering", v.Diskofferingname, v.Diskofferingid)
	setValueOrID(d, "project", v.Project, v.Projectid)
	setValueOrID(d, "zone", v.Zonename, v.Zoneid)

	if v.Attached != "" {
		d.Set("device_id", int(v.Deviceid))
		d.Set("virtual_machine_id", v.Virtualmachineid)
	}

	return nil
}

func resourceCosmicDiskUpdate(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)
	d.Partial(true)

	name := d.Get("name").(string)

	if d.HasChange("disk_offering") || d.HasChange("size") {
		// Create a new parameter struct
		p := cs.Volume.NewResizeVolumeParams(d.Id())

		// Retrieve the disk_offering ID
		diskofferingid, e := retrieveID(cs, "disk_offering", d.Get("disk_offering").(string))
		if e != nil {
			return e.Error()
		}

		// Set the disk_offering ID
		p.SetDiskofferingid(diskofferingid)

		if d.Get("size").(int) != 0 {
			// Set the size
			p.SetSize(int64(d.Get("size").(int)))
		}

		// Set the shrink bit
		p.SetShrinkok(d.Get("shrink_ok").(bool))

		// Change the disk_offering
		r, err := cs.Volume.ResizeVolume(p)
		if err != nil {
			return fmt.Errorf("Error changing disk offering/size for disk %s: %s", name, err)
		}

		// Update the volume ID and set partials
		d.SetId(r.Id)
		d.SetPartial("disk_offering")
		d.SetPartial("size")
	}

	// If the device ID changed, just detach here so we can re-attach the
	// volume at the end of this function
	if d.HasChange("device_id") || d.HasChange("virtual_machine") {
		// Detach the volume
		if err := resourceCosmicDiskDetach(d, meta); err != nil {
			return fmt.Errorf("Error detaching disk %s from virtual machine: %s", name, err)
		}
	}

	if d.Get("attach").(bool) {
		// Attach the volume
		err := resourceCosmicDiskAttach(d, meta)
		if err != nil {
			return fmt.Errorf("Error attaching disk %s to virtual machine: %s", name, err)
		}

		// Set the additional partials
		d.SetPartial("attach")
		d.SetPartial("device_id")
		d.SetPartial("virtual_machine_id")
	} else {
		// Detach the volume
		if err := resourceCosmicDiskDetach(d, meta); err != nil {
			return fmt.Errorf("Error detaching disk %s from virtual machine: %s", name, err)
		}
	}

	d.Partial(false)
	return resourceCosmicDiskRead(d, meta)
}

func resourceCosmicDiskDelete(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Detach the volume
	if err := resourceCosmicDiskDetach(d, meta); err != nil {
		return err
	}

	// Create a new parameter struct
	p := cs.Volume.NewDeleteVolumeParams(d.Id())

	// Delete the voluem
	if _, err := cs.Volume.DeleteVolume(p); err != nil {
		// This is a very poor way to be told the ID does no longer exist :(
		if strings.Contains(err.Error(), fmt.Sprintf(
			"Invalid parameter id value=%s due to incorrect long value format, "+
				"or entity does not exist", d.Id())) {
			return nil
		}

		return err
	}

	return nil
}

func resourceCosmicDiskAttach(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	if virtualmachineid, ok := d.GetOk("virtual_machine_id"); ok {
		// First check if the disk isn't already attached
		if attached, err := isAttached(d, meta); err != nil || attached {
			return err
		}

		// Create a new parameter struct
		p := cs.Volume.NewAttachVolumeParams(d.Id(), virtualmachineid.(string))

		if deviceid, ok := d.GetOk("device_id"); ok {
			p.SetDeviceid(int64(deviceid.(int)))
		}

		// Attach the new volume
		r, err := Retry(10, retryableAttachVolumeFunc(cs, p))
		if err != nil {
			return fmt.Errorf("Error attaching volume to VM: %s", err)
		}

		d.SetId(r.(*cosmic.AttachVolumeResponse).Id)
	}

	return nil
}

func resourceCosmicDiskDetach(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Check if the volume is actually attached, before detaching
	if attached, err := isAttached(d, meta); err != nil || !attached {
		return err
	}

	// Create a new parameter struct
	p := cs.Volume.NewDetachVolumeParams()

	// Set the volume ID
	p.SetId(d.Id())

	// Detach the currently attached volume
	_, err := cs.Volume.DetachVolume(p)
	if err != nil {
		if virtualmachineid, ok := d.GetOk("virtual_machine_id"); ok {
			// Create a new parameter struct
			pd := cs.VirtualMachine.NewStopVirtualMachineParams(virtualmachineid.(string))

			// Stop the virtual machine in order to be able to detach the disk
			if _, err := cs.VirtualMachine.StopVirtualMachine(pd); err != nil {
				return err
			}

			// Try again to detach the currently attached volume
			if _, err := cs.Volume.DetachVolume(p); err != nil {
				return err
			}

			// Create a new parameter struct
			pu := cs.VirtualMachine.NewStartVirtualMachineParams(virtualmachineid.(string))

			// Start the virtual machine again
			if _, err := cs.VirtualMachine.StartVirtualMachine(pu); err != nil {
				return err
			}
		}
	}

	return err
}

func isAttached(d *schema.ResourceData, meta interface{}) (bool, error) {
	cs := meta.(*cosmic.CosmicClient)

	// Get the volume details
	v, _, err := cs.Volume.GetVolumeByID(
		d.Id(),
		cosmic.WithProject(d.Get("project").(string)),
	)
	if err != nil {
		return false, err
	}

	return v.Attached != "", nil
}

func retryableAttachVolumeFunc(
	cs *cosmic.CosmicClient,
	p *cosmic.AttachVolumeParams) func() (interface{}, error) {
	return func() (interface{}, error) {
		r, err := cs.Volume.AttachVolume(p)
		if err != nil {
			return nil, err
		}
		return r, nil
	}
}
<commit_msg>Changes parameter checking for disk_controller<commit_after>package cosmic

import (
	"fmt"
	"strings"

	"github.com/MissionCriticalCloud/go-cosmic/cosmic"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceCosmicDisk() *schema.Resource {
	return &schema.Resource{
		Create: resourceCosmicDiskCreate,
		Read:   resourceCosmicDiskRead,
		Update: resourceCosmicDiskUpdate,
		Delete: resourceCosmicDiskDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"disk_offering": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"attach": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"device_id": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"size": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"shrink_ok": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"disk_controller": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
				ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) {
					v := val.(string)
					switch v {
					case "IDE", "SCSI", "VIRTIO":
					default:
						errs = append(errs, fmt.Errorf("%q must be either 'IDE', 'SCSI' or 'VIRTIO', got: %q", key, v))
					}

					return
				},
			},

			"virtual_machine_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceCosmicDiskCreate(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)
	d.Partial(true)

	name := d.Get("name").(string)

	// Create a new parameter struct
	p := cs.Volume.NewCreateVolumeParams()
	p.SetName(name)

	// Retrieve the disk_offering ID
	diskofferingid, e := retrieveID(cs, "disk_offering", d.Get("disk_offering").(string))
	if e != nil {
		return e.Error()
	}
	// Set the disk_offering ID
	p.SetDiskofferingid(diskofferingid)

	if d.Get("size").(int) != 0 {
		// Set the volume size
		p.SetSize(int64(d.Get("size").(int)))
	}

	// Set the disk_controller type if configured
	if diskcontroller, ok := d.GetOk("disk_controller"); ok {
		p.SetDiskcontroller(diskcontroller.(string))
	}

	// If there is a project supplied, we retrieve and set the project id
	if err := setProjectid(p, cs, d); err != nil {
		return err
	}

	// Retrieve the zone ID
	zoneid, e := retrieveID(cs, "zone", d.Get("zone").(string))
	if e != nil {
		return e.Error()
	}
	// Set the zone ID
	p.SetZoneid(zoneid)

	// Create the new volume
	r, err := cs.Volume.CreateVolume(p)
	if err != nil {
		return fmt.Errorf("Error creating the new disk %s: %s", name, err)
	}

	// Set the volume ID and partials
	d.SetId(r.Id)
	d.SetPartial("name")
	d.SetPartial("device_id")
	d.SetPartial("disk_offering")
	d.SetPartial("size")
	d.SetPartial("disk_controller")
	d.SetPartial("virtual_machine_id")
	d.SetPartial("project")
	d.SetPartial("zone")

	if d.Get("attach").(bool) {
		err := resourceCosmicDiskAttach(d, meta)
		if err != nil {
			return fmt.Errorf("Error attaching the new disk %s to virtual machine: %s", name, err)
		}

		// Set the additional partial
		d.SetPartial("attach")
	}

	d.Partial(false)
	return resourceCosmicDiskRead(d, meta)
}

func resourceCosmicDiskRead(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Get the volume details
	v, count, err := cs.Volume.GetVolumeByID(
		d.Id(),
		cosmic.WithProject(d.Get("project").(string)),
	)
	if err != nil {
		if count == 0 {
			d.SetId("")
			return nil
		}

		return err
	}

	d.Set("name", v.Name)
	d.Set("attach", v.Attached != "")           // If attached this contains a timestamp when attached
	d.Set("size", int(v.Size/(1024*1024*1024))) // Needed to get GB's again
	d.Set("disk_controller", v.Diskcontroller)

	setValueOrID(d, "disk_offering", v.Diskofferingname, v.Diskofferingid)
	setValueOrID(d, "project", v.Project, v.Projectid)
	setValueOrID(d, "zone", v.Zonename, v.Zoneid)

	if v.Attached != "" {
		d.Set("device_id", int(v.Deviceid))
		d.Set("virtual_machine_id", v.Virtualmachineid)
	}

	return nil
}

func resourceCosmicDiskUpdate(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)
	d.Partial(true)

	name := d.Get("name").(string)

	if d.HasChange("disk_offering") || d.HasChange("size") {
		// Create a new parameter struct
		p := cs.Volume.NewResizeVolumeParams(d.Id())

		// Retrieve the disk_offering ID
		diskofferingid, e := retrieveID(cs, "disk_offering", d.Get("disk_offering").(string))
		if e != nil {
			return e.Error()
		}

		// Set the disk_offering ID
		p.SetDiskofferingid(diskofferingid)

		if d.Get("size").(int) != 0 {
			// Set the size
			p.SetSize(int64(d.Get("size").(int)))
		}

		// Set the shrink bit
		p.SetShrinkok(d.Get("shrink_ok").(bool))

		// Change the disk_offering
		r, err := cs.Volume.ResizeVolume(p)
		if err != nil {
			return fmt.Errorf("Error changing disk offering/size for disk %s: %s", name, err)
		}

		// Update the volume ID and set partials
		d.SetId(r.Id)
		d.SetPartial("disk_offering")
		d.SetPartial("size")
	}

	// If the device ID changed, just detach here so we can re-attach the
	// volume at the end of this function
	if d.HasChange("device_id") || d.HasChange("virtual_machine") {
		// Detach the volume
		if err := resourceCosmicDiskDetach(d, meta); err != nil {
			return fmt.Errorf("Error detaching disk %s from virtual machine: %s", name, err)
		}
	}

	if d.Get("attach").(bool) {
		// Attach the volume
		err := resourceCosmicDiskAttach(d, meta)
		if err != nil {
			return fmt.Errorf("Error attaching disk %s to virtual machine: %s", name, err)
		}

		// Set the additional partials
		d.SetPartial("attach")
		d.SetPartial("device_id")
		d.SetPartial("virtual_machine_id")
	} else {
		// Detach the volume
		if err := resourceCosmicDiskDetach(d, meta); err != nil {
			return fmt.Errorf("Error detaching disk %s from virtual machine: %s", name, err)
		}
	}

	d.Partial(false)
	return resourceCosmicDiskRead(d, meta)
}

func resourceCosmicDiskDelete(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Detach the volume
	if err := resourceCosmicDiskDetach(d, meta); err != nil {
		return err
	}

	// Create a new parameter struct
	p := cs.Volume.NewDeleteVolumeParams(d.Id())

	// Delete the voluem
	if _, err := cs.Volume.DeleteVolume(p); err != nil {
		// This is a very poor way to be told the ID does no longer exist :(
		if strings.Contains(err.Error(), fmt.Sprintf(
			"Invalid parameter id value=%s due to incorrect long value format, "+
				"or entity does not exist", d.Id())) {
			return nil
		}

		return err
	}

	return nil
}

func resourceCosmicDiskAttach(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	if virtualmachineid, ok := d.GetOk("virtual_machine_id"); ok {
		// First check if the disk isn't already attached
		if attached, err := isAttached(d, meta); err != nil || attached {
			return err
		}

		// Create a new parameter struct
		p := cs.Volume.NewAttachVolumeParams(d.Id(), virtualmachineid.(string))

		if deviceid, ok := d.GetOk("device_id"); ok {
			p.SetDeviceid(int64(deviceid.(int)))
		}

		// Attach the new volume
		r, err := Retry(10, retryableAttachVolumeFunc(cs, p))
		if err != nil {
			return fmt.Errorf("Error attaching volume to VM: %s", err)
		}

		d.SetId(r.(*cosmic.AttachVolumeResponse).Id)
	}

	return nil
}

func resourceCosmicDiskDetach(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cosmic.CosmicClient)

	// Check if the volume is actually attached, before detaching
	if attached, err := isAttached(d, meta); err != nil || !attached {
		return err
	}

	// Create a new parameter struct
	p := cs.Volume.NewDetachVolumeParams()

	// Set the volume ID
	p.SetId(d.Id())

	// Detach the currently attached volume
	_, err := cs.Volume.DetachVolume(p)
	if err != nil {
		if virtualmachineid, ok := d.GetOk("virtual_machine_id"); ok {
			// Create a new parameter struct
			pd := cs.VirtualMachine.NewStopVirtualMachineParams(virtualmachineid.(string))

			// Stop the virtual machine in order to be able to detach the disk
			if _, err := cs.VirtualMachine.StopVirtualMachine(pd); err != nil {
				return err
			}

			// Try again to detach the currently attached volume
			if _, err := cs.Volume.DetachVolume(p); err != nil {
				return err
			}

			// Create a new parameter struct
			pu := cs.VirtualMachine.NewStartVirtualMachineParams(virtualmachineid.(string))

			// Start the virtual machine again
			if _, err := cs.VirtualMachine.StartVirtualMachine(pu); err != nil {
				return err
			}
		}
	}

	return err
}

func isAttached(d *schema.ResourceData, meta interface{}) (bool, error) {
	cs := meta.(*cosmic.CosmicClient)

	// Get the volume details
	v, _, err := cs.Volume.GetVolumeByID(
		d.Id(),
		cosmic.WithProject(d.Get("project").(string)),
	)
	if err != nil {
		return false, err
	}

	return v.Attached != "", nil
}

func retryableAttachVolumeFunc(
	cs *cosmic.CosmicClient,
	p *cosmic.AttachVolumeParams) func() (interface{}, error) {
	return func() (interface{}, error) {
		r, err := cs.Volume.AttachVolume(p)
		if err != nil {
			return nil, err
		}
		return r, nil
	}
}
<|endoftext|>


<commit_before>package communicator

import (
	"errors"
	"fmt"
	"os"
	"time"

	"github.com/mitchellh/packer/template/interpolate"
)

// Config is the common configuration that communicators allow within
// a builder.
type Config struct {
	Type string `mapstructure:"communicator"`

	// SSH
	SSHHost              string        `mapstructure:"ssh_host"`
	SSHPort              int           `mapstructure:"ssh_port"`
	SSHUsername          string        `mapstructure:"ssh_username"`
	SSHPassword          string        `mapstructure:"ssh_password"`
	SSHPrivateKey        string        `mapstructure:"ssh_private_key_file"`
	SSHPty               bool          `mapstructure:"ssh_pty"`
	SSHTimeout           time.Duration `mapstructure:"ssh_timeout"`
	SSHDisableAgent      bool          `mapstructure:"ssh_disable_agent"`
	SSHHandshakeAttempts int           `mapstructure:"ssh_handshake_attempts"`
	SSHBastionHost       string        `mapstructure:"ssh_bastion_host"`
	SSHBastionPort       int           `mapstructure:"ssh_bastion_port"`
	SSHBastionUsername   string        `mapstructure:"ssh_bastion_username"`
	SSHBastionPassword   string        `mapstructure:"ssh_bastion_password"`
	SSHBastionPrivateKey string        `mapstructure:"ssh_bastion_private_key_file"`

	// WinRM
	WinRMUser     string        `mapstructure:"winrm_username"`
	WinRMPassword string        `mapstructure:"winrm_password"`
	WinRMHost     string        `mapstructure:"winrm_host"`
	WinRMPort     int           `mapstructure:"winrm_port"`
	WinRMTimeout  time.Duration `mapstructure:"winrm_timeout"`
}

// Port returns the port that will be used for access based on config.
func (c *Config) Port() int {
	switch c.Type {
	case "ssh":
		return c.SSHPort
	case "winrm":
		return c.WinRMPort
	default:
		return 0
	}
}

func (c *Config) Prepare(ctx *interpolate.Context) []error {
	if c.Type == "" {
		c.Type = "ssh"
	}

	var errs []error
	switch c.Type {
	case "ssh":
		if es := c.prepareSSH(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "winrm":
		if es := c.prepareWinRM(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "none":
		break
	default:
		return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)}
	}

	return errs
}

func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
	if c.SSHPort == 0 {
		c.SSHPort = 22
	}

	if c.SSHTimeout == 0 {
		c.SSHTimeout = 5 * time.Minute
	}

	if c.SSHHandshakeAttempts == 0 {
		c.SSHHandshakeAttempts = 10
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPort == 0 {
			c.SSHBastionPort = 22
		}

		if c.SSHBastionPrivateKey == "" && c.SSHPrivateKey != "" {
			c.SSHBastionPrivateKey = c.SSHPrivateKey
		}
	}

	// Validation
	var errs []error
	if c.SSHUsername == "" {
		errs = append(errs, errors.New("An ssh_username must be specified"))
	}

	if c.SSHPrivateKey != "" {
		if _, err := os.Stat(c.SSHPrivateKey); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		} else if _, err := SSHFileSigner(c.SSHPrivateKey); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		}
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPassword == "" && c.SSHBastionPrivateKey == "" {
			errs = append(errs, errors.New(
				"ssh_bastion_password or ssh_bastion_private_key_file must be specified"))
		}
	}

	return errs
}

func (c *Config) prepareWinRM(ctx *interpolate.Context) []error {
	if c.WinRMPort == 0 {
		c.WinRMPort = 5985
	}

	if c.WinRMTimeout == 0 {
		c.WinRMTimeout = 30 * time.Minute
	}

	var errs []error
	if c.WinRMUser == "" {
		errs = append(errs, errors.New("winrm_username must be specified."))
	}

	return errs
}
<commit_msg>helper/communicator: allow docker custom communicator<commit_after>package communicator

import (
	"errors"
	"fmt"
	"os"
	"time"

	"github.com/mitchellh/packer/template/interpolate"
)

// Config is the common configuration that communicators allow within
// a builder.
type Config struct {
	Type string `mapstructure:"communicator"`

	// SSH
	SSHHost              string        `mapstructure:"ssh_host"`
	SSHPort              int           `mapstructure:"ssh_port"`
	SSHUsername          string        `mapstructure:"ssh_username"`
	SSHPassword          string        `mapstructure:"ssh_password"`
	SSHPrivateKey        string        `mapstructure:"ssh_private_key_file"`
	SSHPty               bool          `mapstructure:"ssh_pty"`
	SSHTimeout           time.Duration `mapstructure:"ssh_timeout"`
	SSHDisableAgent      bool          `mapstructure:"ssh_disable_agent"`
	SSHHandshakeAttempts int           `mapstructure:"ssh_handshake_attempts"`
	SSHBastionHost       string        `mapstructure:"ssh_bastion_host"`
	SSHBastionPort       int           `mapstructure:"ssh_bastion_port"`
	SSHBastionUsername   string        `mapstructure:"ssh_bastion_username"`
	SSHBastionPassword   string        `mapstructure:"ssh_bastion_password"`
	SSHBastionPrivateKey string        `mapstructure:"ssh_bastion_private_key_file"`

	// WinRM
	WinRMUser     string        `mapstructure:"winrm_username"`
	WinRMPassword string        `mapstructure:"winrm_password"`
	WinRMHost     string        `mapstructure:"winrm_host"`
	WinRMPort     int           `mapstructure:"winrm_port"`
	WinRMTimeout  time.Duration `mapstructure:"winrm_timeout"`
}

// Port returns the port that will be used for access based on config.
func (c *Config) Port() int {
	switch c.Type {
	case "ssh":
		return c.SSHPort
	case "winrm":
		return c.WinRMPort
	default:
		return 0
	}
}

func (c *Config) Prepare(ctx *interpolate.Context) []error {
	if c.Type == "" {
		c.Type = "ssh"
	}

	var errs []error
	switch c.Type {
	case "ssh":
		if es := c.prepareSSH(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "winrm":
		if es := c.prepareWinRM(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "docker", "none":
		break
	default:
		return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)}
	}

	return errs
}

func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
	if c.SSHPort == 0 {
		c.SSHPort = 22
	}

	if c.SSHTimeout == 0 {
		c.SSHTimeout = 5 * time.Minute
	}

	if c.SSHHandshakeAttempts == 0 {
		c.SSHHandshakeAttempts = 10
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPort == 0 {
			c.SSHBastionPort = 22
		}

		if c.SSHBastionPrivateKey == "" && c.SSHPrivateKey != "" {
			c.SSHBastionPrivateKey = c.SSHPrivateKey
		}
	}

	// Validation
	var errs []error
	if c.SSHUsername == "" {
		errs = append(errs, errors.New("An ssh_username must be specified"))
	}

	if c.SSHPrivateKey != "" {
		if _, err := os.Stat(c.SSHPrivateKey); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		} else if _, err := SSHFileSigner(c.SSHPrivateKey); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		}
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPassword == "" && c.SSHBastionPrivateKey == "" {
			errs = append(errs, errors.New(
				"ssh_bastion_password or ssh_bastion_private_key_file must be specified"))
		}
	}

	return errs
}

func (c *Config) prepareWinRM(ctx *interpolate.Context) []error {
	if c.WinRMPort == 0 {
		c.WinRMPort = 5985
	}

	if c.WinRMTimeout == 0 {
		c.WinRMTimeout = 30 * time.Minute
	}

	var errs []error
	if c.WinRMUser == "" {
		errs = append(errs, errors.New("winrm_username must be specified."))
	}

	return errs
}
<|endoftext|>


<commit_before>package resource

import (
	"fmt"

	"github.com/hashicorp/terraform/addrs"
	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/config/hcl2shim"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/hashicorp/terraform/states"
	"github.com/hashicorp/terraform/terraform"
)

// shimState takes a new *states.State and reverts it to a legacy state for the provider ACC tests
func shimNewState(newState *states.State, providers map[string]terraform.ResourceProvider) (*terraform.State, error) {
	state := terraform.NewState()

	// in the odd case of a nil state, let the helper packages handle it
	if newState == nil {
		return nil, nil
	}

	for _, newMod := range newState.Modules {
		mod := state.AddModule(newMod.Addr)

		for name, out := range newMod.OutputValues {
			outputType := ""
			val := hcl2shim.ConfigValueFromHCL2(out.Value)
			ty := out.Value.Type()
			switch {
			case ty == cty.String:
				outputType = "string"
			case ty.IsTupleType() || ty.IsListType():
				outputType = "list"
			case ty.IsMapType():
				outputType = "map"
			}

			mod.Outputs[name] = &terraform.OutputState{
				Type:      outputType,
				Value:     val,
				Sensitive: out.Sensitive,
			}
		}

		for _, res := range newMod.Resources {
			resType := res.Addr.Type
			providerType := res.ProviderConfig.ProviderConfig.Type

			resource := getResource(providers, providerType, resType)

			for key, i := range res.Instances {
				flatmap, err := shimmedAttributes(i.Current, resource)
				if err != nil {
					return nil, fmt.Errorf("error decoding state for %q: %s", resType, err)
				}

				resState := &terraform.ResourceState{
					Type: resType,
					Primary: &terraform.InstanceState{
						ID:         flatmap["id"],
						Attributes: flatmap,
						Tainted:    i.Current.Status == states.ObjectTainted,
					},
				}
				if i.Current.SchemaVersion != 0 {
					resState.Primary.Meta = map[string]interface{}{
						"schema_version": i.Current.SchemaVersion,
					}
				}

				for _, dep := range i.Current.Dependencies {
					resState.Dependencies = append(resState.Dependencies, dep.String())
				}

				// convert the indexes to the old style flapmap indexes
				idx := ""
				switch key.(type) {
				case addrs.IntKey:
					// don't add numeric index values to resources with a count of 0
					if len(res.Instances) > 1 {
						idx = fmt.Sprintf(".%d", key)
					}
				case addrs.StringKey:
					idx = "." + key.String()
				}

				mod.Resources[res.Addr.String()+idx] = resState

				// add any deposed instances
				for _, dep := range i.Deposed {
					flatmap, err := shimmedAttributes(dep, resource)
					if err != nil {
						return nil, fmt.Errorf("error decoding deposed state for %q: %s", resType, err)
					}

					deposed := &terraform.InstanceState{
						ID:         flatmap["id"],
						Attributes: flatmap,
						Tainted:    dep.Status == states.ObjectTainted,
					}
					if dep.SchemaVersion != 0 {
						deposed.Meta = map[string]interface{}{
							"schema_version": dep.SchemaVersion,
						}
					}

					resState.Deposed = append(resState.Deposed, deposed)
				}
			}
		}
	}

	return state, nil
}

func getResource(providers map[string]terraform.ResourceProvider, providerName, resourceType string) *schema.Resource {
	p := providers[providerName]
	if p == nil {
		panic(fmt.Sprintf("provider %q not found in test step", providerName))
	}

	// this is only for tests, so should only see schema.Providers
	provider := p.(*schema.Provider)

	resource := provider.ResourcesMap[resourceType]
	if resource != nil {
		return resource

	}

	resource = provider.DataSourcesMap[resourceType]
	if resource != nil {
		return resource
	}

	panic(fmt.Sprintf("resource %s not found in test step", resourceType))
}

func shimmedAttributes(instance *states.ResourceInstanceObjectSrc, res *schema.Resource) (map[string]string, error) {
	flatmap := instance.AttrsFlat

	if flatmap != nil {
		return flatmap, nil
	}

	// if we have json attrs, they need to be decoded
	rio, err := instance.Decode(res.CoreConfigSchema().ImpliedType())
	if err != nil {
		return nil, err
	}

	instanceState, err := res.ShimInstanceStateFromValue(rio.Value)
	if err != nil {
		return nil, err
	}

	return instanceState.Attributes, nil
}
<commit_msg>type names don't imply the resource mode<commit_after>package resource

import (
	"fmt"

	"github.com/hashicorp/terraform/addrs"
	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/config/hcl2shim"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/hashicorp/terraform/states"
	"github.com/hashicorp/terraform/terraform"
)

// shimState takes a new *states.State and reverts it to a legacy state for the provider ACC tests
func shimNewState(newState *states.State, providers map[string]terraform.ResourceProvider) (*terraform.State, error) {
	state := terraform.NewState()

	// in the odd case of a nil state, let the helper packages handle it
	if newState == nil {
		return nil, nil
	}

	for _, newMod := range newState.Modules {
		mod := state.AddModule(newMod.Addr)

		for name, out := range newMod.OutputValues {
			outputType := ""
			val := hcl2shim.ConfigValueFromHCL2(out.Value)
			ty := out.Value.Type()
			switch {
			case ty == cty.String:
				outputType = "string"
			case ty.IsTupleType() || ty.IsListType():
				outputType = "list"
			case ty.IsMapType():
				outputType = "map"
			}

			mod.Outputs[name] = &terraform.OutputState{
				Type:      outputType,
				Value:     val,
				Sensitive: out.Sensitive,
			}
		}

		for _, res := range newMod.Resources {
			resType := res.Addr.Type
			providerType := res.ProviderConfig.ProviderConfig.Type

			resource := getResource(providers, providerType, res.Addr)

			for key, i := range res.Instances {
				flatmap, err := shimmedAttributes(i.Current, resource)
				if err != nil {
					return nil, fmt.Errorf("error decoding state for %q: %s", resType, err)
				}

				resState := &terraform.ResourceState{
					Type: resType,
					Primary: &terraform.InstanceState{
						ID:         flatmap["id"],
						Attributes: flatmap,
						Tainted:    i.Current.Status == states.ObjectTainted,
					},
				}
				if i.Current.SchemaVersion != 0 {
					resState.Primary.Meta = map[string]interface{}{
						"schema_version": i.Current.SchemaVersion,
					}
				}

				for _, dep := range i.Current.Dependencies {
					resState.Dependencies = append(resState.Dependencies, dep.String())
				}

				// convert the indexes to the old style flapmap indexes
				idx := ""
				switch key.(type) {
				case addrs.IntKey:
					// don't add numeric index values to resources with a count of 0
					if len(res.Instances) > 1 {
						idx = fmt.Sprintf(".%d", key)
					}
				case addrs.StringKey:
					idx = "." + key.String()
				}

				mod.Resources[res.Addr.String()+idx] = resState

				// add any deposed instances
				for _, dep := range i.Deposed {
					flatmap, err := shimmedAttributes(dep, resource)
					if err != nil {
						return nil, fmt.Errorf("error decoding deposed state for %q: %s", resType, err)
					}

					deposed := &terraform.InstanceState{
						ID:         flatmap["id"],
						Attributes: flatmap,
						Tainted:    dep.Status == states.ObjectTainted,
					}
					if dep.SchemaVersion != 0 {
						deposed.Meta = map[string]interface{}{
							"schema_version": dep.SchemaVersion,
						}
					}

					resState.Deposed = append(resState.Deposed, deposed)
				}
			}
		}
	}

	return state, nil
}

func getResource(providers map[string]terraform.ResourceProvider, providerName string, addr addrs.Resource) *schema.Resource {
	p := providers[providerName]
	if p == nil {
		panic(fmt.Sprintf("provider %q not found in test step", providerName))
	}

	// this is only for tests, so should only see schema.Providers
	provider := p.(*schema.Provider)

	switch addr.Mode {
	case addrs.ManagedResourceMode:
		resource := provider.ResourcesMap[addr.Type]
		if resource != nil {
			return resource
		}
	case addrs.DataResourceMode:
		resource := provider.DataSourcesMap[addr.Type]
		if resource != nil {
			return resource
		}
	}

	panic(fmt.Sprintf("resource %s not found in test step", addr.Type))
}

func shimmedAttributes(instance *states.ResourceInstanceObjectSrc, res *schema.Resource) (map[string]string, error) {
	flatmap := instance.AttrsFlat
	if flatmap != nil {
		return flatmap, nil
	}

	// if we have json attrs, they need to be decoded
	rio, err := instance.Decode(res.CoreConfigSchema().ImpliedType())
	if err != nil {
		return nil, err
	}

	instanceState, err := res.ShimInstanceStateFromValue(rio.Value)
	if err != nil {
		return nil, err
	}

	return instanceState.Attributes, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
)

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "usage: %s [options] [file...]\n", filepath.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

// Dockerfile の実行
func runDockerfile(path string) error {
	var file *os.File
	var err error

	if len(path) == 0 {
		file = os.Stdin
	} else {
		file, err = os.Open(path)
		if err != nil {
			// エラー処理をする
			return err
		}
		defer file.Close()
	}

	scanner := bufio.NewScanner(file)

	// 正規表現のコンパイル
	re := regexp.MustCompile("(?i)^ *(ONBUILD +)?([A-Z]+) +([^#]+)")
	lineno := 0

	for scanner.Scan() {
		line := scanner.Text()
		lineno += 1
		match := re.FindStringSubmatch(line)
		if match != nil {
			//onbuild := match[1]
			instruction := match[2]
			args := match[3]

			switch instruction {
			case "FROM":
				// 何もしない
			case "MAINTAINER":
				// 何もしない
			case "RUN":
				// スクリプトを実行
				cmd := exec.Command("/bin/sh", "-c", args)
				out, err := cmd.Output()
				if err != nil {
					fmt.Fprintf(os.Stderr, "%s:%d: %s : %s\n", path, lineno, err, args)
					return err
				}
				fmt.Printf("%s", out)
			case "CMD":
			case "EXPOSE":
				// iptables があれば書換える
			case "ENV":
				// 環境変数を設定
			case "ADD":
				// ファイルを追加
			case "ENTRYPOINT":
			case "VOLUME":
				// 何もしない
			case "USER":
				// ユーザを設定
			case "WORKDIR":
				// 作業ディレクトリを変更
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}

	return err
}

func main() {
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help {
		usage()
	}

	if len(flag.Args()) == 0 {
		runDockerfile("Dockerfile")
	} else {
		for _, v := range flag.Args() {
			runDockerfile(v)
		}
	}
}
<commit_msg>WORKDIR に対応<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
)

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "usage: %s [options] [file...]\n", filepath.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

// Dockerfile の実行
func runDockerfile(path string) error {
	var file *os.File
	var err error

	if len(path) == 0 {
		file = os.Stdin
	} else {
		file, err = os.Open(path)
		if err != nil {
			// エラー処理をする
			return err
		}
		defer file.Close()
	}

	scanner := bufio.NewScanner(file)

	// 正規表現のコンパイル
	re := regexp.MustCompile("(?i)^ *(ONBUILD +)?([A-Z]+) +([^#]+)")
	var workdir string
	lineno := 0

	for scanner.Scan() {
		line := scanner.Text()
		lineno += 1
		match := re.FindStringSubmatch(line)
		if match != nil {
			//onbuild := match[1]
			instruction := match[2]
			args := match[3]

			switch instruction {
			case "FROM":
				// 何もしない
			case "MAINTAINER":
				// 何もしない
			case "RUN":
				// スクリプトを実行
				cmd := exec.Command("/bin/sh", "-c", args)
				cmd.Dir = workdir
				out, err := cmd.Output()
				if err != nil {
					fmt.Fprintf(os.Stderr, "%s:%d: %s : %s\n", path, lineno, err, args)
					return err
				}
				fmt.Printf("%s", out)
			case "CMD":
			case "EXPOSE":
				// iptables があれば書換える
			case "ENV":
				// 環境変数を設定
			case "ADD":
				// ファイルを追加
			case "ENTRYPOINT":
			case "VOLUME":
				// 何もしない
			case "USER":
				// ユーザを設定
			case "WORKDIR":
				// 作業ディレクトリを変更
				workdir = args
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}

	return err
}

func main() {
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help {
		usage()
	}

	if len(flag.Args()) == 0 {
		runDockerfile("Dockerfile")
	} else {
		for _, v := range flag.Args() {
			runDockerfile(v)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>bugfixes<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcchain

import (
	"fmt"
	"github.com/conformal/btcscript"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
)

// CheckpointConfirmations is the number of blocks before the end of the current
// best block chain that a good checkpoint candidate must be.
const CheckpointConfirmations = 2016

// Checkpoint identifies a known good point in the block chain.  Using
// checkpoints allows a few optimizations for old blocks during initial download
// and also prevents forks from old blocks.
//
// Each checkpoint is selected by the core developers based upon several
// factors.  See the documentation for IsCheckpointCandidate for details
// on the selection criteria.
//
// As alluded to above, this package provides an IsCheckpointCandidate function
// which programatically identifies a block as a checkpoint candidate.  The idea
// is that candidates are reviewed by a developer to make the final decision and
// then manually added to the list of checkpoints.
type Checkpoint struct {
	Height int64
	Hash   *btcwire.ShaHash
}

// checkpointData groups checkpoints and other pertinent checkpoint data into
// a single type.
type checkpointData struct {
	// Checkpoints ordered from oldest to newest.
	checkpoints []Checkpoint

	// A map that will be automatically generated with the heights from
	// the checkpoints as keys.
	checkpointsByHeight map[int64]*Checkpoint
}

// checkpointDataMainNet contains checkpoint data for the main network.
var checkpointDataMainNet = checkpointData{
	checkpoints: []Checkpoint{
		{11111, newShaHashFromStr("0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")},
		{33333, newShaHashFromStr("000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")},
		{74000, newShaHashFromStr("0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")},
		{105000, newShaHashFromStr("00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")},
		{134444, newShaHashFromStr("00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")},
		{168000, newShaHashFromStr("000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")},
		{193000, newShaHashFromStr("000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")},
		{210000, newShaHashFromStr("000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")},
		{216116, newShaHashFromStr("00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")},
		{225430, newShaHashFromStr("00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")},
		{250000, newShaHashFromStr("000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")},
		{267300, newShaHashFromStr("000000000000000a83fbd660e918f218bf37edd92b748ad940483c7c116179ac")},
	},
	checkpointsByHeight: nil, // Automatically generated in init.
}

// checkpointDataTestNet3 contains checkpoint data for the test network (version
// 3).
var checkpointDataTestNet3 = checkpointData{
	checkpoints: []Checkpoint{
		{546, newShaHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")},
	},
	checkpointsByHeight: nil, // Automatically generated in init.
}

// newShaHashFromStr converts the passed big-endian hex string into a
// btcwire.ShaHash.  It only differs from the one available in btcwire in that
// it ignores the error since it will only (and must only) be called with
// hard-coded, and therefore known good, hashes.
func newShaHashFromStr(hexStr string) *btcwire.ShaHash {
	sha, _ := btcwire.NewShaHashFromStr(hexStr)
	return sha
}

// DisableCheckpoints provides a mechanism to disable validation against
// checkpoints which you DO NOT want to do in production.  It is provided only
// for debug purposes.
func (b *BlockChain) DisableCheckpoints(disable bool) {
	b.noCheckpoints = disable
}

// checkpointData returns the appropriate checkpoint data set depending on the
// network configured for the block chain.
func (b *BlockChain) checkpointData() *checkpointData {
	switch b.btcnet {
	case btcwire.TestNet3:
		return &checkpointDataTestNet3
	case btcwire.MainNet:
		return &checkpointDataMainNet
	}
	return nil
}

// LatestCheckpoint returns the most recent checkpoint (regardless of whether it
// is already known).  When checkpoints are disabled or there are no checkpoints
// for the active network, it will return nil.
func (b *BlockChain) LatestCheckpoint() *Checkpoint {
	if b.noCheckpoints || b.checkpointData() == nil {
		return nil
	}

	checkpoints := b.checkpointData().checkpoints
	return &checkpoints[len(checkpoints)-1]
}

// verifyCheckpoint returns whether the passed block height and hash combination
// match the hard-coded checkpoint data.  It also returns true if there is no
// checkpoint data for the passed block height.
func (b *BlockChain) verifyCheckpoint(height int64, hash *btcwire.ShaHash) bool {
	if b.noCheckpoints || b.checkpointData() == nil {
		return true
	}

	// Nothing to check if there is no checkpoint data for the block height.
	checkpoint, exists := b.checkpointData().checkpointsByHeight[height]
	if !exists {
		return true
	}

	if !checkpoint.Hash.IsEqual(hash) {
		return false
	}

	log.Infof("Verfied checkpoint at height %d/block %s", checkpoint.Height,
		checkpoint.Hash)
	return true
}

// findLatestKnownCheckpoint finds the most recent checkpoint that is already
// available in the downloaded portion of the block chain and returns the
// associated block.  It returns nil if a checkpoint can't be found (this should
// really only happen for blocks before the first checkpoint).
func (b *BlockChain) findLatestKnownCheckpoint() (*btcutil.Block, error) {
	if b.noCheckpoints || b.checkpointData() == nil {
		return nil, nil
	}

	// No checkpoints.
	checkpoints := b.checkpointData().checkpoints
	numCheckpoints := len(checkpoints)
	if numCheckpoints == 0 {
		return nil, nil
	}

	// Perform the initial search to find and cache the latest known
	// checkpoint if the best chain is not known yet or we haven't already
	// previously searched.
	if b.bestChain == nil || (b.checkpointBlock == nil && b.nextCheckpoint == nil) {
		// Loop backwards through the available checkpoints to find one
		// that we already have.
		checkpointIndex := -1
		for i := numCheckpoints - 1; i >= 0; i-- {
			if b.db.ExistsSha(checkpoints[i].Hash) {
				checkpointIndex = i
				break
			}
		}

		// No known latest checkpoint.  This will only happen on blocks
		// before the first known checkpoint.  So, set the next expected
		// checkpoint to the first checkpoint and return the fact there
		// is no latest known checkpoint block.
		if checkpointIndex == -1 {
			b.nextCheckpoint = &checkpoints[0]
			return nil, nil
		}

		// Cache the latest known checkpoint block for future lookups.
		checkpoint := checkpoints[checkpointIndex]
		block, err := b.db.FetchBlockBySha(checkpoint.Hash)
		if err != nil {
			return nil, err
		}
		b.checkpointBlock = block

		// Set the next expected checkpoint block accordingly.
		b.nextCheckpoint = nil
		if checkpointIndex < numCheckpoints-1 {
			b.nextCheckpoint = &checkpoints[checkpointIndex+1]
		}

		return block, nil
	}

	// At this point we've already searched for the latest known checkpoint,
	// so when there is no next checkpoint, the current checkpoint lockin
	// will always be the latest known checkpoint.
	if b.nextCheckpoint == nil {
		return b.checkpointBlock, nil
	}

	// When there is a next checkpoint and the height of the current best
	// chain does not exceed it, the current checkpoint lockin is still
	// the latest known checkpoint.
	if b.bestChain.height < b.nextCheckpoint.Height {
		return b.checkpointBlock, nil
	}

	// We've reached or exceeded the next checkpoint height.  Note that
	// once a checkpoint lockin has been reached, forks are prevented from
	// any blocks before the checkpoint, so we don't have to worry about the
	// checkpoint going away out from under us due to a chain reorganize.

	// Cache the latest known checkpoint block for future lookups.  Note
	// that if this lookup fails something is very wrong since the chain
	// has already passed the checkpoint which was verified as accurate
	// before inserting it.
	block, err := b.db.FetchBlockBySha(b.nextCheckpoint.Hash)
	if err != nil {
		return nil, err
	}
	b.checkpointBlock = block

	// Set the next expected checkpoint.
	checkpointIndex := -1
	for i := numCheckpoints - 1; i >= 0; i-- {
		if checkpoints[i].Hash.IsEqual(b.nextCheckpoint.Hash) {
			checkpointIndex = i
			break
		}
	}
	b.nextCheckpoint = nil
	if checkpointIndex != -1 && checkpointIndex < numCheckpoints-1 {
		b.nextCheckpoint = &checkpoints[checkpointIndex+1]
	}

	return b.checkpointBlock, nil
}

// isNonstandardTransaction determines whether a transaction contains any
// scripts which are not one of the standard types.
func isNonstandardTransaction(tx *btcutil.Tx) bool {
	// TODO(davec): Should there be checks for the input signature scripts?

	// Check all of the output public key scripts for non-standard scripts.
	for _, txOut := range tx.MsgTx().TxOut {
		scriptClass := btcscript.GetScriptClass(txOut.PkScript)
		if scriptClass == btcscript.NonStandardTy {
			return true
		}
	}
	return false
}

// IsCheckpointCandidate returns whether or not the passed block is a good
// checkpoint candidate.
//
// The factors used to determine a good checkpoint are:
//  - The block must be in the main chain
//  - The block must be at least 'CheckpointConfirmations' blocks prior to the
//    current end of the main chain
//  - The timestamps for the blocks before and after the checkpoint must have
//    timestamps which are also before and after the checkpoint, respectively
//    (due to the median time allowance this is not always the case)
//  - The block must not contain any strange transaction such as those with
//    nonstandard scripts
func (b *BlockChain) IsCheckpointCandidate(block *btcutil.Block) (bool, error) {
	// Checkpoints must be enabled.
	if b.noCheckpoints {
		return false, fmt.Errorf("checkpoints are disabled")
	}

	blockHash, err := block.Sha()
	if err != nil {
		return false, err
	}

	// A checkpoint must be in the main chain.
	if !b.db.ExistsSha(blockHash) {
		return false, nil
	}

	// A checkpoint must be at least CheckpointConfirmations blocks before
	// the end of the main chain.
	blockHeight := block.Height()
	_, mainChainHeight, err := b.db.NewestSha()
	if err != nil {
		return false, err
	}
	if blockHeight > (mainChainHeight - CheckpointConfirmations) {
		return false, nil
	}

	// Get the previous block.
	prevHash := &block.MsgBlock().Header.PrevBlock
	prevBlock, err := b.db.FetchBlockBySha(prevHash)
	if err != nil {
		return false, err
	}

	// Get the next block.
	nextHash, err := b.db.FetchBlockShaByHeight(blockHeight + 1)
	if err != nil {
		return false, err
	}
	nextBlock, err := b.db.FetchBlockBySha(nextHash)
	if err != nil {
		return false, err
	}

	// A checkpoint must have timestamps for the block and the blocks on
	// either side of it in order (due to the median time allowance this is
	// not always the case).
	prevTime := prevBlock.MsgBlock().Header.Timestamp
	curTime := block.MsgBlock().Header.Timestamp
	nextTime := nextBlock.MsgBlock().Header.Timestamp
	if prevTime.After(curTime) || nextTime.Before(curTime) {
		return false, nil
	}

	// A checkpoint must have transactions that only contain standard
	// scripts.
	for _, tx := range block.Transactions() {
		if isNonstandardTransaction(tx) {
			return false, nil
		}
	}

	return true, nil
}

// init is called on package load.
func init() {
	// Generate the checkpoint by height maps from the checkpoint data
	// when the package loads.
	checkpointInitializeList := []*checkpointData{
		&checkpointDataMainNet,
		&checkpointDataTestNet3,
	}
	for _, data := range checkpointInitializeList {
		data.checkpointsByHeight = make(map[int64]*Checkpoint)
		for i := range data.checkpoints {
			checkpoint := &data.checkpoints[i]
			data.checkpointsByHeight[checkpoint.Height] = checkpoint
		}
	}
}
<commit_msg>Add checkpoint at block height 279000.<commit_after>// Copyright (c) 2013-2014 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcchain

import (
	"fmt"
	"github.com/conformal/btcscript"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
)

// CheckpointConfirmations is the number of blocks before the end of the current
// best block chain that a good checkpoint candidate must be.
const CheckpointConfirmations = 2016

// Checkpoint identifies a known good point in the block chain.  Using
// checkpoints allows a few optimizations for old blocks during initial download
// and also prevents forks from old blocks.
//
// Each checkpoint is selected by the core developers based upon several
// factors.  See the documentation for IsCheckpointCandidate for details
// on the selection criteria.
//
// As alluded to above, this package provides an IsCheckpointCandidate function
// which programatically identifies a block as a checkpoint candidate.  The idea
// is that candidates are reviewed by a developer to make the final decision and
// then manually added to the list of checkpoints.
type Checkpoint struct {
	Height int64
	Hash   *btcwire.ShaHash
}

// checkpointData groups checkpoints and other pertinent checkpoint data into
// a single type.
type checkpointData struct {
	// Checkpoints ordered from oldest to newest.
	checkpoints []Checkpoint

	// A map that will be automatically generated with the heights from
	// the checkpoints as keys.
	checkpointsByHeight map[int64]*Checkpoint
}

// checkpointDataMainNet contains checkpoint data for the main network.
var checkpointDataMainNet = checkpointData{
	checkpoints: []Checkpoint{
		{11111, newShaHashFromStr("0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")},
		{33333, newShaHashFromStr("000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")},
		{74000, newShaHashFromStr("0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")},
		{105000, newShaHashFromStr("00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")},
		{134444, newShaHashFromStr("00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")},
		{168000, newShaHashFromStr("000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")},
		{193000, newShaHashFromStr("000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")},
		{210000, newShaHashFromStr("000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")},
		{216116, newShaHashFromStr("00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")},
		{225430, newShaHashFromStr("00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")},
		{250000, newShaHashFromStr("000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")},
		{267300, newShaHashFromStr("000000000000000a83fbd660e918f218bf37edd92b748ad940483c7c116179ac")},
		{279000, newShaHashFromStr("0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")},
	},
	checkpointsByHeight: nil, // Automatically generated in init.
}

// checkpointDataTestNet3 contains checkpoint data for the test network (version
// 3).
var checkpointDataTestNet3 = checkpointData{
	checkpoints: []Checkpoint{
		{546, newShaHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")},
	},
	checkpointsByHeight: nil, // Automatically generated in init.
}

// newShaHashFromStr converts the passed big-endian hex string into a
// btcwire.ShaHash.  It only differs from the one available in btcwire in that
// it ignores the error since it will only (and must only) be called with
// hard-coded, and therefore known good, hashes.
func newShaHashFromStr(hexStr string) *btcwire.ShaHash {
	sha, _ := btcwire.NewShaHashFromStr(hexStr)
	return sha
}

// DisableCheckpoints provides a mechanism to disable validation against
// checkpoints which you DO NOT want to do in production.  It is provided only
// for debug purposes.
func (b *BlockChain) DisableCheckpoints(disable bool) {
	b.noCheckpoints = disable
}

// checkpointData returns the appropriate checkpoint data set depending on the
// network configured for the block chain.
func (b *BlockChain) checkpointData() *checkpointData {
	switch b.btcnet {
	case btcwire.TestNet3:
		return &checkpointDataTestNet3
	case btcwire.MainNet:
		return &checkpointDataMainNet
	}
	return nil
}

// LatestCheckpoint returns the most recent checkpoint (regardless of whether it
// is already known).  When checkpoints are disabled or there are no checkpoints
// for the active network, it will return nil.
func (b *BlockChain) LatestCheckpoint() *Checkpoint {
	if b.noCheckpoints || b.checkpointData() == nil {
		return nil
	}

	checkpoints := b.checkpointData().checkpoints
	return &checkpoints[len(checkpoints)-1]
}

// verifyCheckpoint returns whether the passed block height and hash combination
// match the hard-coded checkpoint data.  It also returns true if there is no
// checkpoint data for the passed block height.
func (b *BlockChain) verifyCheckpoint(height int64, hash *btcwire.ShaHash) bool {
	if b.noCheckpoints || b.checkpointData() == nil {
		return true
	}

	// Nothing to check if there is no checkpoint data for the block height.
	checkpoint, exists := b.checkpointData().checkpointsByHeight[height]
	if !exists {
		return true
	}

	if !checkpoint.Hash.IsEqual(hash) {
		return false
	}

	log.Infof("Verfied checkpoint at height %d/block %s", checkpoint.Height,
		checkpoint.Hash)
	return true
}

// findLatestKnownCheckpoint finds the most recent checkpoint that is already
// available in the downloaded portion of the block chain and returns the
// associated block.  It returns nil if a checkpoint can't be found (this should
// really only happen for blocks before the first checkpoint).
func (b *BlockChain) findLatestKnownCheckpoint() (*btcutil.Block, error) {
	if b.noCheckpoints || b.checkpointData() == nil {
		return nil, nil
	}

	// No checkpoints.
	checkpoints := b.checkpointData().checkpoints
	numCheckpoints := len(checkpoints)
	if numCheckpoints == 0 {
		return nil, nil
	}

	// Perform the initial search to find and cache the latest known
	// checkpoint if the best chain is not known yet or we haven't already
	// previously searched.
	if b.bestChain == nil || (b.checkpointBlock == nil && b.nextCheckpoint == nil) {
		// Loop backwards through the available checkpoints to find one
		// that we already have.
		checkpointIndex := -1
		for i := numCheckpoints - 1; i >= 0; i-- {
			if b.db.ExistsSha(checkpoints[i].Hash) {
				checkpointIndex = i
				break
			}
		}

		// No known latest checkpoint.  This will only happen on blocks
		// before the first known checkpoint.  So, set the next expected
		// checkpoint to the first checkpoint and return the fact there
		// is no latest known checkpoint block.
		if checkpointIndex == -1 {
			b.nextCheckpoint = &checkpoints[0]
			return nil, nil
		}

		// Cache the latest known checkpoint block for future lookups.
		checkpoint := checkpoints[checkpointIndex]
		block, err := b.db.FetchBlockBySha(checkpoint.Hash)
		if err != nil {
			return nil, err
		}
		b.checkpointBlock = block

		// Set the next expected checkpoint block accordingly.
		b.nextCheckpoint = nil
		if checkpointIndex < numCheckpoints-1 {
			b.nextCheckpoint = &checkpoints[checkpointIndex+1]
		}

		return block, nil
	}

	// At this point we've already searched for the latest known checkpoint,
	// so when there is no next checkpoint, the current checkpoint lockin
	// will always be the latest known checkpoint.
	if b.nextCheckpoint == nil {
		return b.checkpointBlock, nil
	}

	// When there is a next checkpoint and the height of the current best
	// chain does not exceed it, the current checkpoint lockin is still
	// the latest known checkpoint.
	if b.bestChain.height < b.nextCheckpoint.Height {
		return b.checkpointBlock, nil
	}

	// We've reached or exceeded the next checkpoint height.  Note that
	// once a checkpoint lockin has been reached, forks are prevented from
	// any blocks before the checkpoint, so we don't have to worry about the
	// checkpoint going away out from under us due to a chain reorganize.

	// Cache the latest known checkpoint block for future lookups.  Note
	// that if this lookup fails something is very wrong since the chain
	// has already passed the checkpoint which was verified as accurate
	// before inserting it.
	block, err := b.db.FetchBlockBySha(b.nextCheckpoint.Hash)
	if err != nil {
		return nil, err
	}
	b.checkpointBlock = block

	// Set the next expected checkpoint.
	checkpointIndex := -1
	for i := numCheckpoints - 1; i >= 0; i-- {
		if checkpoints[i].Hash.IsEqual(b.nextCheckpoint.Hash) {
			checkpointIndex = i
			break
		}
	}
	b.nextCheckpoint = nil
	if checkpointIndex != -1 && checkpointIndex < numCheckpoints-1 {
		b.nextCheckpoint = &checkpoints[checkpointIndex+1]
	}

	return b.checkpointBlock, nil
}

// isNonstandardTransaction determines whether a transaction contains any
// scripts which are not one of the standard types.
func isNonstandardTransaction(tx *btcutil.Tx) bool {
	// TODO(davec): Should there be checks for the input signature scripts?

	// Check all of the output public key scripts for non-standard scripts.
	for _, txOut := range tx.MsgTx().TxOut {
		scriptClass := btcscript.GetScriptClass(txOut.PkScript)
		if scriptClass == btcscript.NonStandardTy {
			return true
		}
	}
	return false
}

// IsCheckpointCandidate returns whether or not the passed block is a good
// checkpoint candidate.
//
// The factors used to determine a good checkpoint are:
//  - The block must be in the main chain
//  - The block must be at least 'CheckpointConfirmations' blocks prior to the
//    current end of the main chain
//  - The timestamps for the blocks before and after the checkpoint must have
//    timestamps which are also before and after the checkpoint, respectively
//    (due to the median time allowance this is not always the case)
//  - The block must not contain any strange transaction such as those with
//    nonstandard scripts
func (b *BlockChain) IsCheckpointCandidate(block *btcutil.Block) (bool, error) {
	// Checkpoints must be enabled.
	if b.noCheckpoints {
		return false, fmt.Errorf("checkpoints are disabled")
	}

	blockHash, err := block.Sha()
	if err != nil {
		return false, err
	}

	// A checkpoint must be in the main chain.
	if !b.db.ExistsSha(blockHash) {
		return false, nil
	}

	// A checkpoint must be at least CheckpointConfirmations blocks before
	// the end of the main chain.
	blockHeight := block.Height()
	_, mainChainHeight, err := b.db.NewestSha()
	if err != nil {
		return false, err
	}
	if blockHeight > (mainChainHeight - CheckpointConfirmations) {
		return false, nil
	}

	// Get the previous block.
	prevHash := &block.MsgBlock().Header.PrevBlock
	prevBlock, err := b.db.FetchBlockBySha(prevHash)
	if err != nil {
		return false, err
	}

	// Get the next block.
	nextHash, err := b.db.FetchBlockShaByHeight(blockHeight + 1)
	if err != nil {
		return false, err
	}
	nextBlock, err := b.db.FetchBlockBySha(nextHash)
	if err != nil {
		return false, err
	}

	// A checkpoint must have timestamps for the block and the blocks on
	// either side of it in order (due to the median time allowance this is
	// not always the case).
	prevTime := prevBlock.MsgBlock().Header.Timestamp
	curTime := block.MsgBlock().Header.Timestamp
	nextTime := nextBlock.MsgBlock().Header.Timestamp
	if prevTime.After(curTime) || nextTime.Before(curTime) {
		return false, nil
	}

	// A checkpoint must have transactions that only contain standard
	// scripts.
	for _, tx := range block.Transactions() {
		if isNonstandardTransaction(tx) {
			return false, nil
		}
	}

	return true, nil
}

// init is called on package load.
func init() {
	// Generate the checkpoint by height maps from the checkpoint data
	// when the package loads.
	checkpointInitializeList := []*checkpointData{
		&checkpointDataMainNet,
		&checkpointDataTestNet3,
	}
	for _, data := range checkpointInitializeList {
		data.checkpointsByHeight = make(map[int64]*Checkpoint)
		for i := range data.checkpoints {
			checkpoint := &data.checkpoints[i]
			data.checkpointsByHeight[checkpoint.Height] = checkpoint
		}
	}
}
<|endoftext|>


<commit_before>// +build !windows

package stats // import "github.com/docker/docker/daemon/stats"

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/opencontainers/runc/libcontainer/system"
)

/*
#include <unistd.h>
*/
import "C"

// platformNewStatsCollector performs platform specific initialisation of the
// Collector structure.
func platformNewStatsCollector(s *Collector) {
	s.clockTicksPerSecond = uint64(system.GetClockTicks())
}

const nanoSecondsPerSecond = 1e9

// getSystemCPUUsage returns the host system's cpu usage in
// nanoseconds. An error is returned if the format of the underlying
// file does not match.
//
// Uses /proc/stat defined by POSIX. Looks for the cpu
// statistics line and then sums up the first seven fields
// provided. See `man 5 proc` for details on specific field
// information.
func (s *Collector) getSystemCPUUsage() (uint64, error) {
	var line string
	f, err := os.Open("/proc/stat")
	if err != nil {
		return 0, err
	}
	defer func() {
		s.bufReader.Reset(nil)
		f.Close()
	}()
	s.bufReader.Reset(f)
	err = nil
	for err == nil {
		line, err = s.bufReader.ReadString('\n')
		if err != nil {
			break
		}
		parts := strings.Fields(line)
		switch parts[0] {
		case "cpu":
			if len(parts) < 8 {
				return 0, fmt.Errorf("invalid number of cpu fields")
			}
			var totalClockTicks uint64
			for _, i := range parts[1:8] {
				v, err := strconv.ParseUint(i, 10, 64)
				if err != nil {
					return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err)
				}
				totalClockTicks += v
			}
			return (totalClockTicks * nanoSecondsPerSecond) /
				s.clockTicksPerSecond, nil
		}
	}
	return 0, fmt.Errorf("invalid stat format. Error trying to parse the '/proc/stat' file")
}

func (s *Collector) getNumberOnlineCPUs() (uint32, error) {
	i, err := C.sysconf(C._SC_NPROCESSORS_ONLN)
	// According to POSIX - errno is undefined after successful
	// sysconf, and can be non-zero in several cases, so look for
	// error in returned value not in errno.
	// (https://sourceware.org/bugzilla/show_bug.cgi?id=21536)
	if i == -1 {
		return 0, err
	}
	return uint32(i), nil
}
<commit_msg>fix: simplify code logic<commit_after>// +build !windows

package stats // import "github.com/docker/docker/daemon/stats"

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/opencontainers/runc/libcontainer/system"
)

/*
#include <unistd.h>
*/
import "C"

// platformNewStatsCollector performs platform specific initialisation of the
// Collector structure.
func platformNewStatsCollector(s *Collector) {
	s.clockTicksPerSecond = uint64(system.GetClockTicks())
}

const nanoSecondsPerSecond = 1e9

// getSystemCPUUsage returns the host system's cpu usage in
// nanoseconds. An error is returned if the format of the underlying
// file does not match.
//
// Uses /proc/stat defined by POSIX. Looks for the cpu
// statistics line and then sums up the first seven fields
// provided. See `man 5 proc` for details on specific field
// information.
func (s *Collector) getSystemCPUUsage() (uint64, error) {
	f, err := os.Open("/proc/stat")
	if err != nil {
		return 0, err
	}
	defer func() {
		s.bufReader.Reset(nil)
		f.Close()
	}()
	s.bufReader.Reset(f)

	for {
		line, err := s.bufReader.ReadString('\n')
		if err != nil {
			break
		}
		parts := strings.Fields(line)
		switch parts[0] {
		case "cpu":
			if len(parts) < 8 {
				return 0, fmt.Errorf("invalid number of cpu fields")
			}
			var totalClockTicks uint64
			for _, i := range parts[1:8] {
				v, err := strconv.ParseUint(i, 10, 64)
				if err != nil {
					return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err)
				}
				totalClockTicks += v
			}
			return (totalClockTicks * nanoSecondsPerSecond) /
				s.clockTicksPerSecond, nil
		}
	}
	return 0, fmt.Errorf("invalid stat format. Error trying to parse the '/proc/stat' file")
}

func (s *Collector) getNumberOnlineCPUs() (uint32, error) {
	i, err := C.sysconf(C._SC_NPROCESSORS_ONLN)
	// According to POSIX - errno is undefined after successful
	// sysconf, and can be non-zero in several cases, so look for
	// error in returned value not in errno.
	// (https://sourceware.org/bugzilla/show_bug.cgi?id=21536)
	if i == -1 {
		return 0, err
	}
	return uint32(i), nil
}
<|endoftext|>


<commit_before><commit_msg>removing rollbar on server side<commit_after><|endoftext|>


<commit_before><commit_msg>fix: sync version to 0.8.11<commit_after><|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"runtime"
	"runtime/trace"
	"strconv"
	"strings"
	"sync"
	"time"
)

type intList []int

func (il *intList) Set(s string) error {
	ss := strings.Split(s, ",")
	for _, s := range ss {
		n, err := strconv.Atoi(s)
		if err != nil {
			return err
		}
		*il = append(*il, n)
	}
	return nil
}

func (il *intList) String() string {
	var ss []string
	for _, n := range *il {
		ss = append(ss, strconv.Itoa(n))
	}
	return strings.Join(ss, ",")
}

var (
	mode      = flag.String("mode", "ideal", "one of ideal, locking, multi-N, finelocking, parsteam, linearpipe-N, splitpipe-N")
	dur       = flag.Duration("dur", 1*time.Second, "perf test duration")
	traceFlag = flag.String("trace", "./trace.out", "execution trace file")
	pars      intList
	maxqs     intList
)

func init() {
	flag.Var(&pars, "par", "perf test parallelism")
	flag.Var(&maxqs, "maxq", "max length of the request queue")
}

// Ideal case: no contention
func idealBrew() {
	useCPU(1 * time.Millisecond)
}

// Locking case: complete contention on a single set of equipent.
var equipment sync.Mutex

func lockingBrew() {
	equipment.Lock()
	grindCoffee()
	makeEspresso()
	steamMilk()
	equipment.Unlock()
}

func grindCoffee() {
	useCPU(333 * time.Microsecond)
}

func makeEspresso() {
	useCPU(334 * time.Microsecond)
}

func steamMilk() {
	useCPU(333 * time.Microsecond)
}

// Fine-grain locking reduces contention.
var grinder, espressoMachine, steamer sync.Mutex

func fineLockingBrew() {
	lockingGrind()
	lockingPress()
	lockingSteam()
}

func lockingGrind() {
	grinder.Lock()
	grindCoffee()
	grinder.Unlock()
}

func lockingPress() {
	espressoMachine.Lock()
	makeEspresso()
	espressoMachine.Unlock()
}

func lockingSteam() {
	steamer.Lock()
	steamMilk()
	steamer.Unlock()
}

// Multiple machines reduce contention.
var grinders, espressoMachines, steamers chan int

func multiBrew() {
	multiGrind()
	multiPress()
	multiSteam()
}

func multiGrind() {
	grinders <- 0
	grindCoffee()
	<-grinders
}

func multiPress() {
	espressoMachines <- 0
	makeEspresso()
	<-espressoMachines
}

func multiSteam() {
	steamers <- 0
	steamMilk()
	<-steamers
}

// Paralellizing operations can help, provided there's available CPU.
// Can steam milk while grinding & pressing, but this loses to
// fine-grain locking when all CPUs utilized.
func parallelSteaming() {
	milk := make(chan int)
	go func() {
		lockingSteam()
		milk <- 0
	}()
	lockingGrind()
	lockingPress()
	<-milk
}

// Linear pipeline
type order struct {
	latte chan int
}
type linearPipeline struct {
	orders, grounds, coffee chan order
	done                    chan int
}

func newLinearPipeline(buffer int) *linearPipeline {
	p := &linearPipeline{
		orders:  make(chan order, buffer),
		grounds: make(chan order, buffer),
		coffee:  make(chan order, buffer),
		done:    make(chan int),
	}
	go p.grinder()
	go p.presser()
	go p.steamer()
	return p
}

func (p *linearPipeline) brew() {
	o := order{make(chan int)}
	p.orders <- o
	<-o.latte
}

func (p *linearPipeline) grinder() {
	for o := range p.orders {
		grindCoffee()
		p.grounds <- o
	}
	close(p.grounds)
}

func (p *linearPipeline) presser() {
	for o := range p.grounds {
		makeEspresso()
		p.coffee <- o
	}
	close(p.coffee)
}

func (p *linearPipeline) steamer() {
	for o := range p.coffee {
		steamMilk()
		o.latte <- 0
	}
	close(p.done)
}

func (p *linearPipeline) close() {
	close(p.orders)
	<-p.done
}

// Split pipeline
type splitOrder struct {
	coffee, milk chan int
}
type splitPipeline struct {
	coffeeOrders, milkOrders, grounds chan splitOrder
	presserDone, steamerDone          chan int
}

func newSplitPipeline(buffer int) *splitPipeline {
	p := &splitPipeline{
		coffeeOrders: make(chan splitOrder, buffer),
		grounds:      make(chan splitOrder, buffer),
		milkOrders:   make(chan splitOrder, buffer),
		presserDone:  make(chan int),
		steamerDone:  make(chan int),
	}
	go p.grinder()
	go p.presser()
	go p.steamer()
	return p
}

func (p *splitPipeline) brew() {
	o := splitOrder{make(chan int), make(chan int)}
	p.coffeeOrders <- o
	p.milkOrders <- o
	<-o.coffee
	<-o.milk
}

func (p *splitPipeline) grinder() {
	for o := range p.coffeeOrders {
		grindCoffee()
		p.grounds <- o
	}
	close(p.grounds)
}

func (p *splitPipeline) presser() {
	for o := range p.grounds {
		makeEspresso()
		o.coffee <- 0
	}
	close(p.presserDone)
}

func (p *splitPipeline) steamer() {
	for o := range p.milkOrders {
		steamMilk()
		o.milk <- 0
	}
	close(p.steamerDone)
}

func (p *splitPipeline) close() {
	close(p.coffeeOrders)
	<-p.presserDone
	close(p.milkOrders)
	<-p.steamerDone
}

func main() {
	rand.Seed(time.Now().UnixNano())
	flag.Parse()
	if len(pars) == 0 || len(maxqs) == 0 {
		log.Print("need at least one --par and --maxq")
		os.Exit(1)
	}
	log.Print("mode=", *mode,
		" GOMAXPROCS=", runtime.GOMAXPROCS(0))
	if *traceFlag != "" {
		traceFile, err := os.Create(*traceFlag)
		if err != nil {
			panic(err)
		}
		trace.Start(traceFile)
		defer func() {
			trace.Stop()
			if err := traceFile.Close(); err != nil {
				log.Panic(err)
			}
		}()
	}
	var f func()
	var n int
	switch {
	case *mode == "ideal":
		f = idealBrew
	case *mode == "locking":
		f = lockingBrew
	case modeParam(*mode, "multi-", &n):
		grinders = make(chan int, n)
		espressoMachines = make(chan int, n)
		steamers = make(chan int, n)
		f = multiBrew
	case *mode == "finelocking":
		f = fineLockingBrew
	case *mode == "parsteam":
		f = parallelSteaming
	case modeParam(*mode, "linearpipe-", &n):
		p := newLinearPipeline(n)
		defer p.close()
		f = p.brew
	case modeParam(*mode, "splitpipe-", &n):
		p := newSplitPipeline(n)
		defer p.close()
		f = p.brew
	default:
		log.Panicf("unknown mode: %s", *mode)
	}
	fmt.Println(perfResultHeader)
	for _, par := range pars {
		if par == 0 {
			par = runtime.GOMAXPROCS(0)
		}
		for _, maxq := range maxqs {
			res := perfTest(10000, par, maxq, *dur, f)
			fmt.Println(res)
		}
	}
}

func modeParam(mode, prefix string, n *int) bool {
	if !strings.HasPrefix(mode, prefix) {
		return false
	}
	var err error
	*n, err = strconv.Atoi((mode)[len(prefix):])
	if err != nil {
		log.Panicf("bad mode %s: %v", mode, err)
	}
	return true
}
<commit_msg>include mode in output<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"runtime"
	"runtime/trace"
	"strconv"
	"strings"
	"sync"
	"time"
)

type intList []int

func (il *intList) Set(s string) error {
	ss := strings.Split(s, ",")
	for _, s := range ss {
		n, err := strconv.Atoi(s)
		if err != nil {
			return err
		}
		*il = append(*il, n)
	}
	return nil
}

func (il *intList) String() string {
	var ss []string
	for _, n := range *il {
		ss = append(ss, strconv.Itoa(n))
	}
	return strings.Join(ss, ",")
}

var (
	mode      = flag.String("mode", "ideal", "one of ideal, locking, multi-N, finelocking, parsteam, linearpipe-N, splitpipe-N")
	dur       = flag.Duration("dur", 1*time.Second, "perf test duration")
	traceFlag = flag.String("trace", "./trace.out", "execution trace file")
	pars      intList
	maxqs     intList
)

func init() {
	flag.Var(&pars, "par", "perf test parallelism")
	flag.Var(&maxqs, "maxq", "max length of the request queue")
}

// Ideal case: no contention
func idealBrew() {
	useCPU(1 * time.Millisecond)
}

// Locking case: complete contention on a single set of equipent.
var equipment sync.Mutex

func lockingBrew() {
	equipment.Lock()
	grindCoffee()
	makeEspresso()
	steamMilk()
	equipment.Unlock()
}

func grindCoffee() {
	useCPU(333 * time.Microsecond)
}

func makeEspresso() {
	useCPU(334 * time.Microsecond)
}

func steamMilk() {
	useCPU(333 * time.Microsecond)
}

// Fine-grain locking reduces contention.
var grinder, espressoMachine, steamer sync.Mutex

func fineLockingBrew() {
	lockingGrind()
	lockingPress()
	lockingSteam()
}

func lockingGrind() {
	grinder.Lock()
	grindCoffee()
	grinder.Unlock()
}

func lockingPress() {
	espressoMachine.Lock()
	makeEspresso()
	espressoMachine.Unlock()
}

func lockingSteam() {
	steamer.Lock()
	steamMilk()
	steamer.Unlock()
}

// Multiple machines reduce contention.
var grinders, espressoMachines, steamers chan int

func multiBrew() {
	multiGrind()
	multiPress()
	multiSteam()
}

func multiGrind() {
	grinders <- 0
	grindCoffee()
	<-grinders
}

func multiPress() {
	espressoMachines <- 0
	makeEspresso()
	<-espressoMachines
}

func multiSteam() {
	steamers <- 0
	steamMilk()
	<-steamers
}

// Paralellizing operations can help, provided there's available CPU.
// Can steam milk while grinding & pressing, but this loses to
// fine-grain locking when all CPUs utilized.
func parallelSteaming() {
	milk := make(chan int)
	go func() {
		lockingSteam()
		milk <- 0
	}()
	lockingGrind()
	lockingPress()
	<-milk
}

// Linear pipeline
type order struct {
	latte chan int
}
type linearPipeline struct {
	orders, grounds, coffee chan order
	done                    chan int
}

func newLinearPipeline(buffer int) *linearPipeline {
	p := &linearPipeline{
		orders:  make(chan order, buffer),
		grounds: make(chan order, buffer),
		coffee:  make(chan order, buffer),
		done:    make(chan int),
	}
	go p.grinder()
	go p.presser()
	go p.steamer()
	return p
}

func (p *linearPipeline) brew() {
	o := order{make(chan int)}
	p.orders <- o
	<-o.latte
}

func (p *linearPipeline) grinder() {
	for o := range p.orders {
		grindCoffee()
		p.grounds <- o
	}
	close(p.grounds)
}

func (p *linearPipeline) presser() {
	for o := range p.grounds {
		makeEspresso()
		p.coffee <- o
	}
	close(p.coffee)
}

func (p *linearPipeline) steamer() {
	for o := range p.coffee {
		steamMilk()
		o.latte <- 0
	}
	close(p.done)
}

func (p *linearPipeline) close() {
	close(p.orders)
	<-p.done
}

// Split pipeline
type splitOrder struct {
	coffee, milk chan int
}
type splitPipeline struct {
	coffeeOrders, milkOrders, grounds chan splitOrder
	presserDone, steamerDone          chan int
}

func newSplitPipeline(buffer int) *splitPipeline {
	p := &splitPipeline{
		coffeeOrders: make(chan splitOrder, buffer),
		grounds:      make(chan splitOrder, buffer),
		milkOrders:   make(chan splitOrder, buffer),
		presserDone:  make(chan int),
		steamerDone:  make(chan int),
	}
	go p.grinder()
	go p.presser()
	go p.steamer()
	return p
}

func (p *splitPipeline) brew() {
	o := splitOrder{make(chan int), make(chan int)}
	p.coffeeOrders <- o
	p.milkOrders <- o
	<-o.milk // receive in reverse order of send to avoid deadlock
	<-o.coffee
}

func (p *splitPipeline) grinder() {
	for o := range p.coffeeOrders {
		grindCoffee()
		p.grounds <- o
	}
	close(p.grounds)
}

func (p *splitPipeline) presser() {
	for o := range p.grounds {
		makeEspresso()
		o.coffee <- 0
	}
	close(p.presserDone)
}

func (p *splitPipeline) steamer() {
	for o := range p.milkOrders {
		steamMilk()
		o.milk <- 0
	}
	close(p.steamerDone)
}

func (p *splitPipeline) close() {
	close(p.coffeeOrders)
	<-p.presserDone
	close(p.milkOrders)
	<-p.steamerDone
}

func main() {
	rand.Seed(time.Now().UnixNano())
	flag.Parse()
	if len(pars) == 0 || len(maxqs) == 0 {
		log.Print("need at least one --par and --maxq")
		os.Exit(1)
	}
	log.Print("mode=", *mode,
		" GOMAXPROCS=", runtime.GOMAXPROCS(0))
	if *traceFlag != "" {
		traceFile, err := os.Create(*traceFlag)
		if err != nil {
			panic(err)
		}
		trace.Start(traceFile)
		defer func() {
			trace.Stop()
			if err := traceFile.Close(); err != nil {
				log.Panic(err)
			}
		}()
	}
	var f func()
	var n int
	switch {
	case *mode == "ideal":
		f = idealBrew
	case *mode == "locking":
		f = lockingBrew
	case modeParam(*mode, "multi-", &n):
		grinders = make(chan int, n)
		espressoMachines = make(chan int, n)
		steamers = make(chan int, n)
		f = multiBrew
	case *mode == "finelocking":
		f = fineLockingBrew
	case *mode == "parsteam":
		f = parallelSteaming
	case modeParam(*mode, "linearpipe-", &n):
		p := newLinearPipeline(n)
		defer p.close()
		f = p.brew
	case modeParam(*mode, "splitpipe-", &n):
		p := newSplitPipeline(n)
		defer p.close()
		f = p.brew
	default:
		log.Panicf("unknown mode: %s", *mode)
	}
	fmt.Println("mode," + perfResultHeader)
	for _, par := range pars {
		if par == 0 {
			par = runtime.GOMAXPROCS(0)
		}
		for _, maxq := range maxqs {
			res := perfTest(10000, par, maxq, *dur, f)
			fmt.Println(*mode + "," + res.String())
		}
	}
}

func modeParam(mode, prefix string, n *int) bool {
	if !strings.HasPrefix(mode, prefix) {
		return false
	}
	var err error
	*n, err = strconv.Atoi((mode)[len(prefix):])
	if err != nil {
		log.Panicf("bad mode %s: %v", mode, err)
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/gonuts/cbor"
	"github.com/nttdots/go-dots/coap"
	"github.com/nttdots/go-dots/dots_common/connection"
	"github.com/nttdots/go-dots/dots_common/messages"
)

type RequestInterface interface {
	LoadJson([]byte) error
	CreateRequest(messageId uint16)
	Send() error
}

/*
 * Dots requests
 */
type Request struct {
	Message     interface{}
	RequestCode messages.Code
	message     coap.Message
	coapType    coap.COAPType
	address     string
	method      string

	connectionFactory connection.ClientConnectionFactory
}

/*
 * Request constructor.
 */
func NewRequest(code messages.Code, coapType coap.COAPType, address, method string, factory connection.ClientConnectionFactory) *Request {
	return &Request{
		nil,
		code,
		coap.Message{},
		coapType,
		address,
		method,
		factory,
	}
}

/*
 * Load a Message to this Request
 */
func (r *Request) LoadMessage(message interface{}) {
	r.Message = message
}

/*
 * convert this Request into the Cbor format.
 */
func (r *Request) dumpCbor() []byte {

	cborWriter := bytes.NewBuffer(nil)
	e := cbor.NewEncoder(cborWriter)

	err := e.Encode(r.Message)
	if err != nil {
		log.Errorf("Error decoding %s", err)
	}
	return cborWriter.Bytes()

}

/*
 * convert this Requests into the JSON format.
 */
func (r *Request) dumpJson() []byte {
	payload, _ := json.Marshal(r.Message)
	return payload
}

/*
 * Load Message from JSON data.
 */
func (r *Request) LoadJson(jsonData []byte) error {
	m := reflect.New(r.RequestCode.Type()).Interface()

	err := json.Unmarshal(jsonData, &m)
	if err != nil {
		return fmt.Errorf("Can't Convert Json to Message Object: %v\n", err)

	}
	r.Message = m
	return nil
}

/*
 * return the Request paths.
 */
func (r *Request) pathString() {
	r.RequestCode.PathString()
}

/*
 * Create CoAP requests.
 */
func (r *Request) CreateRequest(messageId uint16) {
	var code coap.COAPCode

	switch strings.ToUpper(r.method) {
	case "GET":
		code = coap.GET
	case "PUT":
		code = coap.PUT
	case "POST":
		code = coap.POST
	case "DELETE":
		code = coap.DELETE
	default:
		log.WithField("method", r.method).Error("invalid request method.")
	}

	r.message = coap.Message{
		Type:      r.coapType,
		Code:      code,
		MessageID: messageId,
		Payload:   r.dumpCbor(),
	}

	r.message.SetOption(coap.ContentFormat, coap.AppCbor)
	r.message.SetPathString(r.RequestCode.PathString())
}

/*
 * Set the certificate common name to the CoAP request messages.
 */
func (r *Request) SetCommonName(commonName string) {
	r.message.SetOption(coap.CommonName, commonName)
}

/*
 * Send the request to the server.
*/
func (r *Request) Send() (err error) {
	conn, err := r.connectionFactory.Connect(r.address)
	if err != nil {
		log.WithError(err).Error("dtls connect error.")
		return err
	}
	defer conn.Close()

	recv, err := coap.Send(conn, r.message)
	if err != nil {
		return
	}

	if recv.Payload != nil {
		log.Infof("Response payload: %s", recv.Payload)
	}

	return
}

func (r *Request) Close() {
	r.connectionFactory.Close()
}
<commit_msg>show response from server<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/gonuts/cbor"
	"github.com/nttdots/go-dots/coap"
	"github.com/nttdots/go-dots/dots_common/connection"
	"github.com/nttdots/go-dots/dots_common/messages"
)

type RequestInterface interface {
	LoadJson([]byte) error
	CreateRequest(messageId uint16)
	Send() error
}

/*
 * Dots requests
 */
type Request struct {
	Message     interface{}
	RequestCode messages.Code
	message     coap.Message
	coapType    coap.COAPType
	address     string
	method      string

	connectionFactory connection.ClientConnectionFactory
}

/*
 * Request constructor.
 */
func NewRequest(code messages.Code, coapType coap.COAPType, address, method string, factory connection.ClientConnectionFactory) *Request {
	return &Request{
		nil,
		code,
		coap.Message{},
		coapType,
		address,
		method,
		factory,
	}
}

/*
 * Load a Message to this Request
 */
func (r *Request) LoadMessage(message interface{}) {
	r.Message = message
}

/*
 * convert this Request into the Cbor format.
 */
func (r *Request) dumpCbor() []byte {

	cborWriter := bytes.NewBuffer(nil)
	e := cbor.NewEncoder(cborWriter)

	err := e.Encode(r.Message)
	if err != nil {
		log.Errorf("Error decoding %s", err)
	}
	return cborWriter.Bytes()

}

/*
 * convert this Requests into the JSON format.
 */
func (r *Request) dumpJson() []byte {
	payload, _ := json.Marshal(r.Message)
	return payload
}

/*
 * Load Message from JSON data.
 */
func (r *Request) LoadJson(jsonData []byte) error {
	m := reflect.New(r.RequestCode.Type()).Interface()

	err := json.Unmarshal(jsonData, &m)
	if err != nil {
		return fmt.Errorf("Can't Convert Json to Message Object: %v\n", err)

	}
	r.Message = m
	return nil
}

/*
 * return the Request paths.
 */
func (r *Request) pathString() {
	r.RequestCode.PathString()
}

/*
 * Create CoAP requests.
 */
func (r *Request) CreateRequest(messageId uint16) {
	var code coap.COAPCode

	switch strings.ToUpper(r.method) {
	case "GET":
		code = coap.GET
	case "PUT":
		code = coap.PUT
	case "POST":
		code = coap.POST
	case "DELETE":
		code = coap.DELETE
	default:
		log.WithField("method", r.method).Error("invalid request method.")
	}

	r.message = coap.Message{
		Type:      r.coapType,
		Code:      code,
		MessageID: messageId,
		Payload:   r.dumpCbor(),
	}

	r.message.SetOption(coap.ContentFormat, coap.AppCbor)
	r.message.SetPathString(r.RequestCode.PathString())
}

/*
 * Set the certificate common name to the CoAP request messages.
 */
func (r *Request) SetCommonName(commonName string) {
	r.message.SetOption(coap.CommonName, commonName)
}

/*
 * Send the request to the server.
*/
func (r *Request) Send() (err error) {
	conn, err := r.connectionFactory.Connect(r.address)
	if err != nil {
		log.WithError(err).Error("dtls connect error.")
		return err
	}
	defer conn.Close()

	recv, err := coap.Send(conn, r.message)
	if err != nil {
		log.Warnf("Send() => %s", err)
		return
	}

	logMessage(recv)

	return
}

func (r *Request) Close() {
	r.connectionFactory.Close()
}

func logMessage(msg coap.Message) {
	log.Infof("Message Code: %s (%d)", msg.Code, msg.Code)

	if msg.Payload == nil {
		return
	}

	log.Infof("        Raw payload: %s", msg.Payload)

	var v interface {}
	dec := cbor.NewDecoder(bytes.NewReader(msg.Payload))
	err := dec.Decode(&v)
	if err != nil {
		log.WithError(err).Warn("CBOR Decode failed.")
		return
	}

	log.Infof("        CBOR decoded: %s", v)
}
<|endoftext|>


<commit_before>package http

import (
	"reflect"
	"testing"

	"github.com/hashicorp/vault/vault"
)

func TestSysCapabilitiesAccessor(t *testing.T) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := TestServer(t, core)
	defer ln.Close()
	TestServerAuth(t, addr, token)

	// Lookup the token properties
	resp := testHttpGet(t, token, addr+"/v1/auth/token/lookup/"+token)
	var lookupResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &lookupResp)

	// Retrieve the accessor from the token properties
	lookupData := lookupResp["data"].(map[string]interface{})
	accessor := lookupData["accessor"].(string)

	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-accessor", map[string]interface{}{
		"accessor": accessor,
		"path":     "testpath",
	})

	var result map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	err = resp.DecodeJSON(&result)
	if err != nil {
		return nil, err
	}
	var actual []string
	capabilitiesRaw := result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected := []string{"root"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Testing for non-root token's accessor
	// Create a policy first
	resp = testHttpPost(t, token, addr+"/v1/sys/policy/foo", map[string]interface{}{
		"rules": `path "testpath" {capabilities = ["read","sudo"]}`,
	})
	testResponseStatus(t, resp, 204)

	// Create a token against the test policy
	resp = testHttpPost(t, token, addr+"/v1/auth/token/create", map[string]interface{}{
		"policies": []string{"foo"},
	})

	var tokenResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &tokenResp)

	// Check if desired policies are present in the token
	auth := tokenResp["auth"].(map[string]interface{})
	actualPolicies := auth["policies"]
	expectedPolicies := []interface{}{"default", "foo"}
	if !reflect.DeepEqual(actualPolicies, expectedPolicies) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actualPolicies, expectedPolicies)
	}

	// Check the capabilities of non-root token using the accessor
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-accessor", map[string]interface{}{
		"accessor": auth["accessor"],
		"path":     "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	err = resp.DecodeJSON(&result)
	if err != nil {
		return nil, err
	}
	var actual []string
	capabilitiesRaw := result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected := []string{"sudo", "read"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}
}

func TestSysCapabilities(t *testing.T) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := TestServer(t, core)
	defer ln.Close()
	TestServerAuth(t, addr, token)

	// Send both token and path
	resp := testHttpPost(t, token, addr+"/v1/sys/capabilities", map[string]interface{}{
		"token": token,
		"path":  "testpath",
	})

	var actual map[string][]string
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &actual)

	expected := map[string][]string{
		"capabilities": []string{"root"},
	}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Send only path to capabilities-self
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-self", map[string]interface{}{
		"path": "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &actual)
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Testing for non-root tokens

	// Create a policy first
	resp = testHttpPost(t, token, addr+"/v1/sys/policy/foo", map[string]interface{}{
		"rules": `path "testpath" {capabilities = ["read","sudo"]}`,
	})
	testResponseStatus(t, resp, 204)

	// Create a token against the test policy
	resp = testHttpPost(t, token, addr+"/v1/auth/token/create", map[string]interface{}{
		"policies": []string{"foo"},
	})

	var tokenResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &tokenResp)

	// Check if desired policies are present in the token
	auth := tokenResp["auth"].(map[string]interface{})
	actualPolicies := auth["policies"]
	expectedPolicies := []interface{}{"default", "foo"}
	if !reflect.DeepEqual(actualPolicies, expectedPolicies) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actualPolicies, expectedPolicies)
	}

	// Check the capabilities with the created non-root token
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities", map[string]interface{}{
		"token": auth["client_token"],
		"path":  "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &actual)

	expected = map[string][]string{
		"capabilities": []string{"sudo", "read"},
	}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}
}
<commit_msg>Fix http capabilities tests<commit_after>package http

import (
	"reflect"
	"testing"

	"github.com/hashicorp/vault/vault"
)

func TestSysCapabilitiesAccessor(t *testing.T) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := TestServer(t, core)
	defer ln.Close()
	TestServerAuth(t, addr, token)

	// Lookup the token properties
	resp := testHttpGet(t, token, addr+"/v1/auth/token/lookup/"+token)
	var lookupResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &lookupResp)

	// Retrieve the accessor from the token properties
	lookupData := lookupResp["data"].(map[string]interface{})
	accessor := lookupData["accessor"].(string)

	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-accessor", map[string]interface{}{
		"accessor": accessor,
		"path":     "testpath",
	})

	var result map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	var actual []string
	capabilitiesRaw := result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected := []string{"root"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Testing for non-root token's accessor
	// Create a policy first
	resp = testHttpPost(t, token, addr+"/v1/sys/policy/foo", map[string]interface{}{
		"rules": `path "testpath" {capabilities = ["read","sudo"]}`,
	})
	testResponseStatus(t, resp, 204)

	// Create a token against the test policy
	resp = testHttpPost(t, token, addr+"/v1/auth/token/create", map[string]interface{}{
		"policies": []string{"foo"},
	})

	var tokenResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &tokenResp)

	// Check if desired policies are present in the token
	auth := tokenResp["auth"].(map[string]interface{})
	actualPolicies := auth["policies"]
	expectedPolicies := []interface{}{"default", "foo"}
	if !reflect.DeepEqual(actualPolicies, expectedPolicies) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actualPolicies, expectedPolicies)
	}

	// Check the capabilities of non-root token using the accessor
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-accessor", map[string]interface{}{
		"accessor": auth["accessor"],
		"path":     "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	actual = nil
	capabilitiesRaw = result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected = []string{"sudo", "read"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}
}

func TestSysCapabilities(t *testing.T) {
	core, _, token := vault.TestCoreUnsealed(t)
	ln, addr := TestServer(t, core)
	defer ln.Close()
	TestServerAuth(t, addr, token)

	// Send both token and path
	resp := testHttpPost(t, token, addr+"/v1/sys/capabilities", map[string]interface{}{
		"token": token,
		"path":  "testpath",
	})

	var result map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	var actual []string
	capabilitiesRaw := result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected := []string{"root"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Send only path to capabilities-self
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities-self", map[string]interface{}{
		"path": "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	actual = nil
	capabilitiesRaw = result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}

	// Testing for non-root tokens

	// Create a policy first
	resp = testHttpPost(t, token, addr+"/v1/sys/policy/foo", map[string]interface{}{
		"rules": `path "testpath" {capabilities = ["read","sudo"]}`,
	})
	testResponseStatus(t, resp, 204)

	// Create a token against the test policy
	resp = testHttpPost(t, token, addr+"/v1/auth/token/create", map[string]interface{}{
		"policies": []string{"foo"},
	})

	var tokenResp map[string]interface{}
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &tokenResp)

	// Check if desired policies are present in the token
	auth := tokenResp["auth"].(map[string]interface{})
	actualPolicies := auth["policies"]
	expectedPolicies := []interface{}{"default", "foo"}
	if !reflect.DeepEqual(actualPolicies, expectedPolicies) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actualPolicies, expectedPolicies)
	}

	// Check the capabilities with the created non-root token
	resp = testHttpPost(t, token, addr+"/v1/sys/capabilities", map[string]interface{}{
		"token": auth["client_token"],
		"path":  "testpath",
	})
	testResponseStatus(t, resp, 200)
	testResponseBody(t, resp, &result)

	actual = nil
	capabilitiesRaw = result["data"].(map[string]interface{})["capabilities"].([]interface{})
	for _, capability := range capabilitiesRaw {
		actual = append(actual, capability.(string))
	}

	expected = []string{"sudo", "read"}
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, expected)
	}
}
<|endoftext|>