<commit_before>// Package dnsprobe implements a DNS probe.
package dnsprobe // import "hkjn.me/probes/dnsprobe"

import (
	"fmt"
	"net"
	"sort"
	"time"

	"github.com/golang/glog"

	"hkjn.me/prober"
	"hkjn.me/probes"
)

// DnsProber probes a target host's DNS records.
type DnsProber struct {
	Target    string // host to probe
	wantMX    mxRecords
	wantA     []string
	wantNS    nsRecords
	wantCNAME string
	wantTXT   []string
}

// MX applies the option that the prober wants specific MX records.
func MX(mx []*net.MX) func(*DnsProber) {
	return func(p *DnsProber) {
		wantMX := mxRecords(mx)
		sort.Sort(wantMX)
		p.wantMX = wantMX
	}
}

// A applies the option that the prober wants specific A records.
func A(a []string) func(*DnsProber) {
	return func(p *DnsProber) {
		sort.Strings(a)
		p.wantA = a
	}
}

// NS applies the option that the prober wants specific NS records.
func NS(ns []*net.NS) func(*DnsProber) {
	return func(p *DnsProber) {
		nsRec := nsRecords(ns)
		sort.Sort(nsRec)
		p.wantNS = nsRec
	}
}

// CNAME applies the option that the prober wants specific CNAME record.
func CNAME(cname string) func(*DnsProber) {
	return func(p *DnsProber) {
		p.wantCNAME = cname
	}
}

// TXT applies the option that the prober wants specific TXT records.
func TXT(txt []string) func(*DnsProber) {
	return func(p *DnsProber) {
		sort.Strings(txt)
		p.wantTXT = txt
	}
}

// New returns a new instance of the DNS probe with specified options.
func New(target string, options ...func(*DnsProber)) *prober.Probe {
	p := &DnsProber{Target: target}
	for _, opt := range options {
		opt(p)
	}
	return prober.NewProbe(p, "DnsProber", fmt.Sprintf("Probes DNS records of %s", target),
		prober.Interval(time.Minute*5), prober.FailurePenalty(5))
}

// Probe verifies that the target's DNS records are as expected.
func (p *DnsProber) Probe() error {
	if len(p.wantMX) > 0 {
		glog.V(1).Infof("Checking %d MX records..\n", len(p.wantMX))
		err := p.checkMX()
		if err != nil {
			return err
		}
	}
	if len(p.wantA) > 0 {
		glog.V(1).Infof("Checking %d A records..\n", len(p.wantA))
		err := p.checkA()
		if err != nil {
			return err
		}
	}
	if len(p.wantNS) > 0 {
		glog.V(1).Infof("Checking %d NS records..\n", len(p.wantNS))
		err := p.checkNS()
		if err != nil {
			return err
		}
	}
	if p.wantCNAME != "" {
		glog.V(1).Infof("Checking CNAME record..\n")
		err := p.checkCNAME()
		if err != nil {
			return err
		}
	}
	if len(p.wantTXT) > 0 {
		glog.V(1).Infof("Checking %d TXT records..\n", len(p.wantTXT))
		err := p.checkTXT()
		if err != nil {
			return err
		}
	}
	return nil
}

// mxRecords is a collection of MX records, implementing sort.Interface.
//
// We need this custom order since the sort order in net.LookupMX
// randomizes records with the same preference value.
type mxRecords []*net.MX

func (r mxRecords) Len() int { return len(r) }

func (r mxRecords) Swap(i, j int) { r[i], r[j] = r[j], r[i] }

func (r mxRecords) Less(i, j int) bool {
	if r[i].Pref == r[j].Pref {
		return r[i].Host < r[j].Host
	}
	return r[i].Pref < r[j].Pref
}

// String returns a readable description of the MX records.
func (r mxRecords) String() string {
	s := ""
	for i, r := range r {
		if i > 0 {
			s += ", "
		}
		s += fmt.Sprintf("%s (%d)", r.Host, r.Pref)
	}
	return s
}

// checkMX verifies that the target has expected MX records.
func (p *DnsProber) checkMX() error {
	mx, err := net.LookupMX(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up MX records for %s: %v", p.Target, err)
	}
	mxRec := mxRecords(mx)
	if len(mxRec) != len(p.wantMX) {
		return fmt.Errorf("want %d MX records, got %d: %s", len(p.wantMX), len(mxRec), mxRec)
	}
	sort.Sort(mxRec)
	for i, r := range mxRec {
		if p.wantMX[i].Host != r.Host {
			return fmt.Errorf("bad host %q for MX record #%d; want %q", r.Host, i, p.wantMX[i].Host)
		}
		if p.wantMX[i].Pref != r.Pref {
			return fmt.Errorf("bad prio %d for MX record #%d; want %d", i, r.Pref, p.wantMX[i].Pref)
		}
	}
	return nil
}

// checkA verifies that the target has expected A records.
func (p *DnsProber) checkA() error {
	addr, err := net.LookupHost(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up A records for %s: %v", p.Target, err)
	}
	if len(addr) != len(p.wantA) {
		return fmt.Errorf("got %d A records, want %d", len(addr), len(p.wantA))
	}
	sort.Strings(addr)
	for i, a := range addr {
		if p.wantA[i] != a {
			return fmt.Errorf("bad A record %q at #%d; want %q", a, i, p.wantA[i])
		}
	}
	return nil
}

// nsRecords is a collection of NS records, implementing sort.Interface.
type nsRecords []*net.NS

func (r nsRecords) Len() int { return len(r) }

func (r nsRecords) Swap(i, j int) { r[i], r[j] = r[j], r[i] }

func (r nsRecords) Less(i, j int) bool { return r[i].Host < r[j].Host }

// String returns a readable description of the NS records.
func (ns nsRecords) String() string {
	s := ""
	for i, r := range ns {
		if i > 0 {
			s += ", "
		}
		s += r.Host
	}
	return s
}

// checkNS verifies that the target has expected NS records.
func (p *DnsProber) checkNS() error {
	ns, err := net.LookupNS(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up NS records for %s: %v", p.Target, err)
	}
	nsRec := nsRecords(ns)
	if len(nsRec) != len(p.wantNS) {
		return fmt.Errorf("want %d NS records, got %d: %s", len(p.wantNS), len(nsRec), nsRec)
	}
	sort.Sort(nsRec)
	for i, n := range ns {
		if p.wantNS[i].Host != n.Host {
			return fmt.Errorf("bad NS record %q at #%d; want %q", n, i, p.wantNS[i])
		}
	}
	return nil
}

// checkCNAME verifies that the target has expected CNAME record.
func (p *DnsProber) checkCNAME() error {
	cname, err := net.LookupCNAME(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up CNAME record for %s: %v", p.Target, err)
	}
	if cname != p.wantCNAME {
		return fmt.Errorf("bad CNAME record %q; want %q", cname, p.wantCNAME)
	}
	return nil
}

// checkTXT verifies that the target has expected TXT records.
func (p *DnsProber) checkTXT() error {
	txt, err := net.LookupTXT(p.Target)
	if err != nil {
		return err
	}
	if len(txt) != len(p.wantTXT) {
		return fmt.Errorf("want %d TXT records, got %d: %s", len(p.wantTXT), len(txt), txt)
	}
	sort.Strings(txt)
	for i, t := range txt {
		if p.wantTXT[i] != t {
			return fmt.Errorf("bad TXT record %q at #%d; want %q", t, i, p.wantTXT[i])
		}
	}
	return nil
}

// Alert sends an alert notification via email.
func (p *DnsProber) Alert(name, desc string, badness int, records prober.Records) error {
	return probes.SendAlertEmail(name, desc, badness, records)
}
<commit_msg>different case is ok in MX records, jeez<commit_after>// Package dnsprobe implements a DNS probe.
package dnsprobe // import "hkjn.me/probes/dnsprobe"

import (
	"fmt"
	"net"
	"sort"
	"strings"
	"time"

	"github.com/golang/glog"

	"hkjn.me/prober"
	"hkjn.me/probes"
)

// DnsProber probes a target host's DNS records.
type DnsProber struct {
	Target    string // host to probe
	wantMX    mxRecords
	wantA     []string
	wantNS    nsRecords
	wantCNAME string
	wantTXT   []string
}

// MX applies the option that the prober wants specific MX records.
func MX(mx []*net.MX) func(*DnsProber) {
	return func(p *DnsProber) {
		wantMX := mxRecords(mx)
		sort.Sort(wantMX)
		p.wantMX = wantMX
	}
}

// A applies the option that the prober wants specific A records.
func A(a []string) func(*DnsProber) {
	return func(p *DnsProber) {
		sort.Strings(a)
		p.wantA = a
	}
}

// NS applies the option that the prober wants specific NS records.
func NS(ns []*net.NS) func(*DnsProber) {
	return func(p *DnsProber) {
		nsRec := nsRecords(ns)
		sort.Sort(nsRec)
		p.wantNS = nsRec
	}
}

// CNAME applies the option that the prober wants specific CNAME record.
func CNAME(cname string) func(*DnsProber) {
	return func(p *DnsProber) {
		p.wantCNAME = cname
	}
}

// TXT applies the option that the prober wants specific TXT records.
func TXT(txt []string) func(*DnsProber) {
	return func(p *DnsProber) {
		sort.Strings(txt)
		p.wantTXT = txt
	}
}

// New returns a new instance of the DNS probe with specified options.
func New(target string, options ...func(*DnsProber)) *prober.Probe {
	p := &DnsProber{Target: target}
	for _, opt := range options {
		opt(p)
	}
	return prober.NewProbe(p, "DnsProber", fmt.Sprintf("Probes DNS records of %s", target),
		prober.Interval(time.Minute*5), prober.FailurePenalty(5))
}

// Probe verifies that the target's DNS records are as expected.
func (p *DnsProber) Probe() error {
	if len(p.wantMX) > 0 {
		glog.V(1).Infof("Checking %d MX records..\n", len(p.wantMX))
		err := p.checkMX()
		if err != nil {
			return err
		}
	}
	if len(p.wantA) > 0 {
		glog.V(1).Infof("Checking %d A records..\n", len(p.wantA))
		err := p.checkA()
		if err != nil {
			return err
		}
	}
	if len(p.wantNS) > 0 {
		glog.V(1).Infof("Checking %d NS records..\n", len(p.wantNS))
		err := p.checkNS()
		if err != nil {
			return err
		}
	}
	if p.wantCNAME != "" {
		glog.V(1).Infof("Checking CNAME record..\n")
		err := p.checkCNAME()
		if err != nil {
			return err
		}
	}
	if len(p.wantTXT) > 0 {
		glog.V(1).Infof("Checking %d TXT records..\n", len(p.wantTXT))
		err := p.checkTXT()
		if err != nil {
			return err
		}
	}
	return nil
}

// mxRecords is a collection of MX records, implementing sort.Interface.
//
// We need this custom order since the sort order in net.LookupMX
// randomizes records with the same preference value.
type mxRecords []*net.MX

func (r mxRecords) Len() int { return len(r) }

func (r mxRecords) Swap(i, j int) { r[i], r[j] = r[j], r[i] }

func (r mxRecords) Less(i, j int) bool {
	if r[i].Pref == r[j].Pref {
		return r[i].Host < r[j].Host
	}
	return r[i].Pref < r[j].Pref
}

// String returns a readable description of the MX records.
func (r mxRecords) String() string {
	s := ""
	for i, r := range r {
		if i > 0 {
			s += ", "
		}
		s += fmt.Sprintf("%s (%d)", r.Host, r.Pref)
	}
	return s
}

// checkMX verifies that the target has expected MX records.
func (p *DnsProber) checkMX() error {
	mx, err := net.LookupMX(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up MX records for %s: %v", p.Target, err)
	}
	mxRec := mxRecords(mx)
	if len(mxRec) != len(p.wantMX) {
		return fmt.Errorf("want %d MX records, got %d: %s", len(p.wantMX), len(mxRec), mxRec)
	}
	sort.Sort(mxRec)
	for i, r := range mxRec {
		if !strings.EqualFold(p.wantMX[i].Host, r.Host) {
			return fmt.Errorf("bad host %q for MX record #%d; want %q", r.Host, i, p.wantMX[i].Host)
		}
		if p.wantMX[i].Pref != r.Pref {
			return fmt.Errorf("bad prio %d for MX record #%d; want %d", i, r.Pref, p.wantMX[i].Pref)
		}
	}
	return nil
}

// checkA verifies that the target has expected A records.
func (p *DnsProber) checkA() error {
	addr, err := net.LookupHost(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up A records for %s: %v", p.Target, err)
	}
	if len(addr) != len(p.wantA) {
		return fmt.Errorf("got %d A records, want %d", len(addr), len(p.wantA))
	}
	sort.Strings(addr)
	for i, a := range addr {
		if p.wantA[i] != a {
			return fmt.Errorf("bad A record %q at #%d; want %q", a, i, p.wantA[i])
		}
	}
	return nil
}

// nsRecords is a collection of NS records, implementing sort.Interface.
type nsRecords []*net.NS

func (r nsRecords) Len() int { return len(r) }

func (r nsRecords) Swap(i, j int) { r[i], r[j] = r[j], r[i] }

func (r nsRecords) Less(i, j int) bool { return r[i].Host < r[j].Host }

// String returns a readable description of the NS records.
func (ns nsRecords) String() string {
	s := ""
	for i, r := range ns {
		if i > 0 {
			s += ", "
		}
		s += r.Host
	}
	return s
}

// checkNS verifies that the target has expected NS records.
func (p *DnsProber) checkNS() error {
	ns, err := net.LookupNS(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up NS records for %s: %v", p.Target, err)
	}
	nsRec := nsRecords(ns)
	if len(nsRec) != len(p.wantNS) {
		return fmt.Errorf("want %d NS records, got %d: %s", len(p.wantNS), len(nsRec), nsRec)
	}
	sort.Sort(nsRec)
	for i, n := range ns {
		if p.wantNS[i].Host != n.Host {
			return fmt.Errorf("bad NS record %q at #%d; want %q", n, i, p.wantNS[i])
		}
	}
	return nil
}

// checkCNAME verifies that the target has expected CNAME record.
func (p *DnsProber) checkCNAME() error {
	cname, err := net.LookupCNAME(p.Target)
	if err != nil {
		return fmt.Errorf("failed to look up CNAME record for %s: %v", p.Target, err)
	}
	if cname != p.wantCNAME {
		return fmt.Errorf("bad CNAME record %q; want %q", cname, p.wantCNAME)
	}
	return nil
}

// checkTXT verifies that the target has expected TXT records.
func (p *DnsProber) checkTXT() error {
	txt, err := net.LookupTXT(p.Target)
	if err != nil {
		return err
	}
	if len(txt) != len(p.wantTXT) {
		return fmt.Errorf("want %d TXT records, got %d: %s", len(p.wantTXT), len(txt), txt)
	}
	sort.Strings(txt)
	for i, t := range txt {
		if p.wantTXT[i] != t {
			return fmt.Errorf("bad TXT record %q at #%d; want %q", t, i, p.wantTXT[i])
		}
	}
	return nil
}

// Alert sends an alert notification via email.
func (p *DnsProber) Alert(name, desc string, badness int, records prober.Records) error {
	return probes.SendAlertEmail(name, desc, badness, records)
}
<|endoftext|>


<commit_before>package vizzini_test

import (
	"strconv"

	"time"

	. "code.cloudfoundry.org/vizzini/matchers"

	"code.cloudfoundry.org/bbs/models"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Actions", func() {
	var taskDef *models.TaskDefinition

	Describe("Timeout action", func() {
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(models.Timeout(
				&models.RunAction{
					Path: "bash",
					Args: []string{"-c", "sleep 1000"},
					User: "vcap",
				},
				2*time.Second,
			))
			taskDef.ResultFile = ""

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("should fail the Task within the timeout window", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Running))
			Eventually(TaskGetter(logger, guid), 10).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeTrue())
			Expect(task.GetFailureReason()).To(ContainSubstring("timeout"))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})
	})

	Describe("Run action", func() {
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(&models.RunAction{
				Path: "bash",
				Dir:  "/etc",
				Args: []string{"-c", "echo $PWD > /tmp/bar"},
				User: "vcap",
			})

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("should be possible to specify a working directory", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeFalse())
			Expect(task.GetResult()).To(ContainSubstring("/etc"))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})

	})

	Describe("Run action resource limits", func() {
		var processLimit uint64 = 117
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(&models.RunAction{
				Path: "bash",
				Dir:  "/etc",
				Args: []string{"-c", "ulimit -u > /tmp/bar"},
				User: "vcap",
				ResourceLimits: &models.ResourceLimits{
					Nproc: &processLimit,
				},
			})

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("is possible to limit the number of processes", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeFalse())
			Expect(task.GetResult()).To(ContainSubstring(strconv.FormatUint(processLimit, 10)))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})
	})

	Describe("Cancelling Downloads", func() {
		It("should cancel the download", func() {
			desiredLRP := &models.DesiredLRP{
				ProcessGuid: guid,
				RootFs:      defaultRootFS,
				Domain:      domain,
				Instances:   1,
				Action: models.WrapAction(&models.DownloadAction{
					From: "https://s3-us-west-1.amazonaws.com/onsi-public/foo.zip",
					To:   "/tmp",
					User: "vcap",
				}),
			}

			Expect(bbsClient.DesireLRP(logger, desiredLRP)).To(Succeed())
			time.Sleep(3 * time.Second)
			Expect(bbsClient.RemoveDesiredLRP(logger, desiredLRP.ProcessGuid)).To(Succeed())
			Eventually(ActualByProcessGuidGetter(logger, desiredLRP.ProcessGuid), 5).Should(BeEmpty())
		})
	})
})
<commit_msg>Increase nproc for resource limit test<commit_after>package vizzini_test

import (
	"strconv"

	"time"

	. "code.cloudfoundry.org/vizzini/matchers"

	"code.cloudfoundry.org/bbs/models"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Actions", func() {
	var taskDef *models.TaskDefinition

	Describe("Timeout action", func() {
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(models.Timeout(
				&models.RunAction{
					Path: "bash",
					Args: []string{"-c", "sleep 1000"},
					User: "vcap",
				},
				2*time.Second,
			))
			taskDef.ResultFile = ""

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("should fail the Task within the timeout window", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Running))
			Eventually(TaskGetter(logger, guid), 10).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeTrue())
			Expect(task.GetFailureReason()).To(ContainSubstring("timeout"))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})
	})

	Describe("Run action", func() {
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(&models.RunAction{
				Path: "bash",
				Dir:  "/etc",
				Args: []string{"-c", "echo $PWD > /tmp/bar"},
				User: "vcap",
			})

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("should be possible to specify a working directory", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeFalse())
			Expect(task.GetResult()).To(ContainSubstring("/etc"))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})

	})

	Describe("Run action resource limits", func() {
		var processLimit uint64 = 23790
		BeforeEach(func() {
			taskDef = Task()
			taskDef.Action = models.WrapAction(&models.RunAction{
				Path: "bash",
				Dir:  "/etc",
				Args: []string{"-c", "ulimit -u > /tmp/bar"},
				User: "vcap",
				ResourceLimits: &models.ResourceLimits{
					Nproc: &processLimit,
				},
			})

			Expect(bbsClient.DesireTask(logger, guid, domain, taskDef)).To(Succeed())
		})

		It("is possible to limit the number of processes", func() {
			Eventually(TaskGetter(logger, guid)).Should(HaveTaskState(models.Task_Completed))
			task, err := bbsClient.TaskByGuid(logger, guid)
			Expect(err).NotTo(HaveOccurred())
			Expect(task.GetFailed()).To(BeFalse())
			Expect(task.GetResult()).To(ContainSubstring(strconv.FormatUint(processLimit, 10)))

			Expect(bbsClient.ResolvingTask(logger, guid)).To(Succeed())
			Expect(bbsClient.DeleteTask(logger, guid)).To(Succeed())
		})
	})

	Describe("Cancelling Downloads", func() {
		It("should cancel the download", func() {
			desiredLRP := &models.DesiredLRP{
				ProcessGuid: guid,
				RootFs:      defaultRootFS,
				Domain:      domain,
				Instances:   1,
				Action: models.WrapAction(&models.DownloadAction{
					From: "https://s3-us-west-1.amazonaws.com/onsi-public/foo.zip",
					To:   "/tmp",
					User: "vcap",
				}),
			}

			Expect(bbsClient.DesireLRP(logger, desiredLRP)).To(Succeed())
			time.Sleep(3 * time.Second)
			Expect(bbsClient.RemoveDesiredLRP(logger, desiredLRP.ProcessGuid)).To(Succeed())
			Eventually(ActualByProcessGuidGetter(logger, desiredLRP.ProcessGuid), 5).Should(BeEmpty())
		})
	})
})
<|endoftext|>


<commit_before>package editor

import (
	"bufio"
	"context"
	"io"

	"github.com/elpinal/coco3/config"
	"github.com/elpinal/coco3/screen"
)

type Editor interface {
	Read() ([]rune, error)
	Clear()
	SetHistory([][]rune)
}

func New(s screen.Screen, conf *config.Config, in io.Reader, out, err io.Writer) Editor {
	return NewContext(context.Background(), s, conf, in, out, err)
}

func NewContext(ctx context.Context, s screen.Screen, conf *config.Config, in io.Reader, out, err io.Writer) Editor {
	var rd io.RuneReader
	if x, ok := in.(io.RuneReader); ok {
		rd = x
	} else {
		rd = bufio.NewReaderSize(in, 64)
	}
	r := NewReaderContext(ctx, rd)
	return &balancer{
		streamSet: streamSet{
			in:  r,
			out: out,
			err: err,
		},
		editor: &editor{undoTree: newUndoTree()},
		s:      s,
		conf:   conf,
	}
}

type streamSet struct {
	in  *RuneAddReader
	out io.Writer
	err io.Writer
}

type balancer struct {
	streamSet
	*editor
	s    screen.Screen
	conf *config.Config
}

func (b *balancer) Read() ([]rune, error) {
	b.s.SetLastLine("-- INSERT --")
	b.s.Start(b.conf, nil, 0)
	prev := modeInsert
	m := b.enter(prev)
	for {
		end, next, err := m.Run()
		if err != nil {
			return nil, err
		}
		var msg string
		if !end && next == modeInsert {
			msg = "-- INSERT --"
		}
		if !end && next == modeReplace {
			msg = "-- REPLACE --"
		}
		b.s.SetLastLine(msg)
		b.s.Refresh(b.conf, m.Runes(), m.Position())
		if end {
			return m.Runes(), nil
		}
		if prev != next {
			m = b.enter(next)
		}
		prev = next
	}
}

func (b *balancer) enter(m mode) moder {
	switch m {
	case modeInsert:
		return &insert{
			streamSet: streamSet{
				in:  b.in,
				out: b.out,
				err: b.err,
			},
			editor: b.editor,
			s:      b.s,
			conf:   b.conf,
		}
	case modeNormal:
		return &normal{
			streamSet: streamSet{
				in:  b.in,
				out: b.out,
				err: b.err,
			},
			editor: b.editor,
		}
	case modeReplace:
		buf := b.buf
		b.buf = nil
		return &insert{
			streamSet:   b.streamSet,
			editor:      b.editor,
			replaceMode: true,
			replacedBuf: buf,
		}
	}
	return &insert{streamSet: b.streamSet}
}

func (b *balancer) Clear() {
	b.buf = b.buf[:0]
	b.pos = 0
}

func (b *balancer) SetHistory(history [][]rune) {
	// copy history
	b.history = make([][]rune, len(history))
	for i, h := range history {
		b.history[i] = make([]rune, len(h))
		copy(b.history[i], h)
	}
	b.age = len(history)
}

const (
	mchar = iota
	mline
)
<commit_msg>Simplify structure literal<commit_after>package editor

import (
	"bufio"
	"context"
	"io"

	"github.com/elpinal/coco3/config"
	"github.com/elpinal/coco3/screen"
)

type Editor interface {
	Read() ([]rune, error)
	Clear()
	SetHistory([][]rune)
}

func New(s screen.Screen, conf *config.Config, in io.Reader, out, err io.Writer) Editor {
	return NewContext(context.Background(), s, conf, in, out, err)
}

func NewContext(ctx context.Context, s screen.Screen, conf *config.Config, in io.Reader, out, err io.Writer) Editor {
	var rd io.RuneReader
	if x, ok := in.(io.RuneReader); ok {
		rd = x
	} else {
		rd = bufio.NewReaderSize(in, 64)
	}
	r := NewReaderContext(ctx, rd)
	return &balancer{
		streamSet: streamSet{
			in:  r,
			out: out,
			err: err,
		},
		editor: &editor{undoTree: newUndoTree()},
		s:      s,
		conf:   conf,
	}
}

type streamSet struct {
	in  *RuneAddReader
	out io.Writer
	err io.Writer
}

type balancer struct {
	streamSet
	*editor
	s    screen.Screen
	conf *config.Config
}

func (b *balancer) Read() ([]rune, error) {
	b.s.SetLastLine("-- INSERT --")
	b.s.Start(b.conf, nil, 0)
	prev := modeInsert
	m := b.enter(prev)
	for {
		end, next, err := m.Run()
		if err != nil {
			return nil, err
		}
		var msg string
		if !end && next == modeInsert {
			msg = "-- INSERT --"
		}
		if !end && next == modeReplace {
			msg = "-- REPLACE --"
		}
		b.s.SetLastLine(msg)
		b.s.Refresh(b.conf, m.Runes(), m.Position())
		if end {
			return m.Runes(), nil
		}
		if prev != next {
			m = b.enter(next)
		}
		prev = next
	}
}

func (b *balancer) enter(m mode) moder {
	switch m {
	case modeInsert:
		return &insert{
			streamSet: b.streamSet,
			editor:    b.editor,
			s:         b.s,
			conf:      b.conf,
		}
	case modeNormal:
		return &normal{
			streamSet: b.streamSet,
			editor:    b.editor,
		}
	case modeReplace:
		buf := b.buf
		b.buf = nil
		return &insert{
			streamSet:   b.streamSet,
			editor:      b.editor,
			replaceMode: true,
			replacedBuf: buf,
		}
	}
	return &insert{streamSet: b.streamSet}
}

func (b *balancer) Clear() {
	b.buf = b.buf[:0]
	b.pos = 0
}

func (b *balancer) SetHistory(history [][]rune) {
	// copy history
	b.history = make([][]rune, len(history))
	for i, h := range history {
		b.history[i] = make([]rune, len(h))
		copy(b.history[i], h)
	}
	b.age = len(history)
}

const (
	mchar = iota
	mline
)
<|endoftext|>


<commit_before>package jar

func init() {

}
<commit_msg>implement native method: JarFile. getMetaInfEntryNames()<commit_after>package jar

import (
	. "jvmgo/any"
	"jvmgo/jvm/rtda"
	rtc "jvmgo/jvm/rtda/class"
)

func init() {
	_jf(getMetaInfEntryNames, "getMetaInfEntryNames", "()[Ljava/lang/String;")
}

func _jf(method Any, name, desc string) {
	rtc.RegisterNativeMethod("java/util/jar/JarFile", name, desc, method)
}

// private native String[] getMetaInfEntryNames();
// ()[Ljava/lang/String;
func getMetaInfEntryNames(frame *rtda.Frame) {
	// todo
	stack := frame.OperandStack()
	stack.PushNull()
}
<|endoftext|>


<commit_before>package maas

import (
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/log"
)

type maasEnvironProvider struct{}

var _ environs.EnvironProvider = (*maasEnvironProvider)(nil)

func (*maasEnvironProvider) Open(cfg *config.Config) (environs.Environ, error) {
	log.Printf("environs/maas: opening environment %q.", cfg.Name())
	env := new(maasEnviron)
	err := env.SetConfig(cfg)
	if err != nil {
		return nil, err
	}
	return env, nil
}

func (*maasEnvironProvider) Validate(cfg, old *config.Config) (*config.Config, error) {
	panic("Not implemented")
}

func (*maasEnvironProvider) SecretAttrs(*config.Config) (map[string]interface{}, error) {
	panic("Not implemented")
}

func (*maasEnvironProvider) PublicAddress() (string, error) {
	panic("Not implemented")
}

func (*maasEnvironProvider) PrivateAddress() (string, error) {
	panic("Not implemented")
}
<commit_msg>Trivial EnvironProvider.Validate().<commit_after>package maas

import (
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/log"
)

type maasEnvironProvider struct{}

var _ environs.EnvironProvider = (*maasEnvironProvider)(nil)

func (*maasEnvironProvider) Open(cfg *config.Config) (environs.Environ, error) {
	log.Printf("environs/maas: opening environment %q.", cfg.Name())
	env := new(maasEnviron)
	err := env.SetConfig(cfg)
	if err != nil {
		return nil, err
	}
	return env, nil
}

func (*maasEnvironProvider) Validate(cfg, old *config.Config) (*config.Config, error) {
	return cfg, nil
}

func (*maasEnvironProvider) SecretAttrs(*config.Config) (map[string]interface{}, error) {
	panic("Not implemented")
}

func (*maasEnvironProvider) PublicAddress() (string, error) {
	panic("Not implemented")
}

func (*maasEnvironProvider) PrivateAddress() (string, error) {
	panic("Not implemented")
}
<|endoftext|>


<commit_before>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Build toolchain using Go 1.4.
//
// The general strategy is to copy the source files we need into
// a new GOPATH workspace, adjust import paths appropriately,
// invoke the Go 1.4 go command to build those sources,
// and then copy the binaries back.

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

// bootstrapDirs is a list of directories holding code that must be
// compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
// All directories in this list are relative to and must be below $GOROOT/src.
//
// The list has have two kinds of entries: names beginning with cmd/ with
// no other slashes, which are commands, and other paths, which are packages
// supporting the commands. Packages in the standard library can be listed
// if a newer copy needs to be substituted for the Go 1.4 copy when used
// by the command packages.
// These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big.
var bootstrapDirs = []string{
	"cmd/asm",
	"cmd/asm/internal/arch",
	"cmd/asm/internal/asm",
	"cmd/asm/internal/flags",
	"cmd/asm/internal/lex",
	"cmd/compile",
	"cmd/compile/internal/amd64",
	"cmd/compile/internal/arm",
	"cmd/compile/internal/arm64",
	"cmd/compile/internal/gc",
	"cmd/compile/internal/mips",
	"cmd/compile/internal/mips64",
	"cmd/compile/internal/ppc64",
	"cmd/compile/internal/types",
	"cmd/compile/internal/s390x",
	"cmd/compile/internal/ssa",
	"cmd/compile/internal/syntax",
	"cmd/compile/internal/x86",
	"cmd/internal/bio",
	"cmd/internal/gcprog",
	"cmd/internal/dwarf",
	"cmd/internal/objabi",
	"cmd/internal/obj",
	"cmd/internal/obj/arm",
	"cmd/internal/obj/arm64",
	"cmd/internal/obj/mips",
	"cmd/internal/obj/ppc64",
	"cmd/internal/obj/s390x",
	"cmd/internal/obj/x86",
	"cmd/internal/src",
	"cmd/internal/sys",
	"cmd/link",
	"cmd/link/internal/amd64",
	"cmd/link/internal/arm",
	"cmd/link/internal/arm64",
	"cmd/link/internal/ld",
	"cmd/link/internal/mips",
	"cmd/link/internal/mips64",
	"cmd/link/internal/ppc64",
	"cmd/link/internal/s390x",
	"cmd/link/internal/x86",
	"debug/pe",
	"math/big",
	"math/bits",
}

// File prefixes that are ignored by go/build anyway, and cause
// problems with editor generated temporary files (#18931).
var ignorePrefixes = []string{
	".",
	"_",
}

// File suffixes that use build tags introduced since Go 1.4.
// These must not be copied into the bootstrap build directory.
var ignoreSuffixes = []string{
	"_arm64.s",
	"_arm64.go",
}

func bootstrapBuildTools() {
	goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
	if goroot_bootstrap == "" {
		goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
	}
	xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap)

	mkzbootstrap(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))

	// Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
	// We use a subdirectory of $GOROOT/pkg because that's the
	// space within $GOROOT where we store all generated objects.
	// We could use a temporary directory outside $GOROOT instead,
	// but it is easier to debug on failure if the files are in a known location.
	workspace := pathf("%s/pkg/bootstrap", goroot)
	xremoveall(workspace)
	base := pathf("%s/src/bootstrap", workspace)
	xmkdirall(base)

	// Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
	for _, dir := range bootstrapDirs {
		src := pathf("%s/src/%s", goroot, dir)
		dst := pathf("%s/%s", base, dir)
		xmkdirall(dst)
	Dir:
		for _, name := range xreaddirfiles(src) {
			for _, pre := range ignorePrefixes {
				if strings.HasPrefix(name, pre) {
					continue Dir
				}
			}
			for _, suf := range ignoreSuffixes {
				if strings.HasSuffix(name, suf) {
					continue Dir
				}
			}
			srcFile := pathf("%s/%s", src, name)
			dstFile := pathf("%s/%s", dst, name)
			text := readfile(srcFile)
			text = bootstrapRewriteFile(text, srcFile)
			writefile(text, dstFile, 0)
		}
	}

	// Set up environment for invoking Go 1.4 go command.
	// GOROOT points at Go 1.4 GOROOT,
	// GOPATH points at our bootstrap workspace,
	// GOBIN is empty, so that binaries are installed to GOPATH/bin,
	// and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty,
	// so that Go 1.4 builds whatever kind of binary it knows how to build.
	// Restore GOROOT, GOPATH, and GOBIN when done.
	// Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH,
	// because setup will take care of those when bootstrapBuildTools returns.

	defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
	os.Setenv("GOROOT", goroot_bootstrap)

	defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
	os.Setenv("GOPATH", workspace)

	defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
	os.Setenv("GOBIN", "")

	os.Setenv("GOOS", "")
	os.Setenv("GOHOSTOS", "")
	os.Setenv("GOARCH", "")
	os.Setenv("GOHOSTARCH", "")

	// Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to
	// workaround bugs in Go 1.4's compiler. See discussion thread:
	// https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ
	// Use the math_big_pure_go build tag to disable the assembly in math/big
	// which may contain unsupported instructions.
	cmd := []string{
		pathf("%s/bin/go", goroot_bootstrap),
		"install",
		"-gcflags=-l",
		"-tags=math_big_pure_go",
		"-v",
	}
	if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" {
		cmd = append(cmd, "-toolexec="+tool)
	}
	cmd = append(cmd, "bootstrap/cmd/...")
	run(workspace, ShowOutput|CheckExit, cmd...)

	// Copy binaries into tool binary directory.
	for _, name := range bootstrapDirs {
		if !strings.HasPrefix(name, "cmd/") {
			continue
		}
		name = name[len("cmd/"):]
		if !strings.Contains(name, "/") {
			copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
		}
	}

	xprintf("\n")
}

var ssaRewriteFileSubstring = filepath.ToSlash("src/cmd/compile/internal/ssa/rewrite")

// isUnneededSSARewriteFile reports whether srcFile is a
// src/cmd/compile/internal/ssa/rewriteARCHNAME.go file for an
// architecture that isn't for the current runtime.GOARCH.
//
// When unneeded is true archCaps is the rewrite base filename without
// the "rewrite" prefix or ".go" suffix: AMD64, 386, ARM, ARM64, etc.
func isUnneededSSARewriteFile(srcFile string) (archCaps string, unneeded bool) {
	if !strings.Contains(srcFile, ssaRewriteFileSubstring) {
		return "", false
	}
	fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go")
	if fileArch == "" {
		return "", false
	}
	b := fileArch[0]
	if b == '_' || ('a' <= b && b <= 'z') {
		return "", false
	}
	archCaps = fileArch
	fileArch = strings.ToLower(fileArch)
	if fileArch == strings.TrimSuffix(runtime.GOARCH, "le") {
		return "", false
	}
	if fileArch == strings.TrimSuffix(os.Getenv("GOARCH"), "le") {
		return "", false
	}
	return archCaps, true
}

func bootstrapRewriteFile(text, srcFile string) string {
	// During bootstrap, generate dummy rewrite files for
	// irrelevant architectures. We only need to build a bootstrap
	// binary that works for the current runtime.GOARCH.
	// This saves 6+ seconds of bootstrap.
	if archCaps, ok := isUnneededSSARewriteFile(srcFile); ok {
		return fmt.Sprintf(`package ssa

func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") }
func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") }
`, archCaps, archCaps)
	}

	return bootstrapFixImports(text, srcFile)
}

func bootstrapFixImports(text, srcFile string) string {
	lines := strings.SplitAfter(text, "\n")
	inBlock := false
	for i, line := range lines {
		if strings.HasPrefix(line, "import (") {
			inBlock = true
			continue
		}
		if inBlock && strings.HasPrefix(line, ")") {
			inBlock = false
			continue
		}
		if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
			inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
			line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
			for _, dir := range bootstrapDirs {
				if strings.HasPrefix(dir, "cmd/") {
					continue
				}
				line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
			}
			lines[i] = line
		}
	}

	lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]

	return strings.Join(lines, "")
}
<commit_msg>cmd/dist: unleash bootstrap optimization for windows<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Build toolchain using Go 1.4.
//
// The general strategy is to copy the source files we need into
// a new GOPATH workspace, adjust import paths appropriately,
// invoke the Go 1.4 go command to build those sources,
// and then copy the binaries back.

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

// bootstrapDirs is a list of directories holding code that must be
// compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
// All directories in this list are relative to and must be below $GOROOT/src.
//
// The list has have two kinds of entries: names beginning with cmd/ with
// no other slashes, which are commands, and other paths, which are packages
// supporting the commands. Packages in the standard library can be listed
// if a newer copy needs to be substituted for the Go 1.4 copy when used
// by the command packages.
// These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big.
var bootstrapDirs = []string{
	"cmd/asm",
	"cmd/asm/internal/arch",
	"cmd/asm/internal/asm",
	"cmd/asm/internal/flags",
	"cmd/asm/internal/lex",
	"cmd/compile",
	"cmd/compile/internal/amd64",
	"cmd/compile/internal/arm",
	"cmd/compile/internal/arm64",
	"cmd/compile/internal/gc",
	"cmd/compile/internal/mips",
	"cmd/compile/internal/mips64",
	"cmd/compile/internal/ppc64",
	"cmd/compile/internal/types",
	"cmd/compile/internal/s390x",
	"cmd/compile/internal/ssa",
	"cmd/compile/internal/syntax",
	"cmd/compile/internal/x86",
	"cmd/internal/bio",
	"cmd/internal/gcprog",
	"cmd/internal/dwarf",
	"cmd/internal/objabi",
	"cmd/internal/obj",
	"cmd/internal/obj/arm",
	"cmd/internal/obj/arm64",
	"cmd/internal/obj/mips",
	"cmd/internal/obj/ppc64",
	"cmd/internal/obj/s390x",
	"cmd/internal/obj/x86",
	"cmd/internal/src",
	"cmd/internal/sys",
	"cmd/link",
	"cmd/link/internal/amd64",
	"cmd/link/internal/arm",
	"cmd/link/internal/arm64",
	"cmd/link/internal/ld",
	"cmd/link/internal/mips",
	"cmd/link/internal/mips64",
	"cmd/link/internal/ppc64",
	"cmd/link/internal/s390x",
	"cmd/link/internal/x86",
	"debug/pe",
	"math/big",
	"math/bits",
}

// File prefixes that are ignored by go/build anyway, and cause
// problems with editor generated temporary files (#18931).
var ignorePrefixes = []string{
	".",
	"_",
}

// File suffixes that use build tags introduced since Go 1.4.
// These must not be copied into the bootstrap build directory.
var ignoreSuffixes = []string{
	"_arm64.s",
	"_arm64.go",
}

func bootstrapBuildTools() {
	goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
	if goroot_bootstrap == "" {
		goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
	}
	xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap)

	mkzbootstrap(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))

	// Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
	// We use a subdirectory of $GOROOT/pkg because that's the
	// space within $GOROOT where we store all generated objects.
	// We could use a temporary directory outside $GOROOT instead,
	// but it is easier to debug on failure if the files are in a known location.
	workspace := pathf("%s/pkg/bootstrap", goroot)
	xremoveall(workspace)
	base := pathf("%s/src/bootstrap", workspace)
	xmkdirall(base)

	// Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
	for _, dir := range bootstrapDirs {
		src := pathf("%s/src/%s", goroot, dir)
		dst := pathf("%s/%s", base, dir)
		xmkdirall(dst)
	Dir:
		for _, name := range xreaddirfiles(src) {
			for _, pre := range ignorePrefixes {
				if strings.HasPrefix(name, pre) {
					continue Dir
				}
			}
			for _, suf := range ignoreSuffixes {
				if strings.HasSuffix(name, suf) {
					continue Dir
				}
			}
			srcFile := pathf("%s/%s", src, name)
			dstFile := pathf("%s/%s", dst, name)
			text := readfile(srcFile)
			text = bootstrapRewriteFile(text, srcFile)
			writefile(text, dstFile, 0)
		}
	}

	// Set up environment for invoking Go 1.4 go command.
	// GOROOT points at Go 1.4 GOROOT,
	// GOPATH points at our bootstrap workspace,
	// GOBIN is empty, so that binaries are installed to GOPATH/bin,
	// and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty,
	// so that Go 1.4 builds whatever kind of binary it knows how to build.
	// Restore GOROOT, GOPATH, and GOBIN when done.
	// Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH,
	// because setup will take care of those when bootstrapBuildTools returns.

	defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
	os.Setenv("GOROOT", goroot_bootstrap)

	defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
	os.Setenv("GOPATH", workspace)

	defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
	os.Setenv("GOBIN", "")

	os.Setenv("GOOS", "")
	os.Setenv("GOHOSTOS", "")
	os.Setenv("GOARCH", "")
	os.Setenv("GOHOSTARCH", "")

	// Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to
	// workaround bugs in Go 1.4's compiler. See discussion thread:
	// https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ
	// Use the math_big_pure_go build tag to disable the assembly in math/big
	// which may contain unsupported instructions.
	cmd := []string{
		pathf("%s/bin/go", goroot_bootstrap),
		"install",
		"-gcflags=-l",
		"-tags=math_big_pure_go",
		"-v",
	}
	if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" {
		cmd = append(cmd, "-toolexec="+tool)
	}
	cmd = append(cmd, "bootstrap/cmd/...")
	run(workspace, ShowOutput|CheckExit, cmd...)

	// Copy binaries into tool binary directory.
	for _, name := range bootstrapDirs {
		if !strings.HasPrefix(name, "cmd/") {
			continue
		}
		name = name[len("cmd/"):]
		if !strings.Contains(name, "/") {
			copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
		}
	}

	xprintf("\n")
}

var ssaRewriteFileSubstring = filepath.FromSlash("src/cmd/compile/internal/ssa/rewrite")

// isUnneededSSARewriteFile reports whether srcFile is a
// src/cmd/compile/internal/ssa/rewriteARCHNAME.go file for an
// architecture that isn't for the current runtime.GOARCH.
//
// When unneeded is true archCaps is the rewrite base filename without
// the "rewrite" prefix or ".go" suffix: AMD64, 386, ARM, ARM64, etc.
func isUnneededSSARewriteFile(srcFile string) (archCaps string, unneeded bool) {
	if !strings.Contains(srcFile, ssaRewriteFileSubstring) {
		return "", false
	}
	fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go")
	if fileArch == "" {
		return "", false
	}
	b := fileArch[0]
	if b == '_' || ('a' <= b && b <= 'z') {
		return "", false
	}
	archCaps = fileArch
	fileArch = strings.ToLower(fileArch)
	if fileArch == strings.TrimSuffix(runtime.GOARCH, "le") {
		return "", false
	}
	if fileArch == strings.TrimSuffix(os.Getenv("GOARCH"), "le") {
		return "", false
	}
	return archCaps, true
}

func bootstrapRewriteFile(text, srcFile string) string {
	// During bootstrap, generate dummy rewrite files for
	// irrelevant architectures. We only need to build a bootstrap
	// binary that works for the current runtime.GOARCH.
	// This saves 6+ seconds of bootstrap.
	if archCaps, ok := isUnneededSSARewriteFile(srcFile); ok {
		return fmt.Sprintf(`package ssa

func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") }
func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") }
`, archCaps, archCaps)
	}

	return bootstrapFixImports(text, srcFile)
}

func bootstrapFixImports(text, srcFile string) string {
	lines := strings.SplitAfter(text, "\n")
	inBlock := false
	for i, line := range lines {
		if strings.HasPrefix(line, "import (") {
			inBlock = true
			continue
		}
		if inBlock && strings.HasPrefix(line, ")") {
			inBlock = false
			continue
		}
		if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
			inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
			line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
			for _, dir := range bootstrapDirs {
				if strings.HasPrefix(dir, "cmd/") {
					continue
				}
				line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
			}
			lines[i] = line
		}
	}

	lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]

	return strings.Join(lines, "")
}
<|endoftext|>


<commit_before>// Package packaged provided access to configuration embedded directly in Lantern installation
// packages. On OSX, that means data embedded in the Lantern.app app bundle in
// Lantern.app/Contents/Resources/.lantern.yaml, while on Windows that means data embedded
// in AppData/Roaming/Lantern/.lantern.yaml. This allows customization embedded in the
// installer outside of the auto-updated binary that should only be used under special
// circumstances.
package packaged

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/getlantern/appdir"
	"github.com/getlantern/golog"
	"github.com/getlantern/yaml"
)

var (
	log  = golog.LoggerFor("flashlight.packaged")
	name = ".packaged-lantern.yaml"

	// In almost all cases this will be blank, but as a one-time workaround for
	// https://github.com/getlantern/lantern/issues/2857 it is hard-coded
	// to the manoto facebook page at https://www.facebook.com/manototv for a
	// single binary (lantern-2.0.0-beta9+manoto)
	url = "https://www.facebook.com/manototv"

	// This is the local copy of our embedded configuration file. This is necessary
	// to ensure we remember the embedded configuration across auto-updated
	// binaries. We write to the local file system instead of to the package
	// itself (app bundle on OSX, install directory on Windows) because
	// we're not always sure we can write to that directory.
	local = appdir.General("Lantern") + "/" + name
)

// PackagedSettings provided access to configuration embedded in the package.
type PackagedSettings struct {
	StartupUrl string
}

// ReadSettings reads packaged settings from pre-determined paths
// on the various OSes.
func ReadSettings() (string, *PackagedSettings, error) {
	yamlPath, err := packagedSettingsPath()
	if err != nil {
		return "", &PackagedSettings{}, err
	}

	path, ps, er := readSettingsFromFile(yamlPath)
	if er != nil {
		return readSettingsFromFile(local)
	}
	return path, ps, nil
}

// ReadSettingsFromFile reads PackagedSettings from the yaml file at the specified
// path.
func readSettingsFromFile(yamlPath string) (string, *PackagedSettings, error) {
	if url != "" {
		log.Debugf("Startup URL is hard-coded to: %v", url)
		ps := &PackagedSettings{StartupUrl: url}

		// If there is an embedded URL, it's a temporary workaround for this issue:
		// https://github.com/getlantern/lantern/issues/2857
		// As such, we need to store it to disk so that subsequent binaries that
		// are auto-updated will get the new version.
		path, err := writeToDisk(ps)
		if err == nil {
			return path, ps, nil
		}
		return path, nil, err
	}

	log.Debugf("Opening file at: %v", yamlPath)
	data, err := ioutil.ReadFile(yamlPath)
	if err != nil {
		log.Errorf("Error reading file %v", err)
		return "", &PackagedSettings{}, err
	}

	trimmed := strings.TrimSpace(string(data))

	log.Debugf("Read bytes: %v", trimmed)

	if trimmed == "" {
		log.Debugf("Ignoring empty string")
		return "", &PackagedSettings{}, errors.New("Empty string")
	}
	var s PackagedSettings
	err = yaml.Unmarshal([]byte(trimmed), &s)

	if err != nil {
		log.Errorf("Could not read yaml: %v", err)
		return "", &PackagedSettings{}, err
	}
	return yamlPath, &s, nil
}

func packagedSettingsPath() (string, error) {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Errorf("Could not get current directory %v", err)
		return "", err
	}
	log.Debugf("Opening externalUrl from: %v", dir)
	var yamldir string
	if runtime.GOOS == "windows" {
		yamldir = dir
	} else if runtime.GOOS == "darwin" {
		// Code signing doesn't like this file in the current directory
		// for whatever reason, so we grab it from the Resources
		// directory in the app bundle.
		yamldir = dir + "/../Resources"
	} else if runtime.GOOS == "linux" {
		yamldir = dir
	}
	yamlPath := yamldir + "/" + name
	return yamlPath, nil
}

func writeToDisk(ps *PackagedSettings) (string, error) {
	data, err := yaml.Marshal(ps)
	if err != nil {
		log.Errorf("Could not write to disk: %v", err)
		return "", err
	}
	err = ioutil.WriteFile(local, data, 0644)
	if err != nil {
		log.Errorf("Could not write to disk: %v", err)
		return "", err
	}
	return local, nil
}
<commit_msg>Removing hard coded manoto<commit_after>// Package packaged provided access to configuration embedded directly in Lantern installation
// packages. On OSX, that means data embedded in the Lantern.app app bundle in
// Lantern.app/Contents/Resources/.lantern.yaml, while on Windows that means data embedded
// in AppData/Roaming/Lantern/.lantern.yaml. This allows customization embedded in the
// installer outside of the auto-updated binary that should only be used under special
// circumstances.
package packaged

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/getlantern/appdir"
	"github.com/getlantern/golog"
	"github.com/getlantern/yaml"
)

var (
	log  = golog.LoggerFor("flashlight.packaged")
	name = ".packaged-lantern.yaml"

	// In almost all cases this will be blank, but as a one-time workaround for
	// https://github.com/getlantern/lantern/issues/2857 it is hard-coded
	// to the manoto facebook page at https://www.facebook.com/manototv for a
	// single binary (lantern-2.0.0-beta9+manoto)
	url = ""

	// This is the local copy of our embedded configuration file. This is necessary
	// to ensure we remember the embedded configuration across auto-updated
	// binaries. We write to the local file system instead of to the package
	// itself (app bundle on OSX, install directory on Windows) because
	// we're not always sure we can write to that directory.
	local = appdir.General("Lantern") + "/" + name
)

// PackagedSettings provided access to configuration embedded in the package.
type PackagedSettings struct {
	StartupUrl string
}

// ReadSettings reads packaged settings from pre-determined paths
// on the various OSes.
func ReadSettings() (string, *PackagedSettings, error) {
	yamlPath, err := packagedSettingsPath()
	if err != nil {
		return "", &PackagedSettings{}, err
	}

	path, ps, er := readSettingsFromFile(yamlPath)
	if er != nil {
		return readSettingsFromFile(local)
	}
	return path, ps, nil
}

// ReadSettingsFromFile reads PackagedSettings from the yaml file at the specified
// path.
func readSettingsFromFile(yamlPath string) (string, *PackagedSettings, error) {
	if url != "" {
		log.Debugf("Startup URL is hard-coded to: %v", url)
		ps := &PackagedSettings{StartupUrl: url}

		// If there is an embedded URL, it's a temporary workaround for this issue:
		// https://github.com/getlantern/lantern/issues/2857
		// As such, we need to store it to disk so that subsequent binaries that
		// are auto-updated will get the new version.
		path, err := writeToDisk(ps)
		if err == nil {
			return path, ps, nil
		}
		return path, nil, err
	}

	log.Debugf("Opening file at: %v", yamlPath)
	data, err := ioutil.ReadFile(yamlPath)
	if err != nil {
		log.Errorf("Error reading file %v", err)
		return "", &PackagedSettings{}, err
	}

	trimmed := strings.TrimSpace(string(data))

	log.Debugf("Read bytes: %v", trimmed)

	if trimmed == "" {
		log.Debugf("Ignoring empty string")
		return "", &PackagedSettings{}, errors.New("Empty string")
	}
	var s PackagedSettings
	err = yaml.Unmarshal([]byte(trimmed), &s)

	if err != nil {
		log.Errorf("Could not read yaml: %v", err)
		return "", &PackagedSettings{}, err
	}
	return yamlPath, &s, nil
}

func packagedSettingsPath() (string, error) {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Errorf("Could not get current directory %v", err)
		return "", err
	}
	log.Debugf("Opening externalUrl from: %v", dir)
	var yamldir string
	if runtime.GOOS == "windows" {
		yamldir = dir
	} else if runtime.GOOS == "darwin" {
		// Code signing doesn't like this file in the current directory
		// for whatever reason, so we grab it from the Resources
		// directory in the app bundle.
		yamldir = dir + "/../Resources"
	} else if runtime.GOOS == "linux" {
		yamldir = dir
	}
	yamlPath := yamldir + "/" + name
	return yamlPath, nil
}

func writeToDisk(ps *PackagedSettings) (string, error) {
	data, err := yaml.Marshal(ps)
	if err != nil {
		log.Errorf("Could not write to disk: %v", err)
		return "", err
	}
	err = ioutil.WriteFile(local, data, 0644)
	if err != nil {
		log.Errorf("Could not write to disk: %v", err)
		return "", err
	}
	return local, nil
}
<|endoftext|>


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

import (
	"reflect"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/openconfig/goyang/pkg/yang"
)

func protoMsgEq(a, b protoMsg) bool {
	if a.Name != b.Name {
		return false
	}

	if a.YANGPath != b.YANGPath {
		return false
	}

	// Avoid flakes by comparing the fields in an unordered data structure.
	fieldMap := func(s []*protoMsgField) map[string]*protoMsgField {
		e := map[string]*protoMsgField{}
		for _, m := range s {
			e[m.Name] = m
		}
		return e
	}

	if !reflect.DeepEqual(fieldMap(a.Fields), fieldMap(b.Fields)) {
		return false
	}

	return true
}

func TestGenProtoMsg(t *testing.T) {
	tests := []struct {
		name                string
		inMsg               *yangStruct
		inMsgs              map[string]*yangStruct
		inUniqueStructNames map[string]string
		wantMsg             protoMsg
		wantErr             bool
	}{{
		name: "simple message with only scalar fields",
		inMsg: &yangStruct{
			name: "MessageName",
			entry: &yang.Entry{
				Name: "message-name",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"field-one": {
					Name: "field-one",
					Type: &yang.YangType{Kind: yang.Ystring},
				},
				"field-two": {
					Name: "field-two",
					Type: &yang.YangType{Kind: yang.Yint8},
				},
			},
			path: []string{"", "root", "message-name"},
		},
		wantMsg: protoMsg{
			Name:     "MessageName",
			YANGPath: "/root/message-name",
			Fields: []*protoMsgField{{
				Tag:  1,
				Name: "field_one",
				Type: "ywrapper.StringValue",
			}, {
				Tag:  1,
				Name: "field_two",
				Type: "ywrapper.IntValue",
			}},
		},
	}, {
		name: "simple message with leaf-list and a message child",
		inMsg: &yangStruct{
			name: "AMessage",
			entry: &yang.Entry{
				Name: "a-message",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"leaf-list": {
					Name:     "leaf-list",
					Type:     &yang.YangType{Kind: yang.Ystring},
					ListAttr: &yang.ListAttr{},
				},
				"container-child": {
					Name: "container-child",
					Dir:  map[string]*yang.Entry{},
					Parent: &yang.Entry{
						Name: "a-message",
						Parent: &yang.Entry{
							Name: "root",
						},
					},
				},
			},
			path: []string{"", "root", "a-message"},
		},
		inUniqueStructNames: map[string]string{
			"/root/a-message/container-child": "ContainerChild",
		},
		wantMsg: protoMsg{
			Name:     "AMessage",
			YANGPath: "/root/a-message",
			Fields: []*protoMsgField{{
				Tag:        1,
				Name:       "leaf_list",
				Type:       "ywrapper.StringValue",
				IsRepeated: true,
			}, {
				Tag:  1,
				Name: "container_child",
				Type: "ContainerChild",
			}},
		},
	}, {
		name: "message with unimplemented list",
		inMsg: &yangStruct{
			name: "AMessageWithAList",
			entry: &yang.Entry{
				Name: "a-message-with-a-list",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"list": {
					Name: "list",
					Dir: map[string]*yang.Entry{
						"key": {
							Name: "key",
							Type: &yang.YangType{Kind: yang.Ystring},
						},
					},
					Key: "key",
				},
			},
			path: []string{"", "a-messsage-with-a-list", "list"},
		},
		wantErr: true,
	}}

	for _, tt := range tests {
		s := newGenState()
		// Seed the state with the supplied message names that have been provided.
		s.uniqueStructNames = tt.inUniqueStructNames

		got, errs := genProtoMsg(tt.inMsg, tt.inMsgs, s)
		if (len(errs) > 0) != tt.wantErr {
			t.Errorf("%s: genProtoMsg(%#v, %#v, *genState): did not get expected error status, got: %v, wanted err: %v", tt.name, tt.inMsg, tt.inMsgs, errs, tt.wantErr)
		}

		if tt.wantErr {
			continue
		}

		if !protoMsgEq(got, tt.wantMsg) {
			diff := pretty.Compare(got, tt.wantMsg)
			t.Errorf("%s: genProtoMsg(%#v, %#v, *genState): did not get expected protobuf message definition, diff(-got,+want):\n%s", tt.name, tt.inMsg, tt.inMsgs, diff)
		}
	}
}

func TestSafeProtoName(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want string
	}{{
		name: "contains hyphen",
		in:   "with-hyphen",
		want: "with_hyphen",
	}, {
		name: "contains period",
		in:   "with.period",
		want: "with_period",
	}, {
		name: "unchanged",
		in:   "unchanged",
		want: "unchanged",
	}}

	for _, tt := range tests {
		if got := safeProtoFieldName(tt.in); got != tt.want {
			t.Errorf("%s: safeProtoFieldName(%s): did not get expected name, got: %v, want: %v", tt.name, tt.in, got, tt.want)
		}
	}
}
<commit_msg>Add unit tests to catch unmapped protobuf types.<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ygen

import (
	"reflect"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/openconfig/goyang/pkg/yang"
)

func protoMsgEq(a, b protoMsg) bool {
	if a.Name != b.Name {
		return false
	}

	if a.YANGPath != b.YANGPath {
		return false
	}

	// Avoid flakes by comparing the fields in an unordered data structure.
	fieldMap := func(s []*protoMsgField) map[string]*protoMsgField {
		e := map[string]*protoMsgField{}
		for _, m := range s {
			e[m.Name] = m
		}
		return e
	}

	if !reflect.DeepEqual(fieldMap(a.Fields), fieldMap(b.Fields)) {
		return false
	}

	return true
}

func TestGenProtoMsg(t *testing.T) {
	tests := []struct {
		name                string
		inMsg               *yangStruct
		inMsgs              map[string]*yangStruct
		inUniqueStructNames map[string]string
		wantMsg             protoMsg
		wantErr             bool
	}{{
		name: "simple message with only scalar fields",
		inMsg: &yangStruct{
			name: "MessageName",
			entry: &yang.Entry{
				Name: "message-name",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"field-one": {
					Name: "field-one",
					Type: &yang.YangType{Kind: yang.Ystring},
				},
				"field-two": {
					Name: "field-two",
					Type: &yang.YangType{Kind: yang.Yint8},
				},
			},
			path: []string{"", "root", "message-name"},
		},
		wantMsg: protoMsg{
			Name:     "MessageName",
			YANGPath: "/root/message-name",
			Fields: []*protoMsgField{{
				Tag:  1,
				Name: "field_one",
				Type: "ywrapper.StringValue",
			}, {
				Tag:  1,
				Name: "field_two",
				Type: "ywrapper.IntValue",
			}},
		},
	}, {
		name: "simple message with leaf-list and a message child",
		inMsg: &yangStruct{
			name: "AMessage",
			entry: &yang.Entry{
				Name: "a-message",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"leaf-list": {
					Name:     "leaf-list",
					Type:     &yang.YangType{Kind: yang.Ystring},
					ListAttr: &yang.ListAttr{},
				},
				"container-child": {
					Name: "container-child",
					Dir:  map[string]*yang.Entry{},
					Parent: &yang.Entry{
						Name: "a-message",
						Parent: &yang.Entry{
							Name: "root",
						},
					},
				},
			},
			path: []string{"", "root", "a-message"},
		},
		inUniqueStructNames: map[string]string{
			"/root/a-message/container-child": "ContainerChild",
		},
		wantMsg: protoMsg{
			Name:     "AMessage",
			YANGPath: "/root/a-message",
			Fields: []*protoMsgField{{
				Tag:        1,
				Name:       "leaf_list",
				Type:       "ywrapper.StringValue",
				IsRepeated: true,
			}, {
				Tag:  1,
				Name: "container_child",
				Type: "ContainerChild",
			}},
		},
	}, {
		name: "message with unimplemented list",
		inMsg: &yangStruct{
			name: "AMessageWithAList",
			entry: &yang.Entry{
				Name: "a-message-with-a-list",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"list": {
					Name: "list",
					Dir: map[string]*yang.Entry{
						"key": {
							Name: "key",
							Type: &yang.YangType{Kind: yang.Ystring},
						},
					},
					Key: "key",
				},
			},
			path: []string{"", "a-messsage-with-a-list", "list"},
		},
		wantErr: true,
	}, {
		name: "message with an unimplemented mapping",
		inMsg: &yangStruct{
			name: "MessageWithInvalidContents",
			entry: &yang.Entry{
				Name: "message-with-invalid-contents",
				Dir:  map[string]*yang.Entry{},
			},
			fields: map[string]*yang.Entry{
				"unimplemented": {
					Name: "unimplemented",
					Type: &yang.YangType{
						Kind: yang.Yunion,
						Type: []*yang.YangType{
							{Kind: yang.Ybinary},
							{Kind: yang.Yenum},
							{Kind: yang.Ybits},
							{Kind: yang.YinstanceIdentifier},
						},
					},
				},
			},
			path: []string{"", "mesassge-with-invalid-contents", "unimplemented"},
		},
		wantErr: true,
	}}

	for _, tt := range tests {
		s := newGenState()
		// Seed the state with the supplied message names that have been provided.
		s.uniqueStructNames = tt.inUniqueStructNames

		got, errs := genProtoMsg(tt.inMsg, tt.inMsgs, s)
		if (len(errs) > 0) != tt.wantErr {
			t.Errorf("%s: genProtoMsg(%#v, %#v, *genState): did not get expected error status, got: %v, wanted err: %v", tt.name, tt.inMsg, tt.inMsgs, errs, tt.wantErr)
		}

		if tt.wantErr {
			continue
		}

		if !protoMsgEq(got, tt.wantMsg) {
			diff := pretty.Compare(got, tt.wantMsg)
			t.Errorf("%s: genProtoMsg(%#v, %#v, *genState): did not get expected protobuf message definition, diff(-got,+want):\n%s", tt.name, tt.inMsg, tt.inMsgs, diff)
		}
	}
}

func TestSafeProtoName(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want string
	}{{
		name: "contains hyphen",
		in:   "with-hyphen",
		want: "with_hyphen",
	}, {
		name: "contains period",
		in:   "with.period",
		want: "with_period",
	}, {
		name: "unchanged",
		in:   "unchanged",
		want: "unchanged",
	}}

	for _, tt := range tests {
		if got := safeProtoFieldName(tt.in); got != tt.want {
			t.Errorf("%s: safeProtoFieldName(%s): did not get expected name, got: %v, want: %v", tt.name, tt.in, got, tt.want)
		}
	}
}
<|endoftext|>


<commit_before>package users

import (
	"encoding/json"
	"errors"
	"net/http"

	h "github.com/ernestio/api-gateway/helpers"
	"github.com/ernestio/api-gateway/models"
)

// Update : responds to PUT /users/:id: by updating an existing
// user
func Update(au models.User, user string, body []byte) (int, []byte) {
	var u models.User
	var existing models.User

	if err := u.Map(body); err != nil {
		h.L.Error(err.Error())
		return 400, []byte(err.Error())
	}

	err := u.Validate()
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	if u.Username != user {
		return 400, models.NewJSONError("Username does not match payload name")
	}

	// Check if authenticated user is admin or updating itself
	if !u.CanBeChangedBy(au) {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	// Check user exists
	if err := au.FindByUserName(user, &existing); err != nil {
		if err := au.FindByID(user, &existing); err != nil {
			h.L.Error(err.Error())
			return 404, models.NewJSONError("Specified user not found")
		}
	}

	if existing.ID == 0 {
		err := errors.New("Specified user not found")
		h.L.Error(err.Error())
		return 404, models.NewJSONError(err.Error())
	}

	u.Username = existing.Username

	if !au.IsAdmin() && existing.Username != au.Username {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	if !au.IsAdmin() && existing.IsAdmin() != u.IsAdmin() {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	if u.Password != nil {
		err := u.Validate()
		if err != nil {
			return 400, models.NewJSONError(err.Error())
		}

		// Check the old password if it is present
		if u.OldPassword != nil && !existing.ValidPassword(*u.OldPassword) {
			err := errors.New("Provided credentials are not valid")
			h.L.Error(err.Error())
			return 403, models.NewJSONError(err.Error())
		}
	}

	if err := u.Save(); err != nil {
		h.L.Error(err.Error())
		return 500, models.NewJSONError("Error updating user")
	}

	if existing.MFA == nil {
		existing.MFA = h.Bool(false)
	}

	if u.MFA != nil {
		if *u.MFA && !*existing.MFA {
			mfaSecret := u.MFASecret
			u.Redact()
			u.MFASecret = mfaSecret
		} else {
			u.Redact()
		}
	} else {
		u.Redact()
	}

	body, err = json.Marshal(u)
	if err != nil {
		return 500, models.NewJSONError("Internal server error")
	}

	return http.StatusOK, body
}
<commit_msg>checking path matches username or user id<commit_after>package users

import (
	"encoding/json"
	"errors"
	"net/http"
	"strconv"

	h "github.com/ernestio/api-gateway/helpers"
	"github.com/ernestio/api-gateway/models"
)

// Update : responds to PUT /users/:id: by updating an existing
// user
func Update(au models.User, user string, body []byte) (int, []byte) {
	var u models.User
	var existing models.User

	if err := u.Map(body); err != nil {
		h.L.Error(err.Error())
		return 400, []byte(err.Error())
	}

	err := u.Validate()
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	uid, _ := strconv.Atoi(user)

	if u.Username != user && u.ID != uid {
		return 400, models.NewJSONError("User does not match payload name")
	}

	// Check if authenticated user is admin or updating itself
	if !u.CanBeChangedBy(au) {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	// Check user exists
	if err := au.FindByUserName(user, &existing); err != nil {
		if err := au.FindByID(user, &existing); err != nil {
			h.L.Error(err.Error())
			return 404, models.NewJSONError("Specified user not found")
		}
	}

	if existing.ID == 0 {
		err := errors.New("Specified user not found")
		h.L.Error(err.Error())
		return 404, models.NewJSONError(err.Error())
	}

	u.Username = existing.Username

	if !au.IsAdmin() && existing.Username != au.Username {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	if !au.IsAdmin() && existing.IsAdmin() != u.IsAdmin() {
		err := errors.New("You're not allowed to perform this action, please contact your admin")
		h.L.Error(err.Error())
		return 403, models.NewJSONError(err.Error())
	}

	if u.Password != nil {
		err := u.Validate()
		if err != nil {
			return 400, models.NewJSONError(err.Error())
		}

		// Check the old password if it is present
		if u.OldPassword != nil && !existing.ValidPassword(*u.OldPassword) {
			err := errors.New("Provided credentials are not valid")
			h.L.Error(err.Error())
			return 403, models.NewJSONError(err.Error())
		}
	}

	if err := u.Save(); err != nil {
		h.L.Error(err.Error())
		return 500, models.NewJSONError("Error updating user")
	}

	if existing.MFA == nil {
		existing.MFA = h.Bool(false)
	}

	if u.MFA != nil {
		if *u.MFA && !*existing.MFA {
			mfaSecret := u.MFASecret
			u.Redact()
			u.MFASecret = mfaSecret
		} else {
			u.Redact()
		}
	} else {
		u.Redact()
	}

	body, err = json.Marshal(u)
	if err != nil {
		return 500, models.NewJSONError("Internal server error")
	}

	return http.StatusOK, body
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ssm"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSSSMMaintenanceWindowTask_basic(t *testing.T) {
	var task ssm.MaintenanceWindowTask

	name := acctest.RandString(10)
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &task),
				),
			},
		},
	})
}

func TestAccAWSSSMMaintenanceWindowTask_updateForcesNewResource(t *testing.T) {
	var before, after ssm.MaintenanceWindowTask
	name := acctest.RandString(10)
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &before),
				),
			},
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &after),
					testAccCheckAwsSsmWindowsTaskRecreated(t, &before, &after),
				),
			},
		},
	})
}

func testAccCheckAwsSsmWindowsTaskRecreated(t *testing.T,
	before, after *ssm.MaintenanceWindowTask) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if before.WindowTaskId == after.WindowTaskId {
			t.Fatalf("Expected change of Windows Task IDs, but both were %v", before.WindowTaskId)
		}
		return nil
	}
}

func testAccCheckAWSSSMMaintenanceWindowTaskExists(n string, task *ssm.MaintenanceWindowTask) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No SSM Maintenance Window Task Window ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ssmconn

		resp, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
			WindowId: aws.String(rs.Primary.Attributes["window_id"]),
		})
		if err != nil {
			return err
		}

		for _, i := range resp.Tasks {
			if *i.WindowTaskId == rs.Primary.ID {
				*task = *i
				return nil
			}
		}

		return fmt.Errorf("No AWS SSM Maintenance window task found")
	}
}

func testAccCheckAWSSSMMaintenanceWindowTaskDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ssmconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_ssm_maintenance_window_target" {
			continue
		}

		out, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
			WindowId: aws.String(rs.Primary.Attributes["window_id"]),
		})

		if err != nil {
			// Verify the error is what we want
			if ae, ok := err.(awserr.Error); ok && ae.Code() == "DoesNotExistException" {
				continue
			}
			return err
		}

		if len(out.Tasks) > 0 {
			return fmt.Errorf("Expected AWS SSM Maintenance Task to be gone, but was still found")
		}

		return nil
	}

	return nil
}

func testAccAWSSSMMaintenanceWindowTaskBasicConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_ssm_maintenance_window" "foo" {
  name = "maintenance-window-%s"
  schedule = "cron(0 16 ? * TUE *)"
  duration = 3
  cutoff = 1
}

resource "aws_ssm_maintenance_window_task" "target" {
  window_id = "${aws_ssm_maintenance_window.foo.id}"
  task_type = "RUN_COMMAND"
  task_arn = "AWS-RunShellScript"
  priority = 1
  name = "TestMaintenanceWindowTask"
  description = "This ressource is for test purpose only"
  service_role_arn = "${aws_iam_role.ssm_role.arn}"
  max_concurrency = "2"
  max_errors = "1"
  targets {
    key = "InstanceIds"
    values = ["${aws_instance.foo.id}"]
  }
  task_parameters {
    name = "commands"
    values = ["pwd"]
  }
}

resource "aws_instance" "foo" {
  ami = "ami-4fccb37f"

  instance_type = "m1.small"
}

resource "aws_iam_role" "ssm_role" {
  name = "ssm-role-%s"

  assume_role_policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy" "bar" {
  name = "ssm_role_policy_%s"
  role = "${aws_iam_role.ssm_role.name}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "ssm:*",
    "Resource": "*"
  }
}
EOF
}

`, rName, rName, rName)
}

func testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(rName string) string {
	return fmt.Sprintf(`
resource "aws_ssm_maintenance_window" "foo" {
  name = "maintenance-window-%s"
  schedule = "cron(0 16 ? * TUE *)"
  duration = 3
  cutoff = 1
}

resource "aws_ssm_maintenance_window_task" "target" {
  window_id = "${aws_ssm_maintenance_window.foo.id}"
  task_type = "RUN_COMMAND"
  task_arn = "AWS-RunShellScript"
  priority = 1
  name = "TestMaintenanceWindowTask"
  description = "This ressource is for test purpose only"
  service_role_arn = "${aws_iam_role.ssm_role.arn}"
  max_concurrency = "2"
  max_errors = "1"
  targets {
    key = "InstanceIds"
    values = ["${aws_instance.foo.id}"]
  }
  task_parameters {
    name = "commands"
    values = ["date"]
  }
}

resource "aws_instance" "foo" {
  ami = "ami-4fccb37f"

  instance_type = "m1.small"
}

resource "aws_iam_role" "ssm_role" {
  name = "ssm-role-%s"

  assume_role_policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy" "bar" {
  name = "ssm_role_policy_%s"
  role = "${aws_iam_role.ssm_role.name}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "ssm:*",
    "Resource": "*"
  }
}
EOF
}

`, rName, rName, rName)
}
<commit_msg>update acctests to check name and desc exist<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ssm"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSSSMMaintenanceWindowTask_basic(t *testing.T) {
	var task ssm.MaintenanceWindowTask

	name := acctest.RandString(10)
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &task),
					resource.TestCheckResourceAttr("aws_ssm_maintenance_window_task.target", "name", "TestMaintenanceWindowTask"),
					resource.TestCheckResourceAttr("aws_ssm_maintenance_window_task.target", "description", "This ressource is for test purpose only"),
				),
			},
		},
	})
}

func TestAccAWSSSMMaintenanceWindowTask_updateForcesNewResource(t *testing.T) {
	var before, after ssm.MaintenanceWindowTask
	name := acctest.RandString(10)
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &before),
				),
			},
			{
				Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(name),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSSMMaintenanceWindowTaskExists("aws_ssm_maintenance_window_task.target", &after),
					testAccCheckAwsSsmWindowsTaskRecreated(t, &before, &after),
				),
			},
		},
	})
}

func testAccCheckAwsSsmWindowsTaskRecreated(t *testing.T,
	before, after *ssm.MaintenanceWindowTask) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if before.WindowTaskId == after.WindowTaskId {
			t.Fatalf("Expected change of Windows Task IDs, but both were %v", before.WindowTaskId)
		}
		return nil
	}
}

func testAccCheckAWSSSMMaintenanceWindowTaskExists(n string, task *ssm.MaintenanceWindowTask) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No SSM Maintenance Window Task Window ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ssmconn

		resp, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
			WindowId: aws.String(rs.Primary.Attributes["window_id"]),
		})
		if err != nil {
			return err
		}

		for _, i := range resp.Tasks {
			if *i.WindowTaskId == rs.Primary.ID {
				*task = *i
				return nil
			}
		}

		return fmt.Errorf("No AWS SSM Maintenance window task found")
	}
}

func testAccCheckAWSSSMMaintenanceWindowTaskDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ssmconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_ssm_maintenance_window_target" {
			continue
		}

		out, err := conn.DescribeMaintenanceWindowTasks(&ssm.DescribeMaintenanceWindowTasksInput{
			WindowId: aws.String(rs.Primary.Attributes["window_id"]),
		})

		if err != nil {
			// Verify the error is what we want
			if ae, ok := err.(awserr.Error); ok && ae.Code() == "DoesNotExistException" {
				continue
			}
			return err
		}

		if len(out.Tasks) > 0 {
			return fmt.Errorf("Expected AWS SSM Maintenance Task to be gone, but was still found")
		}

		return nil
	}

	return nil
}

func testAccAWSSSMMaintenanceWindowTaskBasicConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_ssm_maintenance_window" "foo" {
  name = "maintenance-window-%s"
  schedule = "cron(0 16 ? * TUE *)"
  duration = 3
  cutoff = 1
}

resource "aws_ssm_maintenance_window_task" "target" {
  window_id = "${aws_ssm_maintenance_window.foo.id}"
  task_type = "RUN_COMMAND"
  task_arn = "AWS-RunShellScript"
  priority = 1
  name = "TestMaintenanceWindowTask"
  description = "This ressource is for test purpose only"
  service_role_arn = "${aws_iam_role.ssm_role.arn}"
  max_concurrency = "2"
  max_errors = "1"
  targets {
    key = "InstanceIds"
    values = ["${aws_instance.foo.id}"]
  }
  task_parameters {
    name = "commands"
    values = ["pwd"]
  }
}

resource "aws_instance" "foo" {
  ami = "ami-4fccb37f"

  instance_type = "m1.small"
}

resource "aws_iam_role" "ssm_role" {
  name = "ssm-role-%s"

  assume_role_policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy" "bar" {
  name = "ssm_role_policy_%s"
  role = "${aws_iam_role.ssm_role.name}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "ssm:*",
    "Resource": "*"
  }
}
EOF
}

`, rName, rName, rName)
}

func testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(rName string) string {
	return fmt.Sprintf(`
resource "aws_ssm_maintenance_window" "foo" {
  name = "maintenance-window-%s"
  schedule = "cron(0 16 ? * TUE *)"
  duration = 3
  cutoff = 1
}

resource "aws_ssm_maintenance_window_task" "target" {
  window_id = "${aws_ssm_maintenance_window.foo.id}"
  task_type = "RUN_COMMAND"
  task_arn = "AWS-RunShellScript"
  priority = 1
  name = "TestMaintenanceWindowTask"
  description = "This ressource is for test purpose only"
  service_role_arn = "${aws_iam_role.ssm_role.arn}"
  max_concurrency = "2"
  max_errors = "1"
  targets {
    key = "InstanceIds"
    values = ["${aws_instance.foo.id}"]
  }
  task_parameters {
    name = "commands"
    values = ["date"]
  }
}

resource "aws_instance" "foo" {
  ami = "ami-4fccb37f"

  instance_type = "m1.small"
}

resource "aws_iam_role" "ssm_role" {
  name = "ssm-role-%s"

  assume_role_policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy" "bar" {
  name = "ssm_role_policy_%s"
  role = "${aws_iam_role.ssm_role.name}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "ssm:*",
    "Resource": "*"
  }
}
EOF
}

`, rName, rName, rName)
}
<|endoftext|>


<commit_before>package keys

type Sequence uint64

const (
	MaxSequence Sequence = (1 << 56) - 1
)

func (seq Sequence) Next(n uint64) Sequence {
	return Sequence(uint64(seq) + n)
}
<commit_msg>Document keys.Sequence<commit_after>package keys

// Sequence is a monotonic value associated with every keys written to LevelDB.
//
// At any time, once a key is written to LevelDB, no matter whether it is a key
// deletion or value setting, it is associated with a Sequence greater than
// Sequences associated to previous written keys.
//
// For this we can conclude:
// * No keys have some Sequence.
// * For key with given Sequence, it is written before keys with bigger
//   Sequences, also it is written after keys with smaller Sequences.
type Sequence uint64

const (
	// MaxSequence is the maximum allowed value for Sequence.
	MaxSequence Sequence = (1 << 56) - 1
)

// Next returns a Sequence which is n greater than this one.
func (seq Sequence) Next(n uint64) Sequence {
	return Sequence(uint64(seq) + n)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/cloudfoundry/cli/plugin"
)

type PluginAutoScaler struct {
}

func (p *PluginAutoScaler) Run(cliConnection plugin.CliConnection, args []string) {
	fmt.Printf("Run autoscaler command: %s \n", args)
}

func (po *PluginAutoScaler) GetMetadata() plugin.PluginMetadata {
	return plugin.PluginMetadata{
		Name: "AutoScaler",
		Version: plugin.VersionType{
			Major: 0,
			Minor: 0,
			Build: 1,
		},
		Commands: []plugin.Command{
			{
				Name: "as-policy",
				Alias: "asp",
				HelpText: "Show the auto-scaling policy of the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-policy APP_NAME [--json]",
					Options: map[string]string{
						"json": "show the policy in json format",
					},
				},
			},
			{
				Name: "as-attach-policy",
				Alias: "asap",
				HelpText: "Attach an auto-scaling policy to the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-attach-policy APP_NAME -p POLICY_FILE",
					Options: map[string]string{
						"p": "the name of the policy file in JSON, if 'policy.json' in the current directory is not used",
					},
				},
			},
			{
				Name: "as-detach-policy",
				Alias: "asdp",
				HelpText: "detach and delete the auto-scaling policy from the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-detach-policy APP_NAME",
				},
			},
			{
				Name: "as-enable-policy",
				Alias: "aseap",
				HelpText: "resume the enforcement of the auto-scaling policy",
				UsageDetails: plugin.Usage{
					Usage: "cf as-enable-policy APP_NAME",
				},
			},
			{
				Name: "as-disable-policy",
				Alias: "asdap",
				HelpText: "suspend the auto-scaling policy temporarily",
				UsageDetails: plugin.Usage{
					Usage: "cf as-disable-policy APP_NAME",
				},
			},
			{
				Name: "as-history",
				Alias: "ash",
				HelpText: "Query the auto-caling history",
				UsageDetails: plugin.Usage{
					Usage: "cf as-history APP_NAME --start-time START --end-time END --json",
					Options: map[string]string{
						"--start-time": "the start time of the query, in format 'yyyy-MM-ddTHH:mm:ss+/-hhmm' or 'yyyy-MM-ddTHH:mm:ssZ'",
						"--end-time": "the end time of the query, in format 'yyyy-MM-ddTHH:mm:ss+/-hhmm' or 'yyyy-MM-ddTHH:mm:ssZ'",
						"--json": "show the history in JSON format",
					},
				},
			},

		},
	}
}<commit_msg>Update plugin.go<commit_after>package main

import (
	"fmt"
	"github.com/cloudfoundry/cli/plugin"
)

type PluginAutoScaler struct {
}

func (p *PluginAutoScaler) Run(cliConnection plugin.CliConnection, args []string) {
	fmt.Printf("Run autoscaler command: %s \n", args)
}

func (po *PluginAutoScaler) GetMetadata() plugin.PluginMetadata {
	return plugin.PluginMetadata{
		Name: "AutoScaler",
		Version: plugin.VersionType{
			Major: 0,
			Minor: 0,
			Build: 1,
		},
		Commands: []plugin.Command{
			{
				Name: "as-policy",
				Alias: "asp",
				HelpText: "Show the auto-scaling policy of the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-policy APP_NAME [--json]",
					Options: map[string]string{
						"json": "show the policy in json format",
					},
				},
			},
			{
				Name: "as-attach-policy",
				Alias: "asap",
				HelpText: "Attach an auto-scaling policy to the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-attach-policy APP_NAME -p POLICY_FILE",
					Options: map[string]string{
						"p": "the name of the policy file in JSON, if 'policy.json' in the current directory is not used",
					},
				},
			},
			{
				Name: "as-detach-policy",
				Alias: "asdp",
				HelpText: "Detach and delete the auto-scaling policy from the application",
				UsageDetails: plugin.Usage{
					Usage: "cf as-detach-policy APP_NAME",
				},
			},
			{
				Name: "as-enable-policy",
				Alias: "aseap",
				HelpText: "Resume the enforcement of the auto-scaling policy",
				UsageDetails: plugin.Usage{
					Usage: "cf as-enable-policy APP_NAME",
				},
			},
			{
				Name: "as-disable-policy",
				Alias: "asdap",
				HelpText: "Suspend the auto-scaling policy temporarily",
				UsageDetails: plugin.Usage{
					Usage: "cf as-disable-policy APP_NAME",
				},
			},
			{
				Name: "as-history",
				Alias: "ash",
				HelpText: "Query the auto-caling history",
				UsageDetails: plugin.Usage{
					Usage: "cf as-history APP_NAME --start-time START --end-time END --json",
					Options: map[string]string{
						"--start-time": "the start time of the query, in format 'yyyy-MM-ddTHH:mm:ss+/-hhmm' or 'yyyy-MM-ddTHH:mm:ssZ'",
						"--end-time": "the end time of the query, in format 'yyyy-MM-ddTHH:mm:ss+/-hhmm' or 'yyyy-MM-ddTHH:mm:ssZ'",
						"--json": "show the history in JSON format",
					},
				},
			},

		},
	}
}
<|endoftext|>


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

package client

import (
	"context"
	"fmt"
	"time"

	"github.com/golang/glog"
	"github.com/google/trillian"
	"github.com/google/trillian/client/backoff"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// CreateAndInitTree uses the adminClient and mapClient to create the tree
// described by req.
// If req describes a MAP tree, then this function will also call the InitMap
// function using mapClient.
// Internally, the function will continue to retry failed requests until either
// the tree is created (and if necessary, initialised) successfully, or ctx is
// cancelled.
func CreateAndInitTree(
	ctx context.Context,
	req *trillian.CreateTreeRequest,
	adminClient trillian.TrillianAdminClient,
	mapClient trillian.TrillianMapClient,
	logClient trillian.TrillianLogClient) (*trillian.Tree, error) {

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	var tree *trillian.Tree
	err := b.Retry(ctx, func() error {
		glog.Info("CreateTree...")
		var err error
		tree, err = adminClient.CreateTree(ctx, req)
		if err != nil {
			if s, ok := status.FromError(err); ok && s.Code() == codes.Unavailable {
				glog.Errorf("Admin server unavailable: %v", err)
				return err
			}
			glog.Errorf("failed to CreateTree(%+v): %T %v", req, err, err)
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	switch tree.TreeType {
	case trillian.TreeType_MAP:
		if err := InitMap(ctx, tree, mapClient); err != nil {
			return nil, err
		}
	case trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG:
		if err := InitLog(ctx, tree, logClient); err != nil {
			return nil, err
		}
	default:
		return nil, fmt.Errorf("Don't know how or whether to initialise tree type %v", tree.TreeType)
	}

	return tree, nil
}

// InitMap initialises a freshly created Map tree.
func InitMap(ctx context.Context, tree *trillian.Tree, mapClient trillian.TrillianMapClient) error {
	if tree.TreeType != trillian.TreeType_MAP {
		return fmt.Errorf("InitMap called with tree of type %v", tree.TreeType)
	}

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	err := b.Retry(ctx, func() error {
		glog.Infof("Initialising Map %x...", tree.TreeId)
		req := &trillian.InitMapRequest{MapId: tree.TreeId}
		resp, err := mapClient.InitMap(ctx, req)
		if err != nil {
			switch s, ok := status.FromError(err); {
			case ok && s.Code() == codes.Unavailable:
				glog.Errorf("Map server unavailable: %v", err)
				return err
			case ok && s.Code() == codes.AlreadyExists:
				glog.Warningf("Bizarrely, the just-created Map (%x) is already initialised!: %v", tree.TreeId, err)
				return err
			}
			glog.Errorf("failed to InitMap(%+v): %T %v", req, err, err)
			return err
		}
		glog.Infof("Initialised Map (%x) with new SignedMapRoot:\n%+v", tree.TreeId, resp.Created)

		return nil
	})
	if err != nil {
		return err
	}

	// Wait for map root to become available.
	return b.Retry(ctx, func() error {
		_, err := mapClient.GetSignedMapRootByRevision(ctx,
			&trillian.GetSignedMapRootByRevisionRequest{
				MapId:    tree.TreeId,
				Revision: 0,
			})
		return err
	})
}

// InitLog initialises a freshly created Log tree.
func InitLog(ctx context.Context, tree *trillian.Tree, logClient trillian.TrillianLogClient) error {
	if tree.TreeType != trillian.TreeType_LOG &&
		tree.TreeType != trillian.TreeType_PREORDERED_LOG {
		return fmt.Errorf("InitLog called with tree of type %v", tree.TreeType)
	}

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	err := b.Retry(ctx, func() error {
		glog.Infof("Initialising Log %x...", tree.TreeId)
		req := &trillian.InitLogRequest{LogId: tree.TreeId}
		resp, err := logClient.InitLog(ctx, req)
		if err != nil {
			switch s, ok := status.FromError(err); {
			case ok && s.Code() == codes.Unavailable:
				glog.Errorf("Log server unavailable: %v", err)
				return err
			case ok && s.Code() == codes.AlreadyExists:
				glog.Warningf("Bizarrely, the just-created Log (%x) is already initialised!: %v", tree.TreeId, err)
				return err
			}
			glog.Errorf("failed to InitLog(%+v): %T %v", req, err, err)
			return err
		}
		glog.Infof("Initialised Log (%x) with new SignedTreeHead:\n%+v", tree.TreeId, resp.Created)

		return nil
	})
	if err != nil {
		return err
	}

	// Wait for log root to become available.
	return b.Retry(ctx, func() error {
		_, err := logClient.GetLatestSignedLogRoot(ctx,
			&trillian.GetLatestSignedLogRootRequest{LogId: tree.TreeId})
		return err
	})
}
<commit_msg>client: update comment to match code<commit_after>// Copyright 2018 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package client

import (
	"context"
	"fmt"
	"time"

	"github.com/golang/glog"
	"github.com/google/trillian"
	"github.com/google/trillian/client/backoff"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// CreateAndInitTree uses the adminClient and logClient/mapClient to create the tree
// described by req.
// If req describes a MAP tree, then this function will also call the InitMap
// function using mapClient.
// If req describes a LOG tree, then this function will also call the InitLog
// function using logClient.
// Internally, the function will continue to retry failed requests until either
// the tree is created (and if necessary, initialised) successfully, or ctx is
// cancelled.
func CreateAndInitTree(
	ctx context.Context,
	req *trillian.CreateTreeRequest,
	adminClient trillian.TrillianAdminClient,
	mapClient trillian.TrillianMapClient,
	logClient trillian.TrillianLogClient) (*trillian.Tree, error) {

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	var tree *trillian.Tree
	err := b.Retry(ctx, func() error {
		glog.Info("CreateTree...")
		var err error
		tree, err = adminClient.CreateTree(ctx, req)
		if err != nil {
			if s, ok := status.FromError(err); ok && s.Code() == codes.Unavailable {
				glog.Errorf("Admin server unavailable: %v", err)
				return err
			}
			glog.Errorf("failed to CreateTree(%+v): %T %v", req, err, err)
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	switch tree.TreeType {
	case trillian.TreeType_MAP:
		if err := InitMap(ctx, tree, mapClient); err != nil {
			return nil, err
		}
	case trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG:
		if err := InitLog(ctx, tree, logClient); err != nil {
			return nil, err
		}
	default:
		return nil, fmt.Errorf("Don't know how or whether to initialise tree type %v", tree.TreeType)
	}

	return tree, nil
}

// InitMap initialises a freshly created Map tree.
func InitMap(ctx context.Context, tree *trillian.Tree, mapClient trillian.TrillianMapClient) error {
	if tree.TreeType != trillian.TreeType_MAP {
		return fmt.Errorf("InitMap called with tree of type %v", tree.TreeType)
	}

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	err := b.Retry(ctx, func() error {
		glog.Infof("Initialising Map %x...", tree.TreeId)
		req := &trillian.InitMapRequest{MapId: tree.TreeId}
		resp, err := mapClient.InitMap(ctx, req)
		if err != nil {
			switch s, ok := status.FromError(err); {
			case ok && s.Code() == codes.Unavailable:
				glog.Errorf("Map server unavailable: %v", err)
				return err
			case ok && s.Code() == codes.AlreadyExists:
				glog.Warningf("Bizarrely, the just-created Map (%x) is already initialised!: %v", tree.TreeId, err)
				return err
			}
			glog.Errorf("failed to InitMap(%+v): %T %v", req, err, err)
			return err
		}
		glog.Infof("Initialised Map (%x) with new SignedMapRoot:\n%+v", tree.TreeId, resp.Created)

		return nil
	})
	if err != nil {
		return err
	}

	// Wait for map root to become available.
	return b.Retry(ctx, func() error {
		_, err := mapClient.GetSignedMapRootByRevision(ctx,
			&trillian.GetSignedMapRootByRevisionRequest{
				MapId:    tree.TreeId,
				Revision: 0,
			})
		return err
	})
}

// InitLog initialises a freshly created Log tree.
func InitLog(ctx context.Context, tree *trillian.Tree, logClient trillian.TrillianLogClient) error {
	if tree.TreeType != trillian.TreeType_LOG &&
		tree.TreeType != trillian.TreeType_PREORDERED_LOG {
		return fmt.Errorf("InitLog called with tree of type %v", tree.TreeType)
	}

	b := &backoff.Backoff{
		Min:    100 * time.Millisecond,
		Max:    10 * time.Second,
		Factor: 2,
		Jitter: true,
	}

	err := b.Retry(ctx, func() error {
		glog.Infof("Initialising Log %x...", tree.TreeId)
		req := &trillian.InitLogRequest{LogId: tree.TreeId}
		resp, err := logClient.InitLog(ctx, req)
		if err != nil {
			switch s, ok := status.FromError(err); {
			case ok && s.Code() == codes.Unavailable:
				glog.Errorf("Log server unavailable: %v", err)
				return err
			case ok && s.Code() == codes.AlreadyExists:
				glog.Warningf("Bizarrely, the just-created Log (%x) is already initialised!: %v", tree.TreeId, err)
				return err
			}
			glog.Errorf("failed to InitLog(%+v): %T %v", req, err, err)
			return err
		}
		glog.Infof("Initialised Log (%x) with new SignedTreeHead:\n%+v", tree.TreeId, resp.Created)

		return nil
	})
	if err != nil {
		return err
	}

	// Wait for log root to become available.
	return b.Retry(ctx, func() error {
		_, err := logClient.GetLatestSignedLogRoot(ctx,
			&trillian.GetLatestSignedLogRootRequest{LogId: tree.TreeId})
		return err
	})
}
<|endoftext|>