<commit_before>package logic

import (
	"context"

	"github.com/manifoldco/torus-cli/apitypes"
	"github.com/manifoldco/torus-cli/envelope"
	"github.com/manifoldco/torus-cli/identity"
	"github.com/manifoldco/torus-cli/primitive"

	"github.com/manifoldco/torus-cli/daemon/observer"
)

// Worklog holds the logic for discovering and acting on worklog items.
// A Worklog item is some action the user should take, either for
// maintenance (this user should be in this keyring, this invite can be
// approved), or as a preventative measure (this credential value should be
// rotated).
//
// Worklog items may be automatically resolved, or require the user do manually
// perform some action.
type Worklog struct {
	engine   *Engine
	handlers map[apitypes.WorklogType]worklogTypeHandler
}

func newWorklog(e *Engine) Worklog {
	w := Worklog{
		engine: e,
		handlers: map[apitypes.WorklogType]worklogTypeHandler{
			apitypes.SecretRotateWorklogType:    &secretRotateHandler{engine: e},
			apitypes.MissingKeypairsWorklogType: &missingKeypairsHandler{engine: e},
			apitypes.InviteApproveWorklogType:   &inviteApproveHandler{engine: e},
		},
	}

	return w
}

type worklogTypeHandler interface {
	list(context.Context, *envelope.Unsigned) ([]apitypes.WorklogItem, error)
	resolve(context.Context, *observer.Notifier, *identity.ID,
		*apitypes.WorklogItem) (*apitypes.WorklogResult, error)
}

// List returns the list of all outstanding worklog items for the given org
func (w *Worklog) List(ctx context.Context, orgID *identity.ID,
	itemType apitypes.WorklogType) ([]apitypes.WorklogItem, error) {

	org, err := w.engine.client.Orgs.Get(ctx, orgID)
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for t, h := range w.handlers {
		if t&itemType == 0 {
			continue
		}

		hItems, err := h.list(ctx, org)
		if err != nil {
			return nil, err
		}
		items = append(items, hItems...)
	}

	return items, nil
}

// Get returns a single worklog item for the given org with the given ident.
func (w *Worklog) Get(ctx context.Context, orgID *identity.ID,
	ident *apitypes.WorklogID) (*apitypes.WorklogItem, error) {

	items, err := w.List(ctx, orgID, ident.Type())
	if err != nil {
		return nil, err
	}

	for _, item := range items {
		if *item.ID == *ident {
			return &item, nil
		}
	}

	return nil, nil
}

// Resolve attempts to resolve the worklog item in the given org with the given
// ident.
func (w *Worklog) Resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, ident *apitypes.WorklogID) (*apitypes.WorklogResult, error) {

	item, err := w.Get(ctx, orgID, ident)
	if err != nil {
		return nil, err
	}

	if item == nil {
		return nil, nil
	}

	return w.handlers[item.Type()].resolve(ctx, n, orgID, item)
}

type secretRotateHandler struct {
	engine *Engine
}

func (h *secretRotateHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	projects, err := h.engine.client.Projects.List(ctx, org.ID)
	if err != nil {
		return nil, err
	}

	cgs := newCredentialGraphSet()
	orgName := org.Body.(*primitive.Org).Name
	for _, project := range projects {
		projName := project.Body.(*primitive.Project).Name
		graphs, err := h.engine.client.CredentialGraph.Search(ctx,
			"/"+orgName+"/"+projName+"/*/*/*/*", h.engine.session.AuthID())
		if err != nil {
			return nil, err
		}

		err = cgs.Add(graphs...)
		if err != nil {
			return nil, err
		}
	}

	needRotation, err := cgs.NeedRotation()
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for _, cred := range needRotation {
		base, err := baseCredential(&cred)
		if err != nil {
			return nil, err
		}

		item := apitypes.WorklogItem{
			Subject: base.PathExp.String() + "/" + base.Name,
			Summary: "A user's access was revoked. This secret's value should be changed.",
		}
		item.CreateID(apitypes.SecretRotateWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *secretRotateHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.ManualWorklogResult,
		Message: "Please set a new value for the secret at " + item.Subject,
	}, nil
}

type missingKeypairsHandler struct {
	engine *Engine
}

func (h *missingKeypairsHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	encClaimed, sigClaimed, err := fetchRegistryKeyPairs(ctx, h.engine.client, org.ID)
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	if encClaimed == nil || sigClaimed == nil {
		item := apitypes.WorklogItem{
			Subject: org.Body.(*primitive.Org).Name,
			Summary: "Signing and Encryption keypairs missing for org.",
		}

		if encClaimed != nil {
			item.Summary = "Signing keypair missing for org."
		} else if sigClaimed != nil {
			item.Summary = "Encryption keypair missing for org."
		}

		item.CreateID(apitypes.MissingKeypairsWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *missingKeypairsHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	err := h.engine.GenerateKeypair(ctx, n, orgID)
	if err != nil {
		return &apitypes.WorklogResult{
			ID:      item.ID,
			State:   apitypes.ErrorWorklogResult,
			Message: "Error generating keypairs: " + err.Error(),
		}, nil
	}

	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.SuccessWorklogResult,
		Message: "Keypairs generated.",
	}, nil
}

type inviteApproveHandler struct {
	engine *Engine
}

func (h *inviteApproveHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	invites, err := h.engine.client.OrgInvite.List(ctx, org.ID, []string{"accepted"}, "")
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for _, invite := range invites {
		item := apitypes.WorklogItem{
			Subject:   invite.Body.(*primitive.OrgInvite).Email,
			Summary:   "Org invite ready for approval",
			SubjectID: invite.ID,
		}
		item.CreateID(apitypes.InviteApproveWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *inviteApproveHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	_, err := h.engine.ApproveInvite(ctx, n, item.SubjectID)
	if err != nil {
		return nil, err
	}
	if err != nil {
		return &apitypes.WorklogResult{
			ID:      item.ID,
			State:   apitypes.ErrorWorklogResult,
			Message: "Error approving invite: " + err.Error(),
		}, nil
	}

	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.SuccessWorklogResult,
		Message: "User invite approved and finalized.",
	}, nil
}
<commit_msg>Share worklog resolve error result generation<commit_after>package logic

import (
	"context"

	"github.com/manifoldco/torus-cli/apitypes"
	"github.com/manifoldco/torus-cli/envelope"
	"github.com/manifoldco/torus-cli/identity"
	"github.com/manifoldco/torus-cli/primitive"

	"github.com/manifoldco/torus-cli/daemon/observer"
)

// Worklog holds the logic for discovering and acting on worklog items.
// A Worklog item is some action the user should take, either for
// maintenance (this user should be in this keyring, this invite can be
// approved), or as a preventative measure (this credential value should be
// rotated).
//
// Worklog items may be automatically resolved, or require the user do manually
// perform some action.
type Worklog struct {
	engine   *Engine
	handlers map[apitypes.WorklogType]worklogTypeHandler
}

func newWorklog(e *Engine) Worklog {
	w := Worklog{
		engine: e,
		handlers: map[apitypes.WorklogType]worklogTypeHandler{
			apitypes.SecretRotateWorklogType:    &secretRotateHandler{engine: e},
			apitypes.MissingKeypairsWorklogType: &missingKeypairsHandler{engine: e},
			apitypes.InviteApproveWorklogType:   &inviteApproveHandler{engine: e},
		},
	}

	return w
}

type worklogTypeHandler interface {
	list(context.Context, *envelope.Unsigned) ([]apitypes.WorklogItem, error)
	resolve(context.Context, *observer.Notifier, *identity.ID,
		*apitypes.WorklogItem) (*apitypes.WorklogResult, error)
	resolveErr() string
}

// List returns the list of all outstanding worklog items for the given org
func (w *Worklog) List(ctx context.Context, orgID *identity.ID,
	itemType apitypes.WorklogType) ([]apitypes.WorklogItem, error) {

	org, err := w.engine.client.Orgs.Get(ctx, orgID)
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for t, h := range w.handlers {
		if t&itemType == 0 {
			continue
		}

		hItems, err := h.list(ctx, org)
		if err != nil {
			return nil, err
		}
		items = append(items, hItems...)
	}

	return items, nil
}

// Get returns a single worklog item for the given org with the given ident.
func (w *Worklog) Get(ctx context.Context, orgID *identity.ID,
	ident *apitypes.WorklogID) (*apitypes.WorklogItem, error) {

	items, err := w.List(ctx, orgID, ident.Type())
	if err != nil {
		return nil, err
	}

	for _, item := range items {
		if *item.ID == *ident {
			return &item, nil
		}
	}

	return nil, nil
}

// Resolve attempts to resolve the worklog item in the given org with the given
// ident.
func (w *Worklog) Resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, ident *apitypes.WorklogID) (*apitypes.WorklogResult, error) {

	item, err := w.Get(ctx, orgID, ident)
	if err != nil {
		return nil, err
	}

	if item == nil {
		return nil, nil
	}

	handler := w.handlers[item.Type()]
	result, err := handler.resolve(ctx, n, orgID, item)

	// We handle errors from the handler's resolve differently than regular
	// errors; for every other part of the daemon code they're non-errors, sent
	// back to the caller for display. The caller can then continue trying to
	// resolve other worklog items.
	if err != nil {
		result = &apitypes.WorklogResult{
			ID:      item.ID,
			State:   apitypes.ErrorWorklogResult,
			Message: handler.resolveErr() + ": " + err.Error(),
		}
	}

	return result, nil
}

type secretRotateHandler struct {
	engine *Engine
}

func (secretRotateHandler) resolveErr() string {
	// This won't happen, because rotation must be manual. Let's include an
	// error message just in case, though!
	return "Error rotating secret"
}

func (h *secretRotateHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	projects, err := h.engine.client.Projects.List(ctx, org.ID)
	if err != nil {
		return nil, err
	}

	cgs := newCredentialGraphSet()
	orgName := org.Body.(*primitive.Org).Name
	for _, project := range projects {
		projName := project.Body.(*primitive.Project).Name
		graphs, err := h.engine.client.CredentialGraph.Search(ctx,
			"/"+orgName+"/"+projName+"/*/*/*/*", h.engine.session.AuthID())
		if err != nil {
			return nil, err
		}

		err = cgs.Add(graphs...)
		if err != nil {
			return nil, err
		}
	}

	needRotation, err := cgs.NeedRotation()
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for _, cred := range needRotation {
		base, err := baseCredential(&cred)
		if err != nil {
			return nil, err
		}

		item := apitypes.WorklogItem{
			Subject: base.PathExp.String() + "/" + base.Name,
			Summary: "A user's access was revoked. This secret's value should be changed.",
		}
		item.CreateID(apitypes.SecretRotateWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *secretRotateHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.ManualWorklogResult,
		Message: "Please set a new value for the secret at " + item.Subject,
	}, nil
}

type missingKeypairsHandler struct {
	engine *Engine
}

func (missingKeypairsHandler) resolveErr() string {
	return "Error generating keypairs"
}

func (h *missingKeypairsHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	encClaimed, sigClaimed, err := fetchRegistryKeyPairs(ctx, h.engine.client, org.ID)
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	if encClaimed == nil || sigClaimed == nil {
		item := apitypes.WorklogItem{
			Subject: org.Body.(*primitive.Org).Name,
			Summary: "Signing and Encryption keypairs missing for org.",
		}

		if encClaimed != nil {
			item.Summary = "Signing keypair missing for org."
		} else if sigClaimed != nil {
			item.Summary = "Encryption keypair missing for org."
		}

		item.CreateID(apitypes.MissingKeypairsWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *missingKeypairsHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	err := h.engine.GenerateKeypair(ctx, n, orgID)
	if err != nil {
		return nil, err
	}

	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.SuccessWorklogResult,
		Message: "Keypairs generated.",
	}, nil
}

type inviteApproveHandler struct {
	engine *Engine
}

func (inviteApproveHandler) resolveErr() string {
	return "Error approving invite"
}

func (h *inviteApproveHandler) list(ctx context.Context, org *envelope.Unsigned) ([]apitypes.WorklogItem, error) {
	invites, err := h.engine.client.OrgInvite.List(ctx, org.ID, []string{"accepted"}, "")
	if err != nil {
		return nil, err
	}

	var items []apitypes.WorklogItem
	for _, invite := range invites {
		item := apitypes.WorklogItem{
			Subject:   invite.Body.(*primitive.OrgInvite).Email,
			Summary:   "Org invite ready for approval",
			SubjectID: invite.ID,
		}
		item.CreateID(apitypes.InviteApproveWorklogType)

		items = append(items, item)
	}

	return items, nil
}

func (h *inviteApproveHandler) resolve(ctx context.Context, n *observer.Notifier,
	orgID *identity.ID, item *apitypes.WorklogItem) (*apitypes.WorklogResult, error) {
	_, err := h.engine.ApproveInvite(ctx, n, item.SubjectID)
	if err != nil {
		return nil, err
	}

	return &apitypes.WorklogResult{
		ID:      item.ID,
		State:   apitypes.SuccessWorklogResult,
		Message: "User invite approved and finalized.",
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"time"
)

func backoffBucket(minWait, maxWait time.Duration, until <-chan struct{}) <-chan struct{} {
	tokens := make(chan struct{})
	limiter := tokens
	go func() {
		d := 0 * time.Second
		t := time.NewTimer(d)
		defer t.Stop()
		for {
			select {
			case limiter <- struct{}{}:
				if d == 0 {
					d = minWait
				} else {
					d *= 2
					if d > maxWait {
						d = maxWait
					}
				}
				limiter = nil
			case <-t.C:
				if limiter != nil {
					d /= 2
				} else {
					limiter = tokens
				}
			case <-until:
				return
			}
			t.Reset(d)
		}
	}()
	return tokens
}
<commit_msg>fix busyloop bug<commit_after>package main

import (
	"fmt"
	"time"
)

// backoffBucket returns a chan that yields a struct{}{} every so often. the wait period
// between structs is between minWait and maxWait. greedy consumers that continuously read
// from the returned bucket chan will see the wait period generally increase.
//
// Note: this func panics if minWait is a non-positive value to avoid busy-looping.
func backoffBucket(minWait, maxWait time.Duration, until <-chan struct{}) <-chan struct{} {
	if maxWait < minWait {
		maxWait, minWait = minWait, maxWait
	}
	if minWait <= 0 {
		panic(fmt.Sprintf("illegal value for minWait: %v", minWait))
	}
	tokens := make(chan struct{})
	limiter := tokens
	go func() {
		d := 0 * time.Second
		t := time.NewTimer(d)
		defer t.Stop()
		for {
			select {
			case limiter <- struct{}{}:
				d *= 2
				if d > maxWait {
					d = maxWait
				}
				limiter = nil
			case <-t.C:
				if limiter != nil {
					d /= 2
				} else {
					limiter = tokens
				}
			case <-until:
				return
			}
			// important to have non-zero minWait otherwise we busy-loop
			if d == 0 {
				d = minWait
			}
			t.Reset(d)
		}
	}()
	return tokens
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/gosuri/uilive"
	"github.com/mattn/go-isatty"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"github.com/weaveworks/flux"
	transport "github.com/weaveworks/flux/http"
)

const largestHeartbeatDelta = 5 * time.Second

type serviceCheckReleaseOpts struct {
	*serviceOpts
	releaseID string
	noFollow  bool
	noTty     bool
}

func newServiceCheckRelease(parent *serviceOpts) *serviceCheckReleaseOpts {
	return &serviceCheckReleaseOpts{serviceOpts: parent}
}

func (opts *serviceCheckReleaseOpts) Command() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "check-release",
		Short: "Check the status of a release.",
		Example: makeExample(
			"fluxctl check-release --release-id=12345678-1234-5678-1234-567812345678",
		),
		RunE: opts.RunE,
	}
	cmd.Flags().StringVarP(&opts.releaseID, "release-id", "r", "", "release ID to check")
	cmd.Flags().BoolVar(&opts.noFollow, "no-follow", false, "dump release job as JSON to stdout")
	cmd.Flags().BoolVar(&opts.noTty, "no-tty", false, "forces simpler, non-TTY status output")
	return cmd
}

func (opts *serviceCheckReleaseOpts) RunE(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		return errorWantedNoArgs
	}

	if opts.releaseID == "" {
		return fmt.Errorf("-r, --release-id is required")
	}

	if opts.noFollow {
		job, err := opts.API.GetRelease(noInstanceID, flux.ReleaseID(opts.releaseID))
		if err != nil {
			return err
		}
		buf, err := json.MarshalIndent(job, "", "    ")
		if err != nil {
			return err
		}
		_, err = os.Stdout.Write(buf)
		return err
	}

	var (
		w    io.Writer = os.Stdout
		stop           = func() {}
	)
	if !opts.noTty && isatty.IsTerminal(os.Stdout.Fd()) {
		liveWriter := uilive.New()
		liveWriter.Start()
		w, stop = liveWriter, liveWriter.Stop
	}
	var (
		job flux.ReleaseJob
		err error

		prevStatus            string
		lastHeartbeatDatabase time.Time
		lastHeartbeatLocal    = time.Now()
		initialRetryBackoff   = 4
		abandonRetryThreshold = 60
		retryBackoff          = initialRetryBackoff
		retryNext             = 0
	)

	for range time.Tick(time.Second) {
		if retryNext > 0 {
			fmt.Fprintf(w, "Last status: %s\n", prevStatus)
			fmt.Fprintf(w, "Service unavailable. Retrying in %d sec.\n", retryNext)
			retryNext--
			continue
		}

		job, err = opts.API.GetRelease(noInstanceID, flux.ReleaseID(opts.releaseID))
		if err != nil {
			if err, ok := errors.Cause(err).(*transport.APIError); ok && err.IsUnavailable() {
				if retryBackoff > abandonRetryThreshold {
					stop()
					fmt.Fprintln(os.Stdout, "Giving up retrying for now. You can check again later with")
					fmt.Fprintf(os.Stdout, "    %s -r %s\n", cmd.CommandPath(), opts.releaseID)
					return errors.New("Abandoned after too many retries.")
				}
				retryNext = retryBackoff
				retryBackoff *= 2
				continue
			}
			fmt.Fprintf(w, "Status: error querying release.\n") // error will get printed below
			break
		}

		retryBackoff = initialRetryBackoff
		status := "Waiting for job to be claimed..."
		if job.Status != "" {
			status = job.Status
		}

		// Checking heartbeat is a bit tricky. We get a timestamp in database
		// time, which may be radically different to our time. I've chosen to
		// check liveness by marking local time whenever the heartbeat time
		// changes. Going long enough without updating that local timestamp
		// triggers the warning.
		if !job.Claimed.IsZero() {
			if job.Heartbeat != lastHeartbeatDatabase {
				lastHeartbeatDatabase = job.Heartbeat
				lastHeartbeatLocal = time.Now()
			}
			if delta := time.Since(lastHeartbeatLocal); delta > largestHeartbeatDelta {
				status += fmt.Sprintf(" -- no heartbeat in %s; worker may have crashed", delta)
			}
		}

		if status != prevStatus {
			fmt.Fprintf(w, "Status: %s\n", status)
		}
		prevStatus = status

		if job.Done {
			break
		}
	}
	stop()

	if err != nil {
		return err
	}

	fmt.Fprintf(os.Stdout, "\n")
	if !job.Success {
		fmt.Fprintf(os.Stdout, "Here's as far as we got:\n")
	} else if job.Spec.Kind == flux.ReleaseKindPlan {
		fmt.Fprintf(os.Stdout, "Here's the plan:\n")
	} else {
		fmt.Fprintf(os.Stdout, "Here's what happened:\n")
	}
	for i, msg := range job.Log {
		fmt.Fprintf(os.Stdout, " %d) %s\n", i+1, msg)
	}

	if job.Spec.Kind == flux.ReleaseKindExecute {
		fmt.Fprintf(os.Stdout, "Took %s\n", job.Finished.Sub(job.Submitted))
	}
	return nil
}
<commit_msg>Use an overall time limit for retrying<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"sync"
	"time"

	"github.com/gosuri/uilive"
	"github.com/mattn/go-isatty"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"github.com/weaveworks/flux"
	transport "github.com/weaveworks/flux/http"
)

const largestHeartbeatDelta = 5 * time.Second
const retryTimeout = 2 * time.Minute

type serviceCheckReleaseOpts struct {
	*serviceOpts
	releaseID string
	noFollow  bool
	noTty     bool
}

func newServiceCheckRelease(parent *serviceOpts) *serviceCheckReleaseOpts {
	return &serviceCheckReleaseOpts{serviceOpts: parent}
}

func (opts *serviceCheckReleaseOpts) Command() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "check-release",
		Short: "Check the status of a release.",
		Example: makeExample(
			"fluxctl check-release --release-id=12345678-1234-5678-1234-567812345678",
		),
		RunE: opts.RunE,
	}
	cmd.Flags().StringVarP(&opts.releaseID, "release-id", "r", "", "release ID to check")
	cmd.Flags().BoolVar(&opts.noFollow, "no-follow", false, "dump release job as JSON to stdout")
	cmd.Flags().BoolVar(&opts.noTty, "no-tty", false, "forces simpler, non-TTY status output")
	return cmd
}

func (opts *serviceCheckReleaseOpts) RunE(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		return errorWantedNoArgs
	}

	if opts.releaseID == "" {
		return fmt.Errorf("-r, --release-id is required")
	}

	if opts.noFollow {
		job, err := opts.API.GetRelease(noInstanceID, flux.ReleaseID(opts.releaseID))
		if err != nil {
			return err
		}
		buf, err := json.MarshalIndent(job, "", "    ")
		if err != nil {
			return err
		}
		_, err = os.Stdout.Write(buf)
		return err
	}

	var (
		w    io.Writer = os.Stdout
		stop           = func() {}
	)
	if !opts.noTty && isatty.IsTerminal(os.Stdout.Fd()) {
		liveWriter := uilive.New()
		liveWriter.Start()
		var stopOnce sync.Once
		w, stop = liveWriter, func() { stopOnce.Do(liveWriter.Stop) }
	}
	var (
		job flux.ReleaseJob
		err error

		prevStatus            string
		lastHeartbeatDatabase time.Time
		lastHeartbeatLocal    = time.Now()

		retryCount    = 0
		lastSucceeded = time.Now()
	)

	for range time.Tick(time.Second) {
		if retryCount > 0 {
			fmt.Fprintf(w, "Last status (%s): %s\n", lastSucceeded.Format(time.Kitchen), prevStatus)
			fmt.Fprintf(w, "Service unavailable. Retrying (#%d) ...\n", retryCount)
		}

		job, err = opts.API.GetRelease(noInstanceID, flux.ReleaseID(opts.releaseID))
		if err != nil {
			if err, ok := errors.Cause(err).(*transport.APIError); ok && err.IsUnavailable() {
				if time.Since(lastSucceeded) > retryTimeout {
					stop()
					fmt.Fprintln(os.Stdout, "Giving up; you can try again with")
					fmt.Fprintf(os.Stdout, "    fluxctl check-release -r %s\n", opts.releaseID)
					fmt.Fprintln(os.Stdout)
					break
				}
				retryCount++
				continue
			}
			fmt.Fprintf(w, "Status: error querying release.\n") // error will get printed below
			break
		}

		lastSucceeded = time.Now()
		retryCount = 0
		status := "Waiting for job to be claimed..."
		if job.Status != "" {
			status = job.Status
		}

		// Checking heartbeat is a bit tricky. We get a timestamp in database
		// time, which may be radically different to our time. I've chosen to
		// check liveness by marking local time whenever the heartbeat time
		// changes. Going long enough without updating that local timestamp
		// triggers the warning.
		if !job.Claimed.IsZero() {
			if job.Heartbeat != lastHeartbeatDatabase {
				lastHeartbeatDatabase = job.Heartbeat
				lastHeartbeatLocal = time.Now()
			}
			if delta := time.Since(lastHeartbeatLocal); delta > largestHeartbeatDelta {
				status += fmt.Sprintf(" -- no heartbeat in %s; worker may have crashed", delta)
			}
		}

		if status != prevStatus {
			fmt.Fprintf(w, "Status: %s\n", status)
		}
		prevStatus = status

		if job.Done {
			break
		}
	}
	stop()

	if err != nil {
		return err
	}

	fmt.Fprintf(os.Stdout, "\n")
	if !job.Success {
		fmt.Fprintf(os.Stdout, "Here's as far as we got:\n")
	} else if job.Spec.Kind == flux.ReleaseKindPlan {
		fmt.Fprintf(os.Stdout, "Here's the plan:\n")
	} else {
		fmt.Fprintf(os.Stdout, "Here's what happened:\n")
	}
	for i, msg := range job.Log {
		fmt.Fprintf(os.Stdout, " %d) %s\n", i+1, msg)
	}

	if job.Spec.Kind == flux.ReleaseKindExecute {
		fmt.Fprintf(os.Stdout, "Took %s\n", job.Finished.Sub(job.Submitted))
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import "github.com/codegangsta/cli"

func registerCommands(app cli.App) *cli.App {

	app.Commands = []cli.Command{
		{
			Name:   "init",
			Usage:  "Initialize local client files",
			Action: cmdClientInit,
		},
		{
			Name:   "experiment",
			Usage:  "Test cli.Action functionality",
			Action: runtime(cmdExperiment),
		},
	}

	app = *registerAttributes(app)
	app = *registerBuckets(app)
	app = *registerCapability(app)
	app = *registerChecks(app)
	app = *registerClusters(app)
	app = *registerDatacenters(app)
	app = *registerEnvironments(app)
	app = *registerGroups(app)
	app = *registerJobs(app)
	app = *registerLevels(app)
	app = *registerMetrics(app)
	app = *registerModes(app)
	app = *registerMonitoring(app)
	app = *registerNodes(app)
	app = *registerOncall(app)
	app = *registerPermissions(app)
	app = *registerPredicates(app)
	app = *registerProperty(app)
	app = *registerProviders(app)
	app = *registerRights(app)
	app = *registerRepository(app)
	app = *registerServers(app)
	app = *registerStates(app)
	app = *registerStatus(app)
	app = *registerTeams(app)
	app = *registerTypes(app)
	app = *registerUnits(app)
	app = *registerUsers(app)
	app = *registerValidity(app)
	app = *registerViews(app)
	app = *registerOps(app)

	return &app
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>somaadm: register instances command<commit_after>package main

import "github.com/codegangsta/cli"

func registerCommands(app cli.App) *cli.App {

	app.Commands = []cli.Command{
		{
			Name:   "init",
			Usage:  "Initialize local client files",
			Action: cmdClientInit,
		},
		{
			Name:   "experiment",
			Usage:  "Test cli.Action functionality",
			Action: runtime(cmdExperiment),
		},
	}

	app = *registerAttributes(app)
	app = *registerBuckets(app)
	app = *registerCapability(app)
	app = *registerChecks(app)
	app = *registerClusters(app)
	app = *registerDatacenters(app)
	app = *registerEnvironments(app)
	app = *registerGroups(app)
	app = *registerInstances(app)
	app = *registerJobs(app)
	app = *registerLevels(app)
	app = *registerMetrics(app)
	app = *registerModes(app)
	app = *registerMonitoring(app)
	app = *registerNodes(app)
	app = *registerOncall(app)
	app = *registerPermissions(app)
	app = *registerPredicates(app)
	app = *registerProperty(app)
	app = *registerProviders(app)
	app = *registerRights(app)
	app = *registerRepository(app)
	app = *registerServers(app)
	app = *registerStates(app)
	app = *registerStatus(app)
	app = *registerTeams(app)
	app = *registerTypes(app)
	app = *registerUnits(app)
	app = *registerUsers(app)
	app = *registerValidity(app)
	app = *registerViews(app)
	app = *registerOps(app)

	return &app
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>// unify-labels is a CLI which will add, rename, or change the color of labels so they match the Jekyll org's requirements.
package main

import (
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/google/go-github/github"
	"github.com/parkr/auto-reply/ctx"
	"github.com/parkr/auto-reply/freeze"
	"github.com/parkr/auto-reply/sentry"
)

var desiredLabels = []*github.Label{
	{Name: github.String("accepted"), Color: github.String("4bc865")},
	{Name: github.String("bug"), Color: github.String("d41313")},
	{Name: github.String("discussion"), Color: github.String("006b75")},
	{Name: github.String("documentation"), Color: github.String("006b75")},
	{Name: github.String("enhancement"), Color: github.String("009800")},
	{Name: github.String("feature"), Color: github.String("009800")},
	{Name: github.String("fix"), Color: github.String("eb6420")},
	{Name: github.String(freeze.LabelName), Color: github.String("0052cc")},
	{Name: github.String("github"), Color: github.String("222222")},
	{Name: github.String("has-pull-request"), Color: github.String("fbca04")},
	{Name: github.String("help-wanted"), Color: github.String("fbca04")},
	{Name: github.String("internal"), Color: github.String("ededed")},
	{Name: github.String("pending-feedback"), Color: github.String("fbca04")},
	{Name: github.String("pending-rebase"), Color: github.String("eb6420")},
	{Name: github.String("pinned"), Color: github.String("f3f4d3")},
	{Name: github.String("release"), Color: github.String("d4c5f9")},
	{Name: github.String("security"), Color: github.String("e11d21")},
	{Name: github.String("stale"), Color: github.String("bfd4f2")},
	{Name: github.String("suggestion"), Color: github.String("0052cc")},
	{Name: github.String("support"), Color: github.String("5319e7")},
	{Name: github.String("tests"), Color: github.String("d4c5f9")},
	{Name: github.String("undetermined"), Color: github.String("fe3868")},
	{Name: github.String("ux"), Color: github.String("006b75")},
	{Name: github.String("windows"), Color: github.String("fbca04")},
	{Name: github.String("wont-fix"), Color: github.String("e11d21")},
}
var listOpts = github.ListOptions{PerPage: 100}

func allPossibleNames(name string) []string {
	return []string{
		name,
		strings.Replace(name, "-", "", -1),
		strings.Replace(name, "-", " ", -1),
		strings.ToLower(name),
		strings.Title(name),
		strings.Title(strings.Replace(name, "-", "", -1)),
		strings.Title(strings.Replace(name, "-", " ", -1)),
	}
}

func findLabel(labels []*github.Label, desiredLabel *github.Label) *github.Label {
	possibleNames := allPossibleNames(*desiredLabel.Name)
	for _, possibleName := range possibleNames {
		for _, label := range labels {
			if *label.Name == possibleName {
				return label
			}
		}
	}

	return nil
}

func processRepo(context *ctx.Context, repo *github.Repository, perform bool) error {
	owner, repoName := *repo.Owner.Login, *repo.Name
	context.Log("Processing %s", *repo.FullName)

	// 1. Find labels on GitHub.
	labels, _, err := context.GitHub.Issues.ListLabels(context.Context(), owner, repoName, &listOpts)
	if err != nil {
		return context.NewError("error fetching labels for %s: %v", *repo.FullName, err)
	}

	for _, desiredLabel := range desiredLabels {
		matchedLabel := findLabel(labels, desiredLabel)

		// It doesn't exist. Create and continue.
		if matchedLabel == nil {
			if perform {
				context.Log("%s: creating %s with color %s", *repo.FullName, *desiredLabel.Name, *desiredLabel.Color)
				_, _, err := context.GitHub.Issues.CreateLabel(context.Context(), owner, repoName, desiredLabel)
				if err != nil {
					return context.NewError("error creating '%s' for %s: %v", *desiredLabel.Name, *repo.FullName, err)
				}
			} else {
				context.Log("%s: would create %s with color %s", *repo.FullName, *desiredLabel.Name, *desiredLabel.Color)
			}
			continue
		}

		// It does exist, but possibly with incorrect info. Update it.
		if *matchedLabel.Name != *desiredLabel.Name || *matchedLabel.Color != *desiredLabel.Color {
			if perform {
				context.Log("%s: updating %s with data: %v",
					*repo.FullName, *matchedLabel.Name, github.Stringify(desiredLabel))
				_, _, err := context.GitHub.Issues.EditLabel(context.Context(), owner, repoName, *matchedLabel.Name, desiredLabel)
				if err != nil {
					return context.NewError("%s: error updating '%s': %v", *repo.FullName, *matchedLabel.Name, err)
				}
			} else {
				context.Log("%s: would update %s with data: %v", *repo.FullName, *matchedLabel.Name, github.Stringify(desiredLabel))
			}
			continue
		}
	}

	return nil
}

func main() {
	var perform bool
	flag.BoolVar(&perform, "f", false, "Whether to modify the labels (if true) or show dry-run output (if false).")
	flag.Parse()

	context := ctx.NewDefaultContext()

	log.SetPrefix("freeze-ancient-issues: ")

	sentryClient, err := sentry.NewClient(map[string]string{
		"app":     "unify-labels",
		"perform": fmt.Sprintf("%t", perform),
	})
	if err != nil {
		panic(err)
	}

	sentryClient.Recover(func() error {
		repos, _, err := context.GitHub.Repositories.List(context.Context(), "jekyll", &github.RepositoryListOptions{
			Type: "owner", Sort: "full_name", Direction: "asc", ListOptions: listOpts,
		})
		if err != nil {
			return err
		}

		for _, repo := range repos {
			if err := processRepo(context, repo, perform); err != nil {
				context.Log("%s: failed!", *repo.FullName)
				return err
			}
		}

		return nil
	})
}
<commit_msg>Add commonly used labels<commit_after>// unify-labels is a CLI which will add, rename, or change the color of labels so they match the Jekyll org's requirements.
package main

import (
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/google/go-github/github"
	"github.com/parkr/auto-reply/ctx"
	"github.com/parkr/auto-reply/freeze"
	"github.com/parkr/auto-reply/sentry"
)

var desiredLabels = []*github.Label{
	{Name: github.String("accepted"), Color: github.String("4bc865")},
	{Name: github.String("bug"), Color: github.String("d41313")},
	{Name: github.String("discussion"), Color: github.String("006b75")},
	{Name: github.String("documentation"), Color: github.String("006b75")},
	{Name: github.String("enhancement"), Color: github.String("009800")},
	{Name: github.String("feature"), Color: github.String("009800")},
	{Name: github.String("fix"), Color: github.String("eb6420")},
	{Name: github.String(freeze.LabelName), Color: github.String("0052cc")},
	{Name: github.String("github"), Color: github.String("222222")},
	{Name: github.String("has-pull-request"), Color: github.String("fbca04")},
	{Name: github.String("help-wanted"), Color: github.String("fbca04")},
	{Name: github.String("internal"), Color: github.String("ededed")},
	{Name: github.String("needs-documentation"), Color: github.String("b72243")},
	{Name: github.String("needs-tests"), Color: github.String("5140a5")},
	{Name: github.String("not-reproduced"), Color: github.String("ba1771")},
	{Name: github.String("pending-feedback"), Color: github.String("fbca04")},
	{Name: github.String("pending-rebase"), Color: github.String("eb6420")},
	{Name: github.String("pinned"), Color: github.String("f3f4d3")},
        {Name: github.String("priority 1 (must)"), Color: github.String("222222")},
        {Name: github.String("priority 2 (should)"), Color: github.String("888888")},
        {Name: github.String("priority 3 (could)"), Color: github.String("cccccc")},
        {Name: github.String("priority 4 (maybe)"), Color: github.String("efefef")},
	{Name: github.String("release"), Color: github.String("d4c5f9")},
	{Name: github.String("security"), Color: github.String("e11d21")},
	{Name: github.String("stale"), Color: github.String("bfd4f2")},
	{Name: github.String("suggestion"), Color: github.String("0052cc")},
	{Name: github.String("support"), Color: github.String("5319e7")},
	{Name: github.String("tests"), Color: github.String("d4c5f9")},
	{Name: github.String("undetermined"), Color: github.String("fe3868")},
	{Name: github.String("ux"), Color: github.String("006b75")},
	{Name: github.String("windows"), Color: github.String("fbca04")},
	{Name: github.String("wont-fix"), Color: github.String("e11d21")},
}
var listOpts = github.ListOptions{PerPage: 100}

func allPossibleNames(name string) []string {
	return []string{
		name,
		strings.Replace(name, "-", "", -1),
		strings.Replace(name, "-", " ", -1),
		strings.ToLower(name),
		strings.Title(name),
		strings.Title(strings.Replace(name, "-", "", -1)),
		strings.Title(strings.Replace(name, "-", " ", -1)),
	}
}

func findLabel(labels []*github.Label, desiredLabel *github.Label) *github.Label {
	possibleNames := allPossibleNames(*desiredLabel.Name)
	for _, possibleName := range possibleNames {
		for _, label := range labels {
			if *label.Name == possibleName {
				return label
			}
		}
	}

	return nil
}

func processRepo(context *ctx.Context, repo *github.Repository, perform bool) error {
	owner, repoName := *repo.Owner.Login, *repo.Name
	context.Log("Processing %s", *repo.FullName)

	// 1. Find labels on GitHub.
	labels, _, err := context.GitHub.Issues.ListLabels(context.Context(), owner, repoName, &listOpts)
	if err != nil {
		return context.NewError("error fetching labels for %s: %v", *repo.FullName, err)
	}

	for _, desiredLabel := range desiredLabels {
		matchedLabel := findLabel(labels, desiredLabel)

		// It doesn't exist. Create and continue.
		if matchedLabel == nil {
			if perform {
				context.Log("%s: creating %s with color %s", *repo.FullName, *desiredLabel.Name, *desiredLabel.Color)
				_, _, err := context.GitHub.Issues.CreateLabel(context.Context(), owner, repoName, desiredLabel)
				if err != nil {
					return context.NewError("error creating '%s' for %s: %v", *desiredLabel.Name, *repo.FullName, err)
				}
			} else {
				context.Log("%s: would create %s with color %s", *repo.FullName, *desiredLabel.Name, *desiredLabel.Color)
			}
			continue
		}

		// It does exist, but possibly with incorrect info. Update it.
		if *matchedLabel.Name != *desiredLabel.Name || *matchedLabel.Color != *desiredLabel.Color {
			if perform {
				context.Log("%s: updating %s with data: %v",
					*repo.FullName, *matchedLabel.Name, github.Stringify(desiredLabel))
				_, _, err := context.GitHub.Issues.EditLabel(context.Context(), owner, repoName, *matchedLabel.Name, desiredLabel)
				if err != nil {
					return context.NewError("%s: error updating '%s': %v", *repo.FullName, *matchedLabel.Name, err)
				}
			} else {
				context.Log("%s: would update %s with data: %v", *repo.FullName, *matchedLabel.Name, github.Stringify(desiredLabel))
			}
			continue
		}
	}

	return nil
}

func main() {
	var perform bool
	flag.BoolVar(&perform, "f", false, "Whether to modify the labels (if true) or show dry-run output (if false).")
	flag.Parse()

	context := ctx.NewDefaultContext()

	log.SetPrefix("freeze-ancient-issues: ")

	sentryClient, err := sentry.NewClient(map[string]string{
		"app":     "unify-labels",
		"perform": fmt.Sprintf("%t", perform),
	})
	if err != nil {
		panic(err)
	}

	sentryClient.Recover(func() error {
		repos, _, err := context.GitHub.Repositories.List(context.Context(), "jekyll", &github.RepositoryListOptions{
			Type: "owner", Sort: "full_name", Direction: "asc", ListOptions: listOpts,
		})
		if err != nil {
			return err
		}

		for _, repo := range repos {
			if err := processRepo(context, repo, perform); err != nil {
				context.Log("%s: failed!", *repo.FullName)
				return err
			}
		}

		return nil
	})
}
<|endoftext|>


<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package tlf

import (
	"encoding"
	"encoding/hex"
	"fmt"

	"github.com/keybase/kbfs/kbfscrypto"
	"github.com/pkg/errors"
)

const (
	// idByteLen is the number of bytes in a top-level folder ID
	idByteLen = 16
	// idStringLen is the number of characters in the string
	// representation of a top-level folder ID
	idStringLen = 2 * idByteLen
	// idSuffix is the last byte of a private top-level folder ID
	idSuffix = 0x16
	// pubIDSuffix is the last byte of a public top-level folder ID
	pubIDSuffix = 0x17
	// singleTeamIDSuffix is the last byte of a single-team top-level
	// folder ID
	singleTeamIDSuffix = 0x26
)

// Type is the type of TLF represented by a particular ID (e.g.,
// public, private, etc.)
type Type int

const (
	_ Type = iota
	// Private represents a private TLF between one or more individual users.
	Private
	// Public represents a public TLF for one or more individual users.
	Public
	// SingleTeam represents a private TLF for a single Keybase team.
	SingleTeam
)

func (t Type) String() string {
	switch t {
	case Private:
		return "private"
	case Public:
		return "public"
	case SingleTeam:
		return "singleTeam"
	default:
		return fmt.Sprintf("Unknown TLF type: %d", t)
	}
}

// ID is a top-level folder ID
type ID struct {
	id [idByteLen]byte
}

var _ encoding.BinaryMarshaler = ID{}
var _ encoding.BinaryUnmarshaler = (*ID)(nil)

var _ encoding.TextMarshaler = ID{}
var _ encoding.TextUnmarshaler = (*ID)(nil)

// NullID is an empty ID
var NullID = ID{}

// Bytes returns the bytes of the TLF ID.
func (id ID) Bytes() []byte {
	return id.id[:]
}

// String implements the fmt.Stringer interface for ID.
func (id ID) String() string {
	return hex.EncodeToString(id.id[:])
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for ID.
func (id ID) MarshalBinary() (data []byte, err error) {
	suffix := id.id[idByteLen-1]
	if suffix != idSuffix && suffix != pubIDSuffix {
		return nil, errors.WithStack(InvalidIDError{id.String()})
	}
	return id.id[:], nil
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for ID.
func (id *ID) UnmarshalBinary(data []byte) error {
	if len(data) != idByteLen {
		return errors.WithStack(
			InvalidIDError{hex.EncodeToString(data)})
	}
	suffix := data[idByteLen-1]
	if suffix != idSuffix && suffix != pubIDSuffix {
		return errors.WithStack(
			InvalidIDError{hex.EncodeToString(data)})
	}
	copy(id.id[:], data)
	return nil
}

// MarshalText implements the encoding.TextMarshaler interface for ID.
func (id ID) MarshalText() ([]byte, error) {
	bytes, err := id.MarshalBinary()
	if err != nil {
		return nil, err
	}
	return []byte(hex.EncodeToString(bytes)), nil
}

// UnmarshalText implements the encoding.TextUnmarshaler interface for
// ID.
func (id *ID) UnmarshalText(buf []byte) error {
	s := string(buf)
	bytes, err := hex.DecodeString(s)
	if err != nil {
		return errors.WithStack(InvalidIDError{s})
	}
	return id.UnmarshalBinary(bytes)
}

// Type returns the type of TLF represented by this ID.
func (id ID) Type() Type {
	switch id.id[idByteLen-1] {
	case idSuffix:
		return Private
	case pubIDSuffix:
		return Public
	case singleTeamIDSuffix:
		return SingleTeam
	default:
		panic(fmt.Sprintf("Unknown ID suffix  %x", id.id[idByteLen-1]))
	}
}

// ParseID parses a hex encoded ID. Returns NullID and an
// InvalidIDError on failure.
func ParseID(s string) (ID, error) {
	var id ID
	err := id.UnmarshalText([]byte(s))
	if err != nil {
		return ID{}, err
	}
	return id, nil
}

// MakeRandomID makes a random ID using a cryptographically secure
// RNG. Returns NullID on failure.
func MakeRandomID(t Type) (ID, error) {
	var idBytes [idByteLen]byte
	err := kbfscrypto.RandRead(idBytes[:])
	if err != nil {
		return NullID, err
	}
	switch t {
	case Private:
		idBytes[idByteLen-1] = idSuffix
	case Public:
		idBytes[idByteLen-1] = pubIDSuffix
	case SingleTeam:
		idBytes[idByteLen-1] = singleTeamIDSuffix
	default:
		panic(fmt.Sprintf("Unknown TLF type %d", t))
	}
	var id ID
	err = id.UnmarshalBinary(idBytes[:])
	if err != nil {
		return NullID, err
	}
	return id, nil
}
<commit_msg>tlf: allow (de)serialization for team TLF IDs<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package tlf

import (
	"encoding"
	"encoding/hex"
	"fmt"

	"github.com/keybase/kbfs/kbfscrypto"
	"github.com/pkg/errors"
)

const (
	// idByteLen is the number of bytes in a top-level folder ID
	idByteLen = 16
	// idStringLen is the number of characters in the string
	// representation of a top-level folder ID
	idStringLen = 2 * idByteLen
	// idSuffix is the last byte of a private top-level folder ID
	idSuffix = 0x16
	// pubIDSuffix is the last byte of a public top-level folder ID
	pubIDSuffix = 0x17
	// singleTeamIDSuffix is the last byte of a single-team top-level
	// folder ID
	singleTeamIDSuffix = 0x26
)

// Type is the type of TLF represented by a particular ID (e.g.,
// public, private, etc.)
type Type int

const (
	_ Type = iota
	// Private represents a private TLF between one or more individual users.
	Private
	// Public represents a public TLF for one or more individual users.
	Public
	// SingleTeam represents a private TLF for a single Keybase team.
	SingleTeam
)

func (t Type) String() string {
	switch t {
	case Private:
		return "private"
	case Public:
		return "public"
	case SingleTeam:
		return "singleTeam"
	default:
		return fmt.Sprintf("Unknown TLF type: %d", t)
	}
}

// ID is a top-level folder ID
type ID struct {
	id [idByteLen]byte
}

var _ encoding.BinaryMarshaler = ID{}
var _ encoding.BinaryUnmarshaler = (*ID)(nil)

var _ encoding.TextMarshaler = ID{}
var _ encoding.TextUnmarshaler = (*ID)(nil)

// NullID is an empty ID
var NullID = ID{}

// Bytes returns the bytes of the TLF ID.
func (id ID) Bytes() []byte {
	return id.id[:]
}

// String implements the fmt.Stringer interface for ID.
func (id ID) String() string {
	return hex.EncodeToString(id.id[:])
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for ID.
func (id ID) MarshalBinary() (data []byte, err error) {
	suffix := id.id[idByteLen-1]
	if suffix != idSuffix && suffix != pubIDSuffix &&
		suffix != singleTeamIDSuffix {
		return nil, errors.WithStack(InvalidIDError{id.String()})
	}
	return id.id[:], nil
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for ID.
func (id *ID) UnmarshalBinary(data []byte) error {
	if len(data) != idByteLen {
		return errors.WithStack(
			InvalidIDError{hex.EncodeToString(data)})
	}
	suffix := data[idByteLen-1]
	if suffix != idSuffix && suffix != pubIDSuffix &&
		suffix != singleTeamIDSuffix {
		return errors.WithStack(
			InvalidIDError{hex.EncodeToString(data)})
	}
	copy(id.id[:], data)
	return nil
}

// MarshalText implements the encoding.TextMarshaler interface for ID.
func (id ID) MarshalText() ([]byte, error) {
	bytes, err := id.MarshalBinary()
	if err != nil {
		return nil, err
	}
	return []byte(hex.EncodeToString(bytes)), nil
}

// UnmarshalText implements the encoding.TextUnmarshaler interface for
// ID.
func (id *ID) UnmarshalText(buf []byte) error {
	s := string(buf)
	bytes, err := hex.DecodeString(s)
	if err != nil {
		return errors.WithStack(InvalidIDError{s})
	}
	return id.UnmarshalBinary(bytes)
}

// Type returns the type of TLF represented by this ID.
func (id ID) Type() Type {
	switch id.id[idByteLen-1] {
	case idSuffix:
		return Private
	case pubIDSuffix:
		return Public
	case singleTeamIDSuffix:
		return SingleTeam
	default:
		panic(fmt.Sprintf("Unknown ID suffix  %x", id.id[idByteLen-1]))
	}
}

// ParseID parses a hex encoded ID. Returns NullID and an
// InvalidIDError on failure.
func ParseID(s string) (ID, error) {
	var id ID
	err := id.UnmarshalText([]byte(s))
	if err != nil {
		return ID{}, err
	}
	return id, nil
}

// MakeRandomID makes a random ID using a cryptographically secure
// RNG. Returns NullID on failure.
func MakeRandomID(t Type) (ID, error) {
	var idBytes [idByteLen]byte
	err := kbfscrypto.RandRead(idBytes[:])
	if err != nil {
		return NullID, err
	}
	switch t {
	case Private:
		idBytes[idByteLen-1] = idSuffix
	case Public:
		idBytes[idByteLen-1] = pubIDSuffix
	case SingleTeam:
		idBytes[idByteLen-1] = singleTeamIDSuffix
	default:
		panic(fmt.Sprintf("Unknown TLF type %d", t))
	}
	var id ID
	err = id.UnmarshalBinary(idBytes[:])
	if err != nil {
		return NullID, err
	}
	return id, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"sort"
	"strings"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/go-homedir"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
)

func resourceAwsS3BucketObject() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsS3BucketObjectPut,
		Read:   resourceAwsS3BucketObjectRead,
		Update: resourceAwsS3BucketObjectPut,
		Delete: resourceAwsS3BucketObjectDelete,

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

			"acl": &schema.Schema{
				Type:         schema.TypeString,
				Default:      "private",
				Optional:     true,
				ValidateFunc: validateS3BucketObjectAclType,
			},

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

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

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

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

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

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

			"source": &schema.Schema{
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"content"},
			},

			"content": &schema.Schema{
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"source"},
			},

			"storage_class": &schema.Schema{
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validateS3BucketObjectStorageClassType,
			},

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

			"etag": &schema.Schema{
				Type: schema.TypeString,
				// This will conflict with SSE-C and SSE-KMS encryption and multi-part upload
				// if/when it's actually implemented. The Etag then won't match raw-file MD5.
				// See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html
				Optional:      true,
				Computed:      true,
				ConflictsWith: []string{"kms_key_id"},
			},

			"version_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsS3BucketObjectPut(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	var body io.ReadSeeker

	if v, ok := d.GetOk("source"); ok {
		source := v.(string)
		path, err := homedir.Expand(source)
		if err != nil {
			return fmt.Errorf("Error expanding homedir in source (%s): %s", source, err)
		}
		file, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening S3 bucket object source (%s): %s", source, err)
		}

		body = file
	} else if v, ok := d.GetOk("content"); ok {
		content := v.(string)
		body = bytes.NewReader([]byte(content))
	} else {
		return fmt.Errorf("Must specify \"source\" or \"content\" field")
	}

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)

	putInput := &s3.PutObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
		ACL:    aws.String(d.Get("acl").(string)),
		Body:   body,
	}

	if v, ok := d.GetOk("storage_class"); ok {
		putInput.StorageClass = aws.String(v.(string))
	}

	if v, ok := d.GetOk("cache_control"); ok {
		putInput.CacheControl = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_type"); ok {
		putInput.ContentType = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_encoding"); ok {
		putInput.ContentEncoding = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_language"); ok {
		putInput.ContentLanguage = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_disposition"); ok {
		putInput.ContentDisposition = aws.String(v.(string))
	}

	if v, ok := d.GetOk("kms_key_id"); ok {
		putInput.SSEKMSKeyId = aws.String(v.(string))
		putInput.ServerSideEncryption = aws.String("aws:kms")
	}

	resp, err := s3conn.PutObject(putInput)
	if err != nil {
		return fmt.Errorf("Error putting object in S3 bucket (%s): %s", bucket, err)
	}

	// See https://forums.aws.amazon.com/thread.jspa?threadID=44003
	d.Set("etag", strings.Trim(*resp.ETag, `"`))

	d.Set("version_id", resp.VersionId)
	d.SetId(key)
	return resourceAwsS3BucketObjectRead(d, meta)
}

func resourceAwsS3BucketObjectRead(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)
	etag := d.Get("etag").(string)

	resp, err := s3conn.HeadObject(
		&s3.HeadObjectInput{
			Bucket:  aws.String(bucket),
			Key:     aws.String(key),
			IfMatch: aws.String(etag),
		})

	if err != nil {
		// If S3 returns a 404 Request Failure, mark the object as destroyed
		if awsErr, ok := err.(awserr.RequestFailure); ok && awsErr.StatusCode() == 404 {
			d.SetId("")
			log.Printf("[WARN] Error Reading Object (%s), object not found (HTTP status 404)", key)
			return nil
		}
		return err
	}
	log.Printf("[DEBUG] Reading S3 Bucket Object meta: %s", resp)

	d.Set("cache_control", resp.CacheControl)
	d.Set("content_disposition", resp.ContentDisposition)
	d.Set("content_encoding", resp.ContentEncoding)
	d.Set("content_language", resp.ContentLanguage)
	d.Set("content_type", resp.ContentType)
	d.Set("version_id", resp.VersionId)
	d.Set("kms_key_id", resp.SSEKMSKeyId)

	// The "STANDARD" (which is also the default) storage
	// class when set would not be included in the results.
	d.Set("storage_class", s3.StorageClassStandard)
	if resp.StorageClass != nil {
		d.Set("storage_class", resp.StorageClass)
	}

	return nil
}

func resourceAwsS3BucketObjectDelete(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)

	if _, ok := d.GetOk("version_id"); ok {
		// Bucket is versioned, we need to delete all versions
		vInput := s3.ListObjectVersionsInput{
			Bucket: aws.String(bucket),
			Prefix: aws.String(key),
		}
		out, err := s3conn.ListObjectVersions(&vInput)
		if err != nil {
			return fmt.Errorf("Failed listing S3 object versions: %s", err)
		}

		for _, v := range out.Versions {
			input := s3.DeleteObjectInput{
				Bucket:    aws.String(bucket),
				Key:       aws.String(key),
				VersionId: v.VersionId,
			}
			_, err := s3conn.DeleteObject(&input)
			if err != nil {
				return fmt.Errorf("Error deleting S3 object version of %s:\n %s:\n %s",
					key, v, err)
			}
		}
	} else {
		// Just delete the object
		input := s3.DeleteObjectInput{
			Bucket: aws.String(bucket),
			Key:    aws.String(key),
		}
		_, err := s3conn.DeleteObject(&input)
		if err != nil {
			return fmt.Errorf("Error deleting S3 bucket object: %s", err)
		}
	}

	return nil
}

func validateS3BucketObjectAclType(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)

	cannedAcls := map[string]bool{
		s3.ObjectCannedACLPrivate:                true,
		s3.ObjectCannedACLPublicRead:             true,
		s3.ObjectCannedACLPublicReadWrite:        true,
		s3.ObjectCannedACLAuthenticatedRead:      true,
		s3.ObjectCannedACLAwsExecRead:            true,
		s3.ObjectCannedACLBucketOwnerRead:        true,
		s3.ObjectCannedACLBucketOwnerFullControl: true,
	}

	sentenceJoin := func(m map[string]bool) string {
		keys := make([]string, 0, len(m))
		for k := range m {
			keys = append(keys, fmt.Sprintf("%q", k))
		}
		sort.Strings(keys)

		length := len(keys)
		words := make([]string, length)
		copy(words, keys)

		words[length-1] = fmt.Sprintf("or %s", words[length-1])
		return strings.Join(words, ", ")
	}

	if _, ok := cannedAcls[value]; !ok {
		errors = append(errors, fmt.Errorf(
			"%q contains an invalid canned ACL type %q. Valid types are either %s",
			k, value, sentenceJoin(cannedAcls)))
	}
	return
}

func validateS3BucketObjectStorageClassType(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)

	storageClass := map[string]bool{
		s3.StorageClassStandard:          true,
		s3.StorageClassReducedRedundancy: true,
		s3.StorageClassStandardIa:        true,
	}

	if _, ok := storageClass[value]; !ok {
		errors = append(errors, fmt.Errorf(
			"%q contains an invalid Storage Class type %q. Valid types are either %q, %q, or %q",
			k, value, s3.StorageClassStandard, s3.StorageClassReducedRedundancy,
			s3.StorageClassStandardIa))
	}
	return
}
<commit_msg>Remove If-Match check and update ETag in state based on HeadObject<commit_after>package aws

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"sort"
	"strings"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/go-homedir"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
)

func resourceAwsS3BucketObject() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsS3BucketObjectPut,
		Read:   resourceAwsS3BucketObjectRead,
		Update: resourceAwsS3BucketObjectPut,
		Delete: resourceAwsS3BucketObjectDelete,

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

			"acl": &schema.Schema{
				Type:         schema.TypeString,
				Default:      "private",
				Optional:     true,
				ValidateFunc: validateS3BucketObjectAclType,
			},

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

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

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

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

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

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

			"source": &schema.Schema{
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"content"},
			},

			"content": &schema.Schema{
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"source"},
			},

			"storage_class": &schema.Schema{
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validateS3BucketObjectStorageClassType,
			},

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

			"etag": &schema.Schema{
				Type: schema.TypeString,
				// This will conflict with SSE-C and SSE-KMS encryption and multi-part upload
				// if/when it's actually implemented. The Etag then won't match raw-file MD5.
				// See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html
				Optional:      true,
				Computed:      true,
				ConflictsWith: []string{"kms_key_id"},
			},

			"version_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsS3BucketObjectPut(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	var body io.ReadSeeker

	if v, ok := d.GetOk("source"); ok {
		source := v.(string)
		path, err := homedir.Expand(source)
		if err != nil {
			return fmt.Errorf("Error expanding homedir in source (%s): %s", source, err)
		}
		file, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening S3 bucket object source (%s): %s", source, err)
		}

		body = file
	} else if v, ok := d.GetOk("content"); ok {
		content := v.(string)
		body = bytes.NewReader([]byte(content))
	} else {
		return fmt.Errorf("Must specify \"source\" or \"content\" field")
	}

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)

	putInput := &s3.PutObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
		ACL:    aws.String(d.Get("acl").(string)),
		Body:   body,
	}

	if v, ok := d.GetOk("storage_class"); ok {
		putInput.StorageClass = aws.String(v.(string))
	}

	if v, ok := d.GetOk("cache_control"); ok {
		putInput.CacheControl = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_type"); ok {
		putInput.ContentType = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_encoding"); ok {
		putInput.ContentEncoding = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_language"); ok {
		putInput.ContentLanguage = aws.String(v.(string))
	}

	if v, ok := d.GetOk("content_disposition"); ok {
		putInput.ContentDisposition = aws.String(v.(string))
	}

	if v, ok := d.GetOk("kms_key_id"); ok {
		putInput.SSEKMSKeyId = aws.String(v.(string))
		putInput.ServerSideEncryption = aws.String("aws:kms")
	}

	resp, err := s3conn.PutObject(putInput)
	if err != nil {
		return fmt.Errorf("Error putting object in S3 bucket (%s): %s", bucket, err)
	}

	// See https://forums.aws.amazon.com/thread.jspa?threadID=44003
	d.Set("etag", strings.Trim(*resp.ETag, `"`))

	d.Set("version_id", resp.VersionId)
	d.SetId(key)
	return resourceAwsS3BucketObjectRead(d, meta)
}

func resourceAwsS3BucketObjectRead(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)

	resp, err := s3conn.HeadObject(
		&s3.HeadObjectInput{
			Bucket: aws.String(bucket),
			Key:    aws.String(key),
		})

	if err != nil {
		// If S3 returns a 404 Request Failure, mark the object as destroyed
		if awsErr, ok := err.(awserr.RequestFailure); ok && awsErr.StatusCode() == 404 {
			d.SetId("")
			log.Printf("[WARN] Error Reading Object (%s), object not found (HTTP status 404)", key)
			return nil
		}
		return err
	}
	log.Printf("[DEBUG] Reading S3 Bucket Object meta: %s", resp)

	d.Set("cache_control", resp.CacheControl)
	d.Set("content_disposition", resp.ContentDisposition)
	d.Set("content_encoding", resp.ContentEncoding)
	d.Set("content_language", resp.ContentLanguage)
	d.Set("content_type", resp.ContentType)
	d.Set("version_id", resp.VersionId)
	d.Set("kms_key_id", resp.SSEKMSKeyId)
	d.Set("etag", strings.Trim(*resp.ETag, `"`))

	// The "STANDARD" (which is also the default) storage
	// class when set would not be included in the results.
	d.Set("storage_class", s3.StorageClassStandard)
	if resp.StorageClass != nil {
		d.Set("storage_class", resp.StorageClass)
	}

	return nil
}

func resourceAwsS3BucketObjectDelete(d *schema.ResourceData, meta interface{}) error {
	s3conn := meta.(*AWSClient).s3conn

	bucket := d.Get("bucket").(string)
	key := d.Get("key").(string)

	if _, ok := d.GetOk("version_id"); ok {
		// Bucket is versioned, we need to delete all versions
		vInput := s3.ListObjectVersionsInput{
			Bucket: aws.String(bucket),
			Prefix: aws.String(key),
		}
		out, err := s3conn.ListObjectVersions(&vInput)
		if err != nil {
			return fmt.Errorf("Failed listing S3 object versions: %s", err)
		}

		for _, v := range out.Versions {
			input := s3.DeleteObjectInput{
				Bucket:    aws.String(bucket),
				Key:       aws.String(key),
				VersionId: v.VersionId,
			}
			_, err := s3conn.DeleteObject(&input)
			if err != nil {
				return fmt.Errorf("Error deleting S3 object version of %s:\n %s:\n %s",
					key, v, err)
			}
		}
	} else {
		// Just delete the object
		input := s3.DeleteObjectInput{
			Bucket: aws.String(bucket),
			Key:    aws.String(key),
		}
		_, err := s3conn.DeleteObject(&input)
		if err != nil {
			return fmt.Errorf("Error deleting S3 bucket object: %s", err)
		}
	}

	return nil
}

func validateS3BucketObjectAclType(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)

	cannedAcls := map[string]bool{
		s3.ObjectCannedACLPrivate:                true,
		s3.ObjectCannedACLPublicRead:             true,
		s3.ObjectCannedACLPublicReadWrite:        true,
		s3.ObjectCannedACLAuthenticatedRead:      true,
		s3.ObjectCannedACLAwsExecRead:            true,
		s3.ObjectCannedACLBucketOwnerRead:        true,
		s3.ObjectCannedACLBucketOwnerFullControl: true,
	}

	sentenceJoin := func(m map[string]bool) string {
		keys := make([]string, 0, len(m))
		for k := range m {
			keys = append(keys, fmt.Sprintf("%q", k))
		}
		sort.Strings(keys)

		length := len(keys)
		words := make([]string, length)
		copy(words, keys)

		words[length-1] = fmt.Sprintf("or %s", words[length-1])
		return strings.Join(words, ", ")
	}

	if _, ok := cannedAcls[value]; !ok {
		errors = append(errors, fmt.Errorf(
			"%q contains an invalid canned ACL type %q. Valid types are either %s",
			k, value, sentenceJoin(cannedAcls)))
	}
	return
}

func validateS3BucketObjectStorageClassType(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)

	storageClass := map[string]bool{
		s3.StorageClassStandard:          true,
		s3.StorageClassReducedRedundancy: true,
		s3.StorageClassStandardIa:        true,
	}

	if _, ok := storageClass[value]; !ok {
		errors = append(errors, fmt.Errorf(
			"%q contains an invalid Storage Class type %q. Valid types are either %q, %q, or %q",
			k, value, s3.StorageClassStandard, s3.StorageClassReducedRedundancy,
			s3.StorageClassStandardIa))
	}
	return
}
<|endoftext|>


<commit_before>package lexer

import "strings"

// NOTE: The code below was HEAVILY influenced by how InfluxDB's parser
// handles lexical tokens.
// You can find the code here: https://github.com/influxdb/influxdb/blob/master/influxql/token.go

// Pos specifies the line and character position of a token.
// The Char and Line are both zero-based indexes.
type Pos struct {
	Line int
	Char int
}

// Token represents each lexer symbol
type Token int

// Token enums
const (
	ILLEGAL Token = iota
	EOF
	WS

	// Punctuation

	LPAREN      // (
	RPAREN      // )
	LBRACKET    // [
	RBRACKET    // ]
	LCURLY      // {
	RCURLY      // }
	COMMA       // ,
	SEMICOLON   // ;
	COLON       // :
	DOT         // .
	SINGLEQUOTE // '
	DOUBLEQUOTE // "
	PERCENT     // %
	DOLLAR      // $
	HASH        // #
	ATSIGN      // @

	// Literals

	startLiterals
	IDENT
	NUMBER
	STRING
	BADSTRING
	BADESCAPE
	TRUE
	FALSE
	REGEX
	BADREGEX
	DURATION_VAL
	endLiterals

	// Operators

	startOperators
	PLUS      // +
	MINUS     // -
	MUL       // *
	DIV       // /
	AMPERSAND // &
	XOR       // ^
	PIPE      // |
	LSHIFT    // <<
	RSHIFT    // >>

	AND // AND
	OR  // OR

	EQ       // =
	NEQ      // !=
	EQREGEX  // =~
	NEQREGEX // !~
	LT       // <
	LTE      // <=
	GT       // >
	GTE      // >=
	endOperators
)

var tokens = map[Token]string{
	ILLEGAL: "ILLEGAL",
	EOF:     "EOF",
	WS:      "WS",

	LPAREN:      "(",
	RPAREN:      ")",
	LBRACKET:    "[",
	RBRACKET:    "]",
	LCURLY:      "{",
	RCURLY:      "}",
	COMMA:       ",",
	SEMICOLON:   ";",
	COLON:       ":",
	DOT:         ".",
	SINGLEQUOTE: "'",
	DOUBLEQUOTE: "\"",
	PERCENT:     "%%",
	DOLLAR:      "$",
	HASH:        "#",
	ATSIGN:      "@",

	IDENT:     "IDENT",
	NUMBER:    "NUM",
	STRING:    "TEXTUAL",
	BADSTRING: "BADSTRING",
	BADESCAPE: "BADESCAPE",
	REGEX:     "REGEX",
	BADREGEX:  "BADREGEX",

	PLUS:      "+",
	MINUS:     "-",
	MUL:       "*",
	DIV:       "/",
	AMPERSAND: "&",
	XOR:       "^",
	PIPE:      "|",
	RSHIFT:    ">>",
	LSHIFT:    "<<",

	AND: "AND",
	OR:  "OR",

	TRUE:  "true",
	FALSE: "false",

	EQ:       "=",
	NEQ:      "!=",
	EQREGEX:  "=~",
	NEQREGEX: "!~",

	LT:  "<",
	LTE: "<=",
	GT:  ">",
	GTE: ">=",
}

var keywords = map[string]Token{}

func init() {
	keywords["and"] = AND
	keywords["or"] = OR
	keywords["true"] = TRUE
	keywords["false"] = FALSE
}

// LoadTokenMap allows for extra keywords to be added to the lexer
func LoadTokenMap(keywordTokens map[Token]string) {

	// Combine built-in tokens and keywords
	for k, v := range keywordTokens {
		tokens[k] = v
	}

	// Load Keywords
	for k, v := range keywordTokens {
		keywords[strings.ToLower(v)] = k
	}
}

// String returns the string representation of the token.
func (tok Token) String() string {
	if _, ok := tokens[tok]; ok {
		return tokens[tok]
	}
	return ""
}

// Precedence returns the operator precedence of the binary operator token.
func (tok Token) Precedence() int {
	switch tok {
	case OR:
		return 1
	case AND:
		return 2
	case EQ, NEQ, EQREGEX, NEQREGEX, LT, LTE, GT, GTE:
		return 3
	case PLUS, MINUS:
		return 4
	case MUL, DIV:
		return 5
	case PIPE, XOR, RSHIFT, LSHIFT:
		return 6
	}
	return 0
}

// isOperator returns true for operator tokens.
func (tok Token) isOperator() bool { return tok > startOperators && tok < endOperators }

// tokstr returns a literal if provided, otherwise returns the token string.
func tokstr(tok Token, lit string) string {
	if lit != "" {
		return lit
	}
	return tok.String()
}

// Lookup returns the token associated with a given string.
func Lookup(ident string) Token {
	if tok, ok := keywords[strings.ToLower(ident)]; ok {
		return tok
	}
	return IDENT
}
<commit_msg>Update tokens.go<commit_after>package lexer

import "strings"

// NOTE: The code below was HEAVILY influenced by how InfluxDB's parser
// handles lexical tokens.
// You can find the code here: https://github.com/influxdb/influxdb/blob/master/influxql/token.go

// Pos specifies the line and character position of a token.
// The Char and Line are both zero-based indexes.
type Pos struct {
	Line int
	Char int
}

// Token represents each lexer symbol
type Token int

// Token enums
const (
	ILLEGAL Token = iota
	EOF
	WS

	// Punctuation

	LPAREN      // (
	RPAREN      // )
	LBRACKET    // [
	RBRACKET    // ]
	LCURLY      // {
	RCURLY      // }
	COMMA       // ,
	SEMICOLON   // ;
	COLON       // :
	DOT         // .
	SINGLEQUOTE // '
	DOUBLEQUOTE // "
	PERCENT     // %
	DOLLAR      // $
	HASH        // #
	ATSIGN      // @

	// Literals

	startLiterals
	IDENT
	NUMBER
	STRING
	BADSTRING
	BADESCAPE
	TRUE
	FALSE
	REGEX
	BADREGEX
	DURATION_VAL
	endLiterals

	// Operators

	startOperators
	PLUS      // +
	MINUS     // -
	MUL       // *
	DIV       // /
	AMPERSAND // &
	XOR       // ^
	PIPE      // |
	LSHIFT    // <<
	RSHIFT    // >>
	POW       // **

	ARROW       // ->
	EQARROW     // =>

	AND // AND
	OR  // OR

	EQ       // =
	NEQ      // !=
	EQREGEX  // =~
	NEQREGEX // !~
	LT       // <
	LTE      // <=
	GT       // >
	GTE      // >=
	endOperators
)

var tokens = map[Token]string{
	ILLEGAL: "ILLEGAL",
	EOF:     "EOF",
	WS:      "WS",

	LPAREN:      "(",
	RPAREN:      ")",
	LBRACKET:    "[",
	RBRACKET:    "]",
	LCURLY:      "{",
	RCURLY:      "}",
	COMMA:       ",",
	SEMICOLON:   ";",
	COLON:       ":",
	DOT:         ".",
	SINGLEQUOTE: "'",
	DOUBLEQUOTE: "\"",
	PERCENT:     "%%",
	DOLLAR:      "$",
	HASH:        "#",
	ATSIGN:      "@",

	IDENT:     "IDENT",
	NUMBER:    "NUM",
	STRING:    "TEXTUAL",
	BADSTRING: "BADSTRING",
	BADESCAPE: "BADESCAPE",
	REGEX:     "REGEX",
	BADREGEX:  "BADREGEX",

	PLUS:      "+",
	MINUS:     "-",
	MUL:       "*",
	DIV:       "/",
	AMPERSAND: "&",
	XOR:       "^",
	PIPE:      "|",
	RSHIFT:    ">>",
	LSHIFT:    "<<",
	POW:       "**",
	ARROW:     "->",
	EQARROW:   "=>",

	AND: "AND",
	OR:  "OR",

	TRUE:  "true",
	FALSE: "false",

	EQ:       "=",
	NEQ:      "!=",
	EQREGEX:  "=~",
	NEQREGEX: "!~",

	LT:  "<",
	LTE: "<=",
	GT:  ">",
	GTE: ">=",
}

var keywords = map[string]Token{}

func init() {
	keywords["and"] = AND
	keywords["or"] = OR
	keywords["true"] = TRUE
	keywords["false"] = FALSE
}

// LoadTokenMap allows for extra keywords to be added to the lexer
func LoadTokenMap(keywordTokens map[Token]string) {

	// Combine built-in tokens and keywords
	for k, v := range keywordTokens {
		tokens[k] = v
	}

	// Load Keywords
	for k, v := range keywordTokens {
		keywords[strings.ToLower(v)] = k
	}
}

// String returns the string representation of the token.
func (tok Token) String() string {
	if _, ok := tokens[tok]; ok {
		return tokens[tok]
	}
	return ""
}

// Precedence returns the operator precedence of the binary operator token.
func (tok Token) Precedence() int {
	switch tok {
	case OR:
		return 1
	case AND:
		return 2
	case EQ, NEQ, EQREGEX, NEQREGEX, LT, LTE, GT, GTE:
		return 3
	case PLUS, MINUS:
		return 4
	case MUL, DIV:
		return 5
	case PIPE, XOR, RSHIFT, LSHIFT, POW:
		return 6
	}
	return 0
}

// isOperator returns true for operator tokens.
func (tok Token) isOperator() bool { return tok > startOperators && tok < endOperators }

// tokstr returns a literal if provided, otherwise returns the token string.
func tokstr(tok Token, lit string) string {
	if lit != "" {
		return lit
	}
	return tok.String()
}

// Lookup returns the token associated with a given string.
func Lookup(ident string) Token {
	if tok, ok := keywords[strings.ToLower(ident)]; ok {
		return tok
	}
	return IDENT
}
<|endoftext|>


<commit_before>package client

import (
	"errors"
	"fmt"

	"golang.org/x/net/context"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

type CmdGitCreate struct {
	libkb.Contextified
	repoName   keybase1.GitRepoName
	teamName   keybase1.TeamName
	skipNotify bool
}

func newCmdGitCreate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "create",
		ArgumentHelp: "<repo name> [--team=<team name>]",
		Usage:        "Create a personal or team git repository.",
		Description:  "`keybase git create reponame` will create a personal git repo.\n   `keybase git create reponame --team=treehouse` will create a\n   team git repo for the `treehouse` team.",
		Action: func(c *cli.Context) {
			cmd := NewCmdGitCreateRunner(g)
			cl.ChooseCommand(cmd, "create", c)
		},
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "team",
				Usage: "keybase team name (optional)",
			},
			cli.BoolFlag{
				Name:  "skip-notify",
				Usage: "skip posting new repo notifications for team members",
			},
		},
	}
}

func NewCmdGitCreateRunner(g *libkb.GlobalContext) *CmdGitCreate {
	return &CmdGitCreate{Contextified: libkb.NewContextified(g)}
}

func (c *CmdGitCreate) ParseArgv(ctx *cli.Context) error {
	if len(ctx.Args()) == 0 {
		return errors.New("repo name argument required")
	}
	c.repoName = keybase1.GitRepoName(ctx.Args()[0])
	c.skipNotify = ctx.Bool("skip-notify")
	if len(ctx.String("team")) > 0 {
		teamName, err := keybase1.TeamNameFromString(ctx.String("team"))
		if err != nil {
			return err
		}
		c.teamName = teamName
	}

	return nil
}

func (c *CmdGitCreate) Run() error {
	cli, err := GetGitClient(c.G())
	if err != nil {
		return err
	}

	var urlString string
	if len(c.teamName.String()) > 0 {
		urlString, err = c.runTeam(cli)
	} else {
		urlString, err = c.runPersonal(cli)
	}

	if err != nil {
		fmt.Printf("%#v\n", err)
		return err
	}

	dui := c.G().UI.GetDumbOutputUI()
	dui.Printf("Repo created! You can clone it with:\n  git clone %s\n", urlString)
	return nil
}

func (c *CmdGitCreate) runPersonal(cli keybase1.GitClient) (string, error) {
	if _, err := cli.CreatePersonalRepo(context.Background(), c.repoName); err != nil {
		return "", err
	}
	return fmt.Sprintf("keybase://private/%s/%s", c.G().Env.GetUsername(), c.repoName), nil
}

func (c *CmdGitCreate) runTeam(cli keybase1.GitClient) (string, error) {
	arg := keybase1.CreateTeamRepoArg{
		TeamName:   c.teamName,
		RepoName:   c.repoName,
		NotifyTeam: !c.skipNotify,
	}
	if _, err := cli.CreateTeamRepo(context.Background(), arg); err != nil {
		return "", err
	}
	return fmt.Sprintf("keybase://team/%s/%s", c.teamName, c.repoName), nil
}

func (c *CmdGitCreate) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
}
<commit_msg>Remove error print<commit_after>package client

import (
	"errors"
	"fmt"

	"golang.org/x/net/context"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

type CmdGitCreate struct {
	libkb.Contextified
	repoName   keybase1.GitRepoName
	teamName   keybase1.TeamName
	skipNotify bool
}

func newCmdGitCreate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "create",
		ArgumentHelp: "<repo name> [--team=<team name>]",
		Usage:        "Create a personal or team git repository.",
		Description:  "`keybase git create reponame` will create a personal git repo.\n   `keybase git create reponame --team=treehouse` will create a\n   team git repo for the `treehouse` team.",
		Action: func(c *cli.Context) {
			cmd := NewCmdGitCreateRunner(g)
			cl.ChooseCommand(cmd, "create", c)
		},
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "team",
				Usage: "keybase team name (optional)",
			},
			cli.BoolFlag{
				Name:  "skip-notify",
				Usage: "skip posting new repo notifications for team members",
			},
		},
	}
}

func NewCmdGitCreateRunner(g *libkb.GlobalContext) *CmdGitCreate {
	return &CmdGitCreate{Contextified: libkb.NewContextified(g)}
}

func (c *CmdGitCreate) ParseArgv(ctx *cli.Context) error {
	if len(ctx.Args()) == 0 {
		return errors.New("repo name argument required")
	}
	c.repoName = keybase1.GitRepoName(ctx.Args()[0])
	c.skipNotify = ctx.Bool("skip-notify")
	if len(ctx.String("team")) > 0 {
		teamName, err := keybase1.TeamNameFromString(ctx.String("team"))
		if err != nil {
			return err
		}
		c.teamName = teamName
	}

	return nil
}

func (c *CmdGitCreate) Run() error {
	cli, err := GetGitClient(c.G())
	if err != nil {
		return err
	}

	var urlString string
	if len(c.teamName.String()) > 0 {
		urlString, err = c.runTeam(cli)
	} else {
		urlString, err = c.runPersonal(cli)
	}

	if err != nil {
		return err
	}

	dui := c.G().UI.GetDumbOutputUI()
	dui.Printf("Repo created! You can clone it with:\n  git clone %s\n", urlString)
	return nil
}

func (c *CmdGitCreate) runPersonal(cli keybase1.GitClient) (string, error) {
	if _, err := cli.CreatePersonalRepo(context.Background(), c.repoName); err != nil {
		return "", err
	}
	return fmt.Sprintf("keybase://private/%s/%s", c.G().Env.GetUsername(), c.repoName), nil
}

func (c *CmdGitCreate) runTeam(cli keybase1.GitClient) (string, error) {
	arg := keybase1.CreateTeamRepoArg{
		TeamName:   c.teamName,
		RepoName:   c.repoName,
		NotifyTeam: !c.skipNotify,
	}
	if _, err := cli.CreateTeamRepo(context.Background(), arg); err != nil {
		return "", err
	}
	return fmt.Sprintf("keybase://team/%s/%s", c.teamName, c.repoName), nil
}

func (c *CmdGitCreate) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.

package grpc_ctxtags

import (
	"reflect"
)

// RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
// It is called from tags middleware on arrival of unary request or a server-stream request.
// Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}

type requestFieldsExtractor interface {
	// ExtractRequestFields is a method declared on a Protobuf message that extracts fields from the interface.
	// The values from the extracted fields should be set in the appendToMap, in order to avoid allocations.
	ExtractRequestFields(appendToMap map[string]interface{})
}

// CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
// These are usually coming from a protoc-plugin that generates additional information based on custom field options.
func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
	if ext, ok := req.(requestFieldsExtractor); ok {
		retMap := make(map[string]interface{})
		ext.ExtractRequestFields(retMap)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
	return nil
}

// TagBasedRequestFieldExtractor is a function that relies on Go struct tags to export log fields from requests.
// These are usually coming from a protoc-plugin, such as Gogo protobuf.
//
//  message Metadata {
//     repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
//  }
//
// The tagName is configurable using the tagName variable. Here it would be "log_field".
func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc {
	return func(fullMethod string, req interface{}) map[string]interface{} {
		retMap := make(map[string]interface{})
		reflectMessageTags(req, retMap, tagName)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
}

func reflectMessageTags(msg interface{}, existingMap map[string]interface{}, tagName string) {
	v := reflect.ValueOf(msg)
	// Only deal with pointers to structs.
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		return
	}
	// Deref the pointer get to the struct.
	v = v.Elem()
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		kind := field.Kind()
		// Only recurse down direct pointers, which should only be to nested structs.
		if kind == reflect.Ptr {
			reflectMessageTags(field.Interface(), existingMap, tagName)
		}
		// In case of arrays/splices (repeated fields) go down to the concrete type.
		if kind == reflect.Array || kind == reflect.Slice {
			if field.Len() == 0 {
				continue
			}
			kind = field.Index(0).Kind()
		}
		// Only be interested in
		if (kind >= reflect.Bool && kind <= reflect.Float64) || kind == reflect.String {
			if tag := t.Field(i).Tag.Get(tagName); tag != "" {
				existingMap[tag] = field.Interface()
			}
		}
	}
	return
}
<commit_msg>Fix panic in TagBasedRequestFieldExtractor when gogoproto.stdtime is used.<commit_after>// Copyright 2017 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.

package grpc_ctxtags

import (
	"reflect"
)

// RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
// It is called from tags middleware on arrival of unary request or a server-stream request.
// Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}

type requestFieldsExtractor interface {
	// ExtractRequestFields is a method declared on a Protobuf message that extracts fields from the interface.
	// The values from the extracted fields should be set in the appendToMap, in order to avoid allocations.
	ExtractRequestFields(appendToMap map[string]interface{})
}

// CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
// These are usually coming from a protoc-plugin that generates additional information based on custom field options.
func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
	if ext, ok := req.(requestFieldsExtractor); ok {
		retMap := make(map[string]interface{})
		ext.ExtractRequestFields(retMap)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
	return nil
}

// TagBasedRequestFieldExtractor is a function that relies on Go struct tags to export log fields from requests.
// These are usually coming from a protoc-plugin, such as Gogo protobuf.
//
//  message Metadata {
//     repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
//  }
//
// The tagName is configurable using the tagName variable. Here it would be "log_field".
func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc {
	return func(fullMethod string, req interface{}) map[string]interface{} {
		retMap := make(map[string]interface{})
		reflectMessageTags(req, retMap, tagName)
		if len(retMap) == 0 {
			return nil
		}
		return retMap
	}
}

func reflectMessageTags(msg interface{}, existingMap map[string]interface{}, tagName string) {
	v := reflect.ValueOf(msg)
	// Only deal with pointers to structs.
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		return
	}
	// Deref the pointer get to the struct.
	v = v.Elem()
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		kind := field.Kind()
		// Only recurse down direct pointers, which should only be to nested structs.
		if kind == reflect.Ptr && field.CanInterface() {
			reflectMessageTags(field.Interface(), existingMap, tagName)
		}
		// In case of arrays/splices (repeated fields) go down to the concrete type.
		if kind == reflect.Array || kind == reflect.Slice {
			if field.Len() == 0 {
				continue
			}
			kind = field.Index(0).Kind()
		}
		// Only be interested in
		if (kind >= reflect.Bool && kind <= reflect.Float64) || kind == reflect.String {
			if tag := t.Field(i).Tag.Get(tagName); tag != "" {
				existingMap[tag] = field.Interface()
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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 apiconfig

import (
	"fmt"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/cmd/kubeadm/app/master"
	"k8s.io/kubernetes/pkg/api"
	rbac "k8s.io/kubernetes/pkg/apis/rbac/v1beta1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

// CreateBootstrapRBACClusterRole creates the necessary ClusterRole for bootstrapping
func CreateBootstrapRBACClusterRole(clientset *clientset.Clientset) error {
	clusterRole := rbac.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{Name: "kubeadm:kubelet-bootstrap"},
		Rules: []rbac.PolicyRule{
			rbac.NewRule("get").Groups("").Resources("nodes").RuleOrDie(),
			rbac.NewRule("create", "watch").Groups("certificates.k8s.io").Resources("certificatesigningrequests").RuleOrDie(),
		},
	}
	if _, err := clientset.Rbac().ClusterRoles().Create(&clusterRole); err != nil {
		return err
	}

	subject := rbac.Subject{
		Kind: "Group",
		Name: "kubeadm:kubelet-bootstrap",
	}

	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "kubeadm:kubelet-bootstrap",
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "kubeadm:kubelet-bootstrap",
		},
		Subjects: []rbac.Subject{subject},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created kubelet-bootstrap RBAC rules")

	return nil
}

// CreateKubeDNSRBACClusterRole creates the necessary ClusterRole for kube-dns
func CreateKubeDNSRBACClusterRole(clientset *clientset.Clientset) error {
	clusterRole := rbac.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{Name: "kubeadm:" + master.KubeDNS},
		Rules: []rbac.PolicyRule{
			rbac.NewRule("list", "watch").Groups("").Resources("endpoints", "services").RuleOrDie(),
			// TODO: remove watch rule when https://github.com/kubernetes/kubernetes/pull/38816 gets merged
			rbac.NewRule("get", "list", "watch").Groups("").Resources("configmaps").RuleOrDie(),
		},
	}
	if _, err := clientset.Rbac().ClusterRoles().Create(&clusterRole); err != nil {
		return err
	}

	subject := rbac.Subject{
		Kind:      "ServiceAccount",
		Name:      master.KubeDNS,
		Namespace: api.NamespaceSystem,
	}

	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "kubeadm:" + master.KubeDNS,
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "kubeadm:" + master.KubeDNS,
		},
		Subjects: []rbac.Subject{subject},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created kube-dns RBAC rules")

	return nil
}

// CreateKubeProxyClusterRoleBinding creates the necessary ClusterRole for kube-dns
func CreateKubeProxyClusterRoleBinding(clientset *clientset.Clientset) error {
	systemKubeProxySubject := rbac.Subject{
		Kind:      "User",
		Name:      "system:kube-proxy",
		Namespace: api.NamespaceSystem,
	}

	systemNodesSubject := rbac.Subject{
		Kind:      "Group",
		Name:      "system:nodes",
		Namespace: api.NamespaceSystem,
	}

	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "system:node-proxier",
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "system:node-proxier",
		},
		Subjects: []rbac.Subject{systemKubeProxySubject, systemNodesSubject},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Update(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created kube-proxy RBAC rules")

	return nil
}
<commit_msg>kubeadm: use built-in system:node-bootstrapper role<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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 apiconfig

import (
	"fmt"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/cmd/kubeadm/app/master"
	"k8s.io/kubernetes/pkg/api"
	rbac "k8s.io/kubernetes/pkg/apis/rbac/v1beta1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

// CreateBootstrapRBACClusterRole grants the system:node-bootstrapper role to the group we created the bootstrap credential with
func CreateBootstrapRBACClusterRole(clientset *clientset.Clientset) error {
	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "kubeadm:kubelet-bootstrap",
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "system:node-bootstrapper",
		},
		Subjects: []rbac.Subject{
			rbac.Subject{Kind: "Group", Name: "kubeadm:kubelet-bootstrap"},
		},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created node bootstrapper RBAC rules")

	return nil
}

// CreateKubeDNSRBACClusterRole creates the necessary ClusterRole for kube-dns
func CreateKubeDNSRBACClusterRole(clientset *clientset.Clientset) error {
	clusterRole := rbac.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{Name: "kubeadm:" + master.KubeDNS},
		Rules: []rbac.PolicyRule{
			rbac.NewRule("list", "watch").Groups("").Resources("endpoints", "services").RuleOrDie(),
			// TODO: remove watch rule when https://github.com/kubernetes/kubernetes/pull/38816 gets merged
			rbac.NewRule("get", "list", "watch").Groups("").Resources("configmaps").RuleOrDie(),
		},
	}
	if _, err := clientset.Rbac().ClusterRoles().Create(&clusterRole); err != nil {
		return err
	}

	subject := rbac.Subject{
		Kind:      "ServiceAccount",
		Name:      master.KubeDNS,
		Namespace: api.NamespaceSystem,
	}

	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "kubeadm:" + master.KubeDNS,
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "kubeadm:" + master.KubeDNS,
		},
		Subjects: []rbac.Subject{subject},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created kube-dns RBAC rules")

	return nil
}

// CreateKubeProxyClusterRoleBinding creates the necessary ClusterRole for kube-dns
func CreateKubeProxyClusterRoleBinding(clientset *clientset.Clientset) error {
	systemKubeProxySubject := rbac.Subject{
		Kind:      "User",
		Name:      "system:kube-proxy",
		Namespace: api.NamespaceSystem,
	}

	systemNodesSubject := rbac.Subject{
		Kind:      "Group",
		Name:      "system:nodes",
		Namespace: api.NamespaceSystem,
	}

	clusterRoleBinding := rbac.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: "system:node-proxier",
		},
		RoleRef: rbac.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     "system:node-proxier",
		},
		Subjects: []rbac.Subject{systemKubeProxySubject, systemNodesSubject},
	}
	if _, err := clientset.Rbac().ClusterRoleBindings().Update(&clusterRoleBinding); err != nil {
		return err
	}
	fmt.Println("[apiconfig] Created kube-proxy RBAC rules")

	return nil
}
<|endoftext|>


<commit_before>package goltime

import (
	"net/http"
	"strconv"
	"strings"
	"time"
)

// the currency for goltime
type Timestamp struct {
	Year, Month, Day, Hour, Min, Sec, MilliSec, MicroSec, NanoSec, PicoSec int
}

// getting value for second fragments from second value
func secondFragments(second string) (sec, milliSec, microSec, nanoSec, picoSec int) {
	fragments := strings.Split(abc, ".")

	if len(fragments) > 0 {
		sec, _ = strconv.Atoi(fragments[0])
	}
	if len(fragments) > 1 {
		milliSec, _ = strconv.Atoi(fragments[1])
	}
	if len(fragments) > 2 {
		microSec, _ = strconv.Atoi(fragments[2])
	}
	if len(fragments) > 3 {
		nanoSec, _ = strconv.Atoi(fragments[3])
	}
	if len(fragments) > 4 {
		picoSec, _ = strconv.Atoi(fragments[4])
	}
	return
}

// creating Timestamp struct from string array of counts [Y M D h m s]
func CreateTimestamp(time_point []string) Timestamp {
	year, _ := strconv.Atoi(time_point[0])
	month, _ := strconv.Atoi(time_point[1])
	day, _ := strconv.Atoi(time_point[2])
	hour, _ := strconv.Atoi(time_point[3])
	min, _ := strconv.Atoi(time_point[4])
	sec, milliSec, mircoSec, nanoSec, picoSec := secondFragments(time_point[5])

	return Timestamp{
		Year:     year,
		Month:    month,
		Day:      day,
		Hour:     hour,
		Min:      min,
		Sec:      sec,
		MilliSec: milliSec,
		MicroSec: microSec,
		NanoSec:  nanoSec,
		PicoSec:  picoSec,
	}
}

/*
creating Timestamp from Request handler of HTTP having formvalues for it
under "year", "month", "day", "hour", "min", "sec"
*/
func TimestampFromHTTPRequest(req *http.Request) Timestamp {
	return CreateTimestamp([]string{
		req.FormValue("year"), req.FormValue("month"), req.FormValue("day"),
		req.FormValue("hour"), req.FormValue("min"), req.FormValue("sec"),
	})
}

// create time.Time from a Timestamp struct
func (timestamp *Timestamp) Time() time.Time {
	return time.Date(timestamp.Year, time.Month(timestamp.Month), timestamp.Day,
		timestamp.Hour, timestamp.Min, timestamp.Sec, timestamp.MilliSec, time.UTC)
}

// create Timestamp struct from time.Now
func TimestampNow() Timestamp {
	var year, day, hour, min, sec int
	var month time.Month
	year, month, day = time.Now().Date()
	hour, min, sec = time.Now().Clock()
	return Timestamp{
		Year:     year,
		Month:    int(month),
		Day:      day,
		Hour:     hour,
		Min:      min,
		Sec:      sec,
		MilliSec: 0,
		MicroSec: 0,
		NanoSec:  0,
		PicoSec:  0,
	}
}
<commit_msg>[goltime] fixing typos for micro and fragment<commit_after>package goltime

import (
	"net/http"
	"strconv"
	"strings"
	"time"
)

// the currency for goltime
type Timestamp struct {
	Year, Month, Day, Hour, Min, Sec, MilliSec, MicroSec, NanoSec, PicoSec int
}

// getting value for second fragments from second value
func secondFragments(second string) (sec, milliSec, microSec, nanoSec, picoSec int) {
	fragments := strings.Split(second, ".")

	if len(fragments) > 0 {
		sec, _ = strconv.Atoi(fragments[0])
	}
	if len(fragments) > 1 {
		milliSec, _ = strconv.Atoi(fragments[1])
	}
	if len(fragments) > 2 {
		microSec, _ = strconv.Atoi(fragments[2])
	}
	if len(fragments) > 3 {
		nanoSec, _ = strconv.Atoi(fragments[3])
	}
	if len(fragments) > 4 {
		picoSec, _ = strconv.Atoi(fragments[4])
	}
	return
}

// creating Timestamp struct from string array of counts [Y M D h m s]
func CreateTimestamp(time_point []string) Timestamp {
	year, _ := strconv.Atoi(time_point[0])
	month, _ := strconv.Atoi(time_point[1])
	day, _ := strconv.Atoi(time_point[2])
	hour, _ := strconv.Atoi(time_point[3])
	min, _ := strconv.Atoi(time_point[4])
	sec, milliSec, microSec, nanoSec, picoSec := secondFragments(time_point[5])

	return Timestamp{
		Year:     year,
		Month:    month,
		Day:      day,
		Hour:     hour,
		Min:      min,
		Sec:      sec,
		MilliSec: milliSec,
		MicroSec: microSec,
		NanoSec:  nanoSec,
		PicoSec:  picoSec,
	}
}

/*
creating Timestamp from Request handler of HTTP having formvalues for it
under "year", "month", "day", "hour", "min", "sec"
*/
func TimestampFromHTTPRequest(req *http.Request) Timestamp {
	return CreateTimestamp([]string{
		req.FormValue("year"), req.FormValue("month"), req.FormValue("day"),
		req.FormValue("hour"), req.FormValue("min"), req.FormValue("sec"),
	})
}

// create time.Time from a Timestamp struct
func (timestamp *Timestamp) Time() time.Time {
	return time.Date(timestamp.Year, time.Month(timestamp.Month), timestamp.Day,
		timestamp.Hour, timestamp.Min, timestamp.Sec, timestamp.MilliSec, time.UTC)
}

// create Timestamp struct from time.Now
func TimestampNow() Timestamp {
	var year, day, hour, min, sec int
	var month time.Month
	year, month, day = time.Now().Date()
	hour, min, sec = time.Now().Clock()
	return Timestamp{
		Year:     year,
		Month:    int(month),
		Day:      day,
		Hour:     hour,
		Min:      min,
		Sec:      sec,
		MilliSec: 0,
		MicroSec: 0,
		NanoSec:  0,
		PicoSec:  0,
	}
}
<|endoftext|>