<commit_before>/*
Copyright 2014 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 cmd

import (
	"errors"
	"fmt"
	"io"
	"net/url"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/cobra"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
	restclient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/remotecommand"
	"k8s.io/kubernetes/pkg/api/legacyscheme"
	api "k8s.io/kubernetes/pkg/apis/core"
	coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)

var (
	attachExample = templates.Examples(i18n.T(`
		# Get output from running pod 123456-7890, using the first container by default
		kubectl attach 123456-7890

		# Get output from ruby-container from pod 123456-7890
		kubectl attach 123456-7890 -c ruby-container

		# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890
		# and sends stdout/stderr from 'bash' back to the client
		kubectl attach 123456-7890 -c ruby-container -i -t

		# Get output from the first pod of a ReplicaSet named nginx
		kubectl attach rs/nginx
		`))
)

const (
	defaultPodAttachTimeout = 60 * time.Second
	defaultPodLogsTimeout   = 20 * time.Second
)

func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
	options := &AttachOptions{
		StreamOptions: StreamOptions{
			In:  cmdIn,
			Out: cmdOut,
			Err: cmdErr,
		},

		Attach: &DefaultRemoteAttach{},
	}
	cmd := &cobra.Command{
		Use:     "attach (POD | TYPE/NAME) -c CONTAINER",
		Short:   i18n.T("Attach to a running container"),
		Long:    "Attach to a process that is already running inside an existing container.",
		Example: attachExample,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(options.Complete(f, cmd, args))
			cmdutil.CheckErr(options.Validate())
			cmdutil.CheckErr(options.Run())
		},
	}
	cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodAttachTimeout)
	cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen")
	cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container")
	cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY")
	return cmd
}

// RemoteAttach defines the interface accepted by the Attach command - provided for test stubbing
type RemoteAttach interface {
	Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error
}

// DefaultRemoteAttach is the standard implementation of attaching
type DefaultRemoteAttach struct{}

func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
	exec, err := remotecommand.NewSPDYExecutor(config, method, url)
	if err != nil {
		return err
	}
	return exec.Stream(remotecommand.StreamOptions{
		Stdin:             stdin,
		Stdout:            stdout,
		Stderr:            stderr,
		Tty:               tty,
		TerminalSizeQueue: terminalSizeQueue,
	})
}

// AttachOptions declare the arguments accepted by the Exec command
type AttachOptions struct {
	StreamOptions

	CommandName string

	Pod *api.Pod

	Attach        RemoteAttach
	PodClient     coreclient.PodsGetter
	GetPodTimeout time.Duration
	Config        *restclient.Config
}

// Complete verifies command line arguments and loads data from the command environment
func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string) error {
	if len(argsIn) == 0 {
		return cmdutil.UsageErrorf(cmd, "at least 1 argument is required for attach")
	}
	if len(argsIn) > 2 {
		return cmdutil.UsageErrorf(cmd, "expected POD, TYPE/NAME, or TYPE NAME, (at most 2 arguments) saw %d: %v", len(argsIn), argsIn)
	}

	namespace, _, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	p.GetPodTimeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd)
	if err != nil {
		return cmdutil.UsageErrorf(cmd, err.Error())
	}

	builder := f.NewBuilder().
		Internal().
		NamespaceParam(namespace).DefaultNamespace()

	switch len(argsIn) {
	case 1:
		builder.ResourceNames("pods", argsIn[0])
	case 2:
		builder.ResourceNames(argsIn[0], argsIn[1])
	}

	obj, err := builder.Do().Object()
	if err != nil {
		return err
	}

	attachablePod, err := f.AttachablePodForObject(obj, p.GetPodTimeout)
	if err != nil {
		return err
	}

	p.PodName = attachablePod.Name
	p.Namespace = namespace

	config, err := f.ClientConfig()
	if err != nil {
		return err
	}
	p.Config = config

	clientset, err := f.ClientSet()
	if err != nil {
		return err
	}
	p.PodClient = clientset.Core()

	if p.CommandName == "" {
		p.CommandName = cmd.CommandPath()
	}

	return nil
}

// Validate checks that the provided attach options are specified.
func (p *AttachOptions) Validate() error {
	allErrs := []error{}
	if len(p.PodName) == 0 {
		allErrs = append(allErrs, errors.New("pod name must be specified"))
	}
	if p.Out == nil || p.Err == nil {
		allErrs = append(allErrs, errors.New("both output and error output must be provided"))
	}
	if p.Attach == nil || p.PodClient == nil || p.Config == nil {
		allErrs = append(allErrs, errors.New("client, client config, and attach must be provided"))
	}
	return utilerrors.NewAggregate(allErrs)
}

// Run executes a validated remote execution against a pod.
func (p *AttachOptions) Run() error {
	if p.Pod == nil {
		pod, err := p.PodClient.Pods(p.Namespace).Get(p.PodName, metav1.GetOptions{})
		if err != nil {
			return err
		}

		if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed {
			return fmt.Errorf("cannot attach a container in a completed pod; current phase is %s", pod.Status.Phase)
		}

		p.Pod = pod
		// TODO: convert this to a clean "wait" behavior
	}
	pod := p.Pod

	// check for TTY
	containerToAttach, err := p.containerToAttachTo(pod)
	if err != nil {
		return fmt.Errorf("cannot attach to the container: %v", err)
	}
	if p.TTY && !containerToAttach.TTY {
		p.TTY = false
		if p.Err != nil {
			fmt.Fprintf(p.Err, "Unable to use a TTY - container %s did not allocate one\n", containerToAttach.Name)
		}
	} else if !p.TTY && containerToAttach.TTY {
		// the container was launched with a TTY, so we have to force a TTY here, otherwise you'll get
		// an error "Unrecognized input header"
		p.TTY = true
	}

	// ensure we can recover the terminal while attached
	t := p.setupTTY()

	// save p.Err so we can print the command prompt message below
	stderr := p.Err

	var sizeQueue remotecommand.TerminalSizeQueue
	if t.Raw {
		if size := t.GetSize(); size != nil {
			// fake resizing +1 and then back to normal so that attach-detach-reattach will result in the
			// screen being redrawn
			sizePlusOne := *size
			sizePlusOne.Width++
			sizePlusOne.Height++

			// this call spawns a goroutine to monitor/update the terminal size
			sizeQueue = t.MonitorSize(&sizePlusOne, size)
		}

		// unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is
		// true
		p.Err = nil
	}

	fn := func() error {

		if !p.Quiet && stderr != nil {
			fmt.Fprintln(stderr, "If you don't see a command prompt, try pressing enter.")
		}

		restClient, err := restclient.RESTClientFor(p.Config)
		if err != nil {
			return err
		}
		// TODO: consider abstracting into a client invocation or client helper
		req := restClient.Post().
			Resource("pods").
			Name(pod.Name).
			Namespace(pod.Namespace).
			SubResource("attach")
		req.VersionedParams(&api.PodAttachOptions{
			Container: containerToAttach.Name,
			Stdin:     p.Stdin,
			Stdout:    p.Out != nil,
			Stderr:    p.Err != nil,
			TTY:       t.Raw,
		}, legacyscheme.ParameterCodec)

		return p.Attach.Attach("POST", req.URL(), p.Config, p.In, p.Out, p.Err, t.Raw, sizeQueue)
	}

	if err := t.Safe(fn); err != nil {
		return err
	}

	if p.Stdin && t.Raw && pod.Spec.RestartPolicy == api.RestartPolicyAlways {
		fmt.Fprintf(p.Out, "Session ended, resume using '%s %s -c %s -i -t' command when the pod is running\n", p.CommandName, pod.Name, containerToAttach.Name)
	}
	return nil
}

// containerToAttach returns a reference to the container to attach to, given
// by name or the first container if name is empty.
func (p *AttachOptions) containerToAttachTo(pod *api.Pod) (*api.Container, error) {
	if len(p.ContainerName) > 0 {
		for i := range pod.Spec.Containers {
			if pod.Spec.Containers[i].Name == p.ContainerName {
				return &pod.Spec.Containers[i], nil
			}
		}
		for i := range pod.Spec.InitContainers {
			if pod.Spec.InitContainers[i].Name == p.ContainerName {
				return &pod.Spec.InitContainers[i], nil
			}
		}
		return nil, fmt.Errorf("container not found (%s)", p.ContainerName)
	}

	glog.V(4).Infof("defaulting container name to %s", pod.Spec.Containers[0].Name)
	return &pod.Spec.Containers[0], nil
}

// GetContainerName returns the name of the container to attach to, with a fallback.
func (p *AttachOptions) GetContainerName(pod *api.Pod) (string, error) {
	c, err := p.containerToAttachTo(pod)
	if err != nil {
		return "", err
	}
	return c.Name, nil
}
<commit_msg>UPSTREAM: 58533: add suggestion to describe pod for container names<commit_after>/*
Copyright 2014 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 cmd

import (
	"errors"
	"fmt"
	"io"
	"net/url"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/cobra"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
	restclient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/remotecommand"
	"k8s.io/kubernetes/pkg/api/legacyscheme"
	api "k8s.io/kubernetes/pkg/apis/core"
	coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)

var (
	attachExample = templates.Examples(i18n.T(`
		# Get output from running pod 123456-7890, using the first container by default
		kubectl attach 123456-7890

		# Get output from ruby-container from pod 123456-7890
		kubectl attach 123456-7890 -c ruby-container

		# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890
		# and sends stdout/stderr from 'bash' back to the client
		kubectl attach 123456-7890 -c ruby-container -i -t

		# Get output from the first pod of a ReplicaSet named nginx
		kubectl attach rs/nginx
		`))
)

const (
	defaultPodAttachTimeout = 60 * time.Second
	defaultPodLogsTimeout   = 20 * time.Second
)

func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
	options := &AttachOptions{
		StreamOptions: StreamOptions{
			In:  cmdIn,
			Out: cmdOut,
			Err: cmdErr,
		},

		Attach: &DefaultRemoteAttach{},
	}
	cmd := &cobra.Command{
		Use:     "attach (POD | TYPE/NAME) -c CONTAINER",
		Short:   i18n.T("Attach to a running container"),
		Long:    "Attach to a process that is already running inside an existing container.",
		Example: attachExample,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(options.Complete(f, cmd, args))
			cmdutil.CheckErr(options.Validate())
			cmdutil.CheckErr(options.Run())
		},
	}
	cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodAttachTimeout)
	cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen")
	cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container")
	cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY")
	return cmd
}

// RemoteAttach defines the interface accepted by the Attach command - provided for test stubbing
type RemoteAttach interface {
	Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error
}

// DefaultRemoteAttach is the standard implementation of attaching
type DefaultRemoteAttach struct{}

func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error {
	exec, err := remotecommand.NewSPDYExecutor(config, method, url)
	if err != nil {
		return err
	}
	return exec.Stream(remotecommand.StreamOptions{
		Stdin:             stdin,
		Stdout:            stdout,
		Stderr:            stderr,
		Tty:               tty,
		TerminalSizeQueue: terminalSizeQueue,
	})
}

// AttachOptions declare the arguments accepted by the Exec command
type AttachOptions struct {
	StreamOptions

	CommandName       string
	SuggestedCmdUsage string

	Pod *api.Pod

	Attach        RemoteAttach
	PodClient     coreclient.PodsGetter
	GetPodTimeout time.Duration
	Config        *restclient.Config
}

// Complete verifies command line arguments and loads data from the command environment
func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string) error {
	if len(argsIn) == 0 {
		return cmdutil.UsageErrorf(cmd, "at least 1 argument is required for attach")
	}
	if len(argsIn) > 2 {
		return cmdutil.UsageErrorf(cmd, "expected POD, TYPE/NAME, or TYPE NAME, (at most 2 arguments) saw %d: %v", len(argsIn), argsIn)
	}

	namespace, _, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	p.GetPodTimeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd)
	if err != nil {
		return cmdutil.UsageErrorf(cmd, err.Error())
	}

	builder := f.NewBuilder().
		Internal().
		NamespaceParam(namespace).DefaultNamespace()

	switch len(argsIn) {
	case 1:
		builder.ResourceNames("pods", argsIn[0])
	case 2:
		builder.ResourceNames(argsIn[0], argsIn[1])
	}

	obj, err := builder.Do().Object()
	if err != nil {
		return err
	}

	attachablePod, err := f.AttachablePodForObject(obj, p.GetPodTimeout)
	if err != nil {
		return err
	}

	p.PodName = attachablePod.Name
	p.Namespace = namespace

	fullCmdName := ""
	cmdParent := cmd.Parent()
	if cmdParent != nil {
		fullCmdName = cmdParent.CommandPath()
	}
	if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "describe") {
		p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", fullCmdName, p.PodName, p.Namespace)
	}

	config, err := f.ClientConfig()
	if err != nil {
		return err
	}
	p.Config = config

	clientset, err := f.ClientSet()
	if err != nil {
		return err
	}
	p.PodClient = clientset.Core()

	if p.CommandName == "" {
		p.CommandName = cmd.CommandPath()
	}

	return nil
}

// Validate checks that the provided attach options are specified.
func (p *AttachOptions) Validate() error {
	allErrs := []error{}
	if len(p.PodName) == 0 {
		allErrs = append(allErrs, errors.New("pod name must be specified"))
	}
	if p.Out == nil || p.Err == nil {
		allErrs = append(allErrs, errors.New("both output and error output must be provided"))
	}
	if p.Attach == nil || p.PodClient == nil || p.Config == nil {
		allErrs = append(allErrs, errors.New("client, client config, and attach must be provided"))
	}
	return utilerrors.NewAggregate(allErrs)
}

// Run executes a validated remote execution against a pod.
func (p *AttachOptions) Run() error {
	if p.Pod == nil {
		pod, err := p.PodClient.Pods(p.Namespace).Get(p.PodName, metav1.GetOptions{})
		if err != nil {
			return err
		}

		if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed {
			return fmt.Errorf("cannot attach a container in a completed pod; current phase is %s", pod.Status.Phase)
		}

		p.Pod = pod
		// TODO: convert this to a clean "wait" behavior
	}
	pod := p.Pod

	// check for TTY
	containerToAttach, err := p.containerToAttachTo(pod)
	if err != nil {
		return fmt.Errorf("cannot attach to the container: %v", err)
	}
	if p.TTY && !containerToAttach.TTY {
		p.TTY = false
		if p.Err != nil {
			fmt.Fprintf(p.Err, "Unable to use a TTY - container %s did not allocate one\n", containerToAttach.Name)
		}
	} else if !p.TTY && containerToAttach.TTY {
		// the container was launched with a TTY, so we have to force a TTY here, otherwise you'll get
		// an error "Unrecognized input header"
		p.TTY = true
	}

	// ensure we can recover the terminal while attached
	t := p.setupTTY()

	// save p.Err so we can print the command prompt message below
	stderr := p.Err

	var sizeQueue remotecommand.TerminalSizeQueue
	if t.Raw {
		if size := t.GetSize(); size != nil {
			// fake resizing +1 and then back to normal so that attach-detach-reattach will result in the
			// screen being redrawn
			sizePlusOne := *size
			sizePlusOne.Width++
			sizePlusOne.Height++

			// this call spawns a goroutine to monitor/update the terminal size
			sizeQueue = t.MonitorSize(&sizePlusOne, size)
		}

		// unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is
		// true
		p.Err = nil
	}

	fn := func() error {

		if !p.Quiet && stderr != nil {
			fmt.Fprintln(stderr, "If you don't see a command prompt, try pressing enter.")
		}

		restClient, err := restclient.RESTClientFor(p.Config)
		if err != nil {
			return err
		}
		// TODO: consider abstracting into a client invocation or client helper
		req := restClient.Post().
			Resource("pods").
			Name(pod.Name).
			Namespace(pod.Namespace).
			SubResource("attach")
		req.VersionedParams(&api.PodAttachOptions{
			Container: containerToAttach.Name,
			Stdin:     p.Stdin,
			Stdout:    p.Out != nil,
			Stderr:    p.Err != nil,
			TTY:       t.Raw,
		}, legacyscheme.ParameterCodec)

		return p.Attach.Attach("POST", req.URL(), p.Config, p.In, p.Out, p.Err, t.Raw, sizeQueue)
	}

	if err := t.Safe(fn); err != nil {
		return err
	}

	if p.Stdin && t.Raw && pod.Spec.RestartPolicy == api.RestartPolicyAlways {
		fmt.Fprintf(p.Out, "Session ended, resume using '%s %s -c %s -i -t' command when the pod is running\n", p.CommandName, pod.Name, containerToAttach.Name)
	}
	return nil
}

// containerToAttach returns a reference to the container to attach to, given
// by name or the first container if name is empty.
func (p *AttachOptions) containerToAttachTo(pod *api.Pod) (*api.Container, error) {
	if len(p.ContainerName) > 0 {
		for i := range pod.Spec.Containers {
			if pod.Spec.Containers[i].Name == p.ContainerName {
				return &pod.Spec.Containers[i], nil
			}
		}
		for i := range pod.Spec.InitContainers {
			if pod.Spec.InitContainers[i].Name == p.ContainerName {
				return &pod.Spec.InitContainers[i], nil
			}
		}
		return nil, fmt.Errorf("container not found (%s)", p.ContainerName)
	}

	if len(p.SuggestedCmdUsage) > 0 {
		fmt.Fprintf(p.Err, "Defaulting container name to %s.\n", pod.Spec.Containers[0].Name)
		fmt.Fprintf(p.Err, "%s\n", p.SuggestedCmdUsage)
	}

	glog.V(4).Infof("defaulting container name to %s", pod.Spec.Containers[0].Name)
	return &pod.Spec.Containers[0], nil
}

// GetContainerName returns the name of the container to attach to, with a fallback.
func (p *AttachOptions) GetContainerName(pod *api.Pod) (string, error) {
	c, err := p.containerToAttachTo(pod)
	if err != nil {
		return "", err
	}
	return c.Name, nil
}
<|endoftext|>


<commit_before>package keeper

import (
	"context"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/validator/types"
)

func (k msgServer) DisableValidator(goCtx context.Context, msg *types.MsgDisableValidator) (*types.MsgDisableValidatorResponse, error) {
	ctx := sdk.UnwrapSDKContext(goCtx)

	creatorAddr, err := sdk.ValAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err)
	}

	// check if message creator has enough rights to propose disable validator
	if !k.dclauthKeeper.HasRole(ctx, sdk.AccAddress(creatorAddr), types.EnableDisableValidatorRole) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"Disable validator transaction should be signed by an account with the %s role",
			types.EnableDisableValidatorRole,
		)
	}

	// check if validator exists
	isFound := k.Keeper.IsValidatorPresent(ctx, creatorAddr)
	if !isFound {
		return nil, sdkstakingtypes.ErrNoValidatorFound
	}

	// check if disabled validator exists
	_, isFound = k.GetDisabledValidator(ctx, msg.Creator)
	if isFound {
		return nil, types.NewErrDisabledValidatorAlreadyExists(msg.Creator)
	}

	creator, err := sdk.ValAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress,
			"Don't convert validator address to ValAddress")
	}

	disabledValidator := types.DisabledValidator{
		Address:             msg.Creator,
		Creator:             string(creator),
		DisabledByNodeAdmin: true,
	}

	// Disable validator
	validator, _ := k.GetValidator(ctx, sdk.ValAddress(msg.Creator))
	k.Jail(ctx, validator, "disabled by a node admin")

	// store disabled validator
	k.SetDisabledValidator(ctx, disabledValidator)

	return &types.MsgDisableValidatorResponse{}, nil
}
<commit_msg>Add implementation when we disable validator, that validator should be in the entity 'Revoked Account' and remove in the entity 'Account'<commit_after>package keeper

import (
	"context"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

	dclauthTypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/validator/types"
)

func (k msgServer) DisableValidator(goCtx context.Context, msg *types.MsgDisableValidator) (*types.MsgDisableValidatorResponse, error) {
	ctx := sdk.UnwrapSDKContext(goCtx)

	creatorAddr, err := sdk.ValAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err)
	}

	// check if message creator has enough rights to propose disable validator
	if !k.dclauthKeeper.HasRole(ctx, sdk.AccAddress(creatorAddr), types.EnableDisableValidatorRole) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"Disable validator transaction should be signed by an account with the %s role",
			types.EnableDisableValidatorRole,
		)
	}

	// check if validator exists
	isFound := k.Keeper.IsValidatorPresent(ctx, creatorAddr)
	if !isFound {
		return nil, sdkstakingtypes.ErrNoValidatorFound
	}

	// check if disabled validator exists
	_, isFound = k.GetDisabledValidator(ctx, msg.Creator)
	if isFound {
		return nil, types.NewErrDisabledValidatorAlreadyExists(msg.Creator)
	}

	creator, err := sdk.ValAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress,
			"Don't convert validator address to ValAddress")
	}

	disabledValidator := types.DisabledValidator{
		Address:             msg.Creator,
		Creator:             string(creator),
		DisabledByNodeAdmin: true,
	}

	// Disable validator
	validator, _ := k.GetValidator(ctx, sdk.ValAddress(msg.Creator))
	k.Jail(ctx, validator, "disabled by a node admin")

	// store disabled validator
	k.SetDisabledValidator(ctx, disabledValidator)

	accAddr, err := sdk.AccAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err)
	}

	// get account
	account, ok := k.dclauthKeeper.GetAccountO(ctx, accAddr)

	// check we can get that account or can not
	if !ok {
		return nil, dclauthTypes.ErrAccountDoesNotExist(accAddr)
	}

	// create revoked account record
	revokedAccount := dclauthTypes.NewRevokedAccount(&account, account.Approvals)
	k.dclauthKeeper.SetRevokedAccount(ctx, *revokedAccount)

	// delete account record
	k.dclauthKeeper.RemoveAccount(ctx, accAddr)

	return &types.MsgDisableValidatorResponse{}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"

	. "github.com/russross/codegrinder/types"
)

func init() {
	problemTypes["standardmlunittest"] = &ProblemType{
		Name:        "standardmlunittest",
		Image:       "codegrinder/standardml",
		MaxCPU:      10,
		MaxSession:  30 * 60,
		MaxTimeout:  5 * 60,
		MaxFD:       100,
		MaxFileSize: 10,
		MaxMemory:   128,
		MaxThreads:  20,
		Actions: map[string]*ProblemTypeAction{
			"grade": &ProblemTypeAction{
				Action:      "grade",
				Button:      "Grade",
				Message:     "Grading‥",
				Interactive: false,
				Handler:     nannyHandler(standardMLUnittestGrade),
			},
		},
	}
}

var standardMLaout = `#!/bin/bash
set -e
ln -s tests/*.sml ./
rm -f test_detail.xml
poly < tests.sml
`

func standardMLUnittestGrade(n *Nanny, args, options []string, files map[string]string, stdin io.Reader) {
	log.Printf("standard ML unit test grade")

	// create an a.out file
	if err := n.PutFiles(map[string]string{"a.out": standardMLaout}); err != nil {
		n.ReportCard.LogAndFailf("error creating a.out: %v", err)
		return
	}

	// make it executable
	if err := n.ExecSimple([]string{"chmod", "755", "a.out"}, nil, false); err != nil {
		return
	}

	// run a.out and parse the output (in common with c++)
	gTestAOutCommon(n, files, nil)
}
<commit_msg>sml actions<commit_after>package main

import (
	"io"
	"log"

	. "github.com/russross/codegrinder/types"
)

func init() {
	problemTypes["standardmlunittest"] = &ProblemType{
		Name:        "standardmlunittest",
		Image:       "codegrinder/standardml",
		MaxCPU:      10,
		MaxSession:  30 * 60,
		MaxTimeout:  5 * 60,
		MaxFD:       100,
		MaxFileSize: 10,
		MaxMemory:   128,
		MaxThreads:  20,
		Actions: map[string]*ProblemTypeAction{
			"grade": &ProblemTypeAction{
				Action:      "grade",
				Button:      "Grade",
				Message:     "Grading‥",
				Interactive: false,
				Handler:     nannyHandler(standardMLUnittestGrade),
			},
			"run": &ProblemTypeAction{
				Action:      "run",
				Button:      "Run",
				Message:     "Running %s‥",
				Interactive: true,
				Handler:     nannyHandler(standardMLRun),
			},
			"shell": &ProblemTypeAction{
				Action:      "shell",
				Button:      "Shell",
				Message:     "Running PolyML shell‥",
				Interactive: true,
				Handler:     nannyHandler(standardMLShell),
			},
		},
	}
}

var standardMLaout = `#!/bin/bash
set -e
ln -s tests/*.sml ./
rm -f test_detail.xml
poly < tests.sml
`

func standardMLUnittestGrade(n *Nanny, args, options []string, files map[string]string, stdin io.Reader) {
	log.Printf("standard ML unit test grade")

	// create an a.out file
	if err := n.PutFiles(map[string]string{"a.out": standardMLaout}); err != nil {
		n.ReportCard.LogAndFailf("error creating a.out: %v", err)
		return
	}

	// make it executable
	if err := n.ExecSimple([]string{"chmod", "755", "a.out"}, nil, false); err != nil {
		return
	}

	// run a.out and parse the output (in common with c++)
	gTestAOutCommon(n, files, nil)
}

var standardMLRunaout = `#!/bin/bash
set -e
echo ';' > /tmp/semi
cat *.sml /tmp/semi | rlwrap poly
`

func standardMLRun(n *Nanny, args, options []string, files map[string]string, stdin io.Reader) {
	log.Printf("standard ML run")

	// create an a.out file
	if err := n.PutFiles(map[string]string{"a.out": standardMLaout}); err != nil {
		n.ReportCard.LogAndFailf("error creating a.out: %v", err)
		return
	}

	// make it executable
	if err := n.ExecSimple([]string{"chmod", "755", "a.out"}, nil, false); err != nil {
		return
	}

	// run a.out
	n.ExecSimple([]string{"a.out"}, stdin, true)
}

func standardMLShell(n *Nanny, args, options []string, files map[string]string, stdin io.Reader) {
	log.Printf("standard ML shell")

	n.ExecSimple([]string{"rlwrap", "poly"}, stdin, true)
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2014 John Gettings

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package sws

import(
	"fmt"
	"net/http"
	"os"
	"path"
	"regexp"
)

// the default server object to use
var DefaultServer = NewServer()

/*
	Adds a route to handle the given pattern using the given handler, to the DefaultServer.
*/
func Handle(pattern string, handler http.Handler) {
	DefaultServer.Handle(pattern, handler)
}

/*
	Adds a route to handle the given pattern using the gieven handler function, to the Default Server.
*/
func HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ) {
	DefaultServer.HandleFunc(pattern, handler)
}

/*
	Runs the Default Server on the given address addr.
*/
func Run(addr string) error {
	return DefaultServer.Run(addr)
}

/*
	Sets the DefaultServer's NotFoundHandler to the given function.
*/
func SetNotFoundHandler( handler func(http.ResponseWriter, *http.Request) ) {
	DefaultServer.NotFoundHandler = handler
}

/*
	Sets the DefaultServer's InternalErrorHandler to the given function
*/
func SetInternalErrorHandler( handler func(http.ResponseWriter, *http.Request, error) ) {
	DefaultServer.InternalErrorHandler = handler
}

/*
	Attempts to parse the form parameters of the given request object into an easy to use map. If a paremeter has multiple values, only the first is populated into the map.
*/
func ParseParams(r *http.Request) map[string]string {
	r.ParseForm()

	ret := make(map[string]string)

	for k, v := range r.Form {
		if v != nil && len(v) > 0 {
			ret[k] = v[0]
		} else {
			fmt.Printf("Warning: No parameter found for key '%v'\n", k)
		}
	}
	return ret
}

/*
	A simple handler function for when resources are not found. Sends a plaintext "404 Not Found" response with appropriate headers.
*/
func DefaultNotFound(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("404 Not Found"))
}

/*
	A simple handler function for when an error occurs in the server. Sends a plaintext "500 Internal Server Error" along with the result of err.Error() response, along with the appropriate headers.
*/
func DefaultInternalError(w http.ResponseWriter, r *http.Request, err error) {
	w.WriteHeader(500)
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("500 Internal Server Error\n"))
	w.Write([]byte(err.Error()))
}

type SimpleWebServer struct {
	router *regexpRouter
	NotFoundHandler func (http.ResponseWriter, *http.Request)	//A Handler function to handle when resources are not found.
	InternalErrorHandler func(http.ResponseWriter, *http.Request, error)	//A function to handle internal server errors
	StaticDir string 	//The path to the directory from which static files are to be served
	StaticFileCacheParam string 	//The value which is to be set for the header's 'Cache-Control:' parameter for static files
}

/*
	Instantiates and returns a pointer to a new SimpleWebServer object with all the default values set.
*/
func NewServer() *SimpleWebServer {
	//get the current working directory
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	//initialize a new SimpleWebServer object
	s := &SimpleWebServer{newRegexpRouter(), DefaultNotFound, DefaultInternalError, path.Join(wd, "static"), "max-age=604800"}	//default cache max age of 1 week
	//make sure the server's RegexpRouter object has a pointer to the server
	s.router.Server = s
	//return a pointer to the server
	return s
}

/*
	Adds a route to the server's Router to handle the given patern using the given handler.
*/
func (s *SimpleWebServer) Handle(pattern string, handler http.Handler) {
	s.router.Handle(pattern, handler)
}

/*
	Adds a route to the server's Router to handle the given patern using the given handler function.
*/
func (s *SimpleWebServer) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ){
	s.router.HandleFunc(pattern, handler)
}

/*
	Runs the server on the TCP network address addr
*/
func (s *SimpleWebServer) Run(addr string) error {
	http.Handle("/", s.router)
	err := http.ListenAndServe(addr, nil)
	return err
}

/*
	A convenience method to set the StaticFileCacheParam of the server to a maximum age of age, in seconds
*/
func (s *SimpleWebServer) SetStaticFileCacheMaxAge(age int) {
	s.StaticFileCacheParam = fmt.Sprintf("max-age=%v", age)
}

/*
	Attempts to serve a static file that matches the request.
*/
func (s *SimpleWebServer) attemptToServeStaticFile(w http.ResponseWriter, r *http.Request) {
	//create a path string for where the file should be
	filePath := path.Join(s.StaticDir, r.URL.Path)

	if s.fileExists(filePath){	//if the file exists:

		//fmt.Printf("Attempting to serve static file: %v\n", r.URL.Path)

		//set the cache header field
		w.Header().Set("Cache-Control", s.StaticFileCacheParam)
		//serve the file
		http.ServeFile(w, r, filePath)

	} else {	//if the file doesn't exist

		// fmt.Printf("File Not Found: %v\n", r.URL.Path)

		//call the server's not found handler
		s.NotFoundHandler(w, r)
	}
}

/*
	determines if the file at filePath exists
*/
func (s *SimpleWebServer) fileExists(filePath string) bool {
	info, err := os.Stat(filePath)
	if err != nil {
		return false;
	}
	return !info.IsDir()
}

type route struct {
	pattern *regexp.Regexp
	handler http.Handler
}

type regexpRouter struct {
	routes []*route
	Server *SimpleWebServer
}

/*
	Instantiates a new regexpRouter (with a nil Server) and returns a pointer to it.
*/
func newRegexpRouter() *regexpRouter {
	return &regexpRouter{make([]*route, 0, 4), nil}	//default static file cache life of 1 day
}

/*
	Adds a new route to the regexpRouter for the given pattern and Handler
*/
func (h *regexpRouter) Handle(pattern string, handler http.Handler){
	rpat, err := regexp.Compile(pattern)
	if err != nil {
		panic(err)
	}
	h.routes = append(h.routes, &route{rpat, handler})
}

/*
	Adds a new route to the regexpRouter for the given pattern and handler function
*/
func (h *regexpRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ){
	rpat, err := regexp.Compile(pattern)
	if err != nil {
		panic(err)
	}
	h.routes = append(h.routes, &route{rpat, http.HandlerFunc(handler)})
}

/*
	Attempts to find a matching route for the request. If no route matches, and the router's Server is non-nil, it attempts to serve a static file from the Server, otherwise it serves a basic plaintext 404.
*/
func (h *regexpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//iterate through all the routes, looking for a match
    for _, route := range h.routes {
        if route.pattern.MatchString(r.URL.Path) {
            route.handler.ServeHTTP(w, r)
            return
        }
    }
    //if the request doesn't match one of the registerd routes,
    if h.Server != nil {
    	//and if the router has a pointer to a server, attempt to serve a static file for the request
	    h.Server.attemptToServeStaticFile(w, r);
    } else {
    	//otherwise, just serve a basic plaintext 404
    	DefaultNotFound(w, r)
    }
}
<commit_msg>refactored to explicity use multiplexer for request handling<commit_after>/*
The MIT License (MIT)

Copyright (c) 2014 John Gettings

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package sws

import(
	"fmt"
	"net/http"
	"os"
	"path"
	"regexp"
)

// the default server object to use
var DefaultServer = NewServer()

/*
	Adds a route to handle the given pattern using the given handler, to the DefaultServer.
*/
func Handle(pattern string, handler http.Handler) {
	DefaultServer.Handle(pattern, handler)
}

/*
	Adds a route to handle the given pattern using the gieven handler function, to the Default Server.
*/
func HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ) {
	DefaultServer.HandleFunc(pattern, handler)
}

/*
	Runs the Default Server on the given address addr.
*/
func Run(addr string) error {
	return DefaultServer.Run(addr)
}

/*
	Sets the DefaultServer's NotFoundHandler to the given function.
*/
func SetNotFoundHandler( handler func(http.ResponseWriter, *http.Request) ) {
	DefaultServer.NotFoundHandler = handler
}

/*
	Sets the DefaultServer's InternalErrorHandler to the given function
*/
func SetInternalErrorHandler( handler func(http.ResponseWriter, *http.Request, error) ) {
	DefaultServer.InternalErrorHandler = handler
}

/*
	Attempts to parse the form parameters of the given request object into an easy to use map. If a paremeter has multiple values, only the first is populated into the map.
*/
func ParseParams(r *http.Request) map[string]string {
	r.ParseForm()

	ret := make(map[string]string)

	for k, v := range r.Form {
		if v != nil && len(v) > 0 {
			ret[k] = v[0]
		} else {
			fmt.Printf("Warning: No parameter found for key '%v'\n", k)
		}
	}
	return ret
}

/*
	A simple handler function for when resources are not found. Sends a plaintext "404 Not Found" response with appropriate headers.
*/
func DefaultNotFound(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("404 Not Found"))
}

/*
	A simple handler function for when an error occurs in the server. Sends a plaintext "500 Internal Server Error" along with the result of err.Error() response, along with the appropriate headers.
*/
func DefaultInternalError(w http.ResponseWriter, r *http.Request, err error) {
	w.WriteHeader(500)
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("500 Internal Server Error\n"))
	w.Write([]byte(err.Error()))
}

type SimpleWebServer struct {
	router *regexpRouter
	NotFoundHandler func (http.ResponseWriter, *http.Request)	//A Handler function to handle when resources are not found.
	InternalErrorHandler func(http.ResponseWriter, *http.Request, error)	//A function to handle internal server errors
	StaticDir string 	//The path to the directory from which static files are to be served
	StaticFileCacheParam string 	//The value which is to be set for the header's 'Cache-Control:' parameter for static files
}

/*
	Instantiates and returns a pointer to a new SimpleWebServer object with all the default values set.
*/
func NewServer() *SimpleWebServer {
	//get the current working directory
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	//initialize a new SimpleWebServer object
	s := &SimpleWebServer{newRegexpRouter(), DefaultNotFound, DefaultInternalError, path.Join(wd, "static"), "max-age=604800"}	//default cache max age of 1 week
	//make sure the server's RegexpRouter object has a pointer to the server
	s.router.Server = s
	//return a pointer to the server
	return s
}

/*
	Adds a route to the server's Router to handle the given patern using the given handler.
*/
func (s *SimpleWebServer) Handle(pattern string, handler http.Handler) {
	s.router.Handle(pattern, handler)
}

/*
	Adds a route to the server's Router to handle the given patern using the given handler function.
*/
func (s *SimpleWebServer) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ){
	s.router.HandleFunc(pattern, handler)
}

/*
	Runs the server on the TCP network address addr
*/
func (s *SimpleWebServer) Run(addr string) error {

	mux := http.NewServeMux()

	mux.Handle("/", s.router)

	// http.Handle("/", s.router)
	err := http.ListenAndServe(addr, mux)
	return err
}

/*
	A convenience method to set the StaticFileCacheParam of the server to a maximum age of age, in seconds
*/
func (s *SimpleWebServer) SetStaticFileCacheMaxAge(age int) {
	s.StaticFileCacheParam = fmt.Sprintf("max-age=%v", age)
}

/*
	Attempts to serve a static file that matches the request.
*/
func (s *SimpleWebServer) attemptToServeStaticFile(w http.ResponseWriter, r *http.Request) {
	//create a path string for where the file should be
	filePath := path.Join(s.StaticDir, r.URL.Path)

	// fmt.Printf("attempting to serve file from: %v\n", filePath)

	if s.fileExists(filePath){	//if the file exists:

		// fmt.Printf("Attempting to serve static file: %v\n", r.URL.Path)

		//set the cache header field
		w.Header().Set("Cache-Control", s.StaticFileCacheParam)
		//serve the file
		http.ServeFile(w, r, filePath)

	} else {	//if the file doesn't exist

		// fmt.Printf("File Not Found: %v\n", r.URL.Path)

		//call the server's not found handler
		s.NotFoundHandler(w, r)
	}
}

/*
	determines if the file at filePath exists
*/
func (s *SimpleWebServer) fileExists(filePath string) bool {
	info, err := os.Stat(filePath)
	if err != nil {
		return false;
	}
	return !info.IsDir()
}

type route struct {
	pattern *regexp.Regexp
	handler http.Handler
}

type regexpRouter struct {
	routes []*route
	Server *SimpleWebServer
}

/*
	Instantiates a new regexpRouter (with a nil Server) and returns a pointer to it.
*/
func newRegexpRouter() *regexpRouter {
	return &regexpRouter{make([]*route, 0, 4), nil}	//default static file cache life of 1 day
}

/*
	Adds a new route to the regexpRouter for the given pattern and Handler
*/
func (h *regexpRouter) Handle(pattern string, handler http.Handler){
	rpat, err := regexp.Compile(pattern)
	if err != nil {
		panic(err)
	}
	h.routes = append(h.routes, &route{rpat, handler})
}

/*
	Adds a new route to the regexpRouter for the given pattern and handler function
*/
func (h *regexpRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request) ){
	rpat, err := regexp.Compile(pattern)
	if err != nil {
		panic(err)
	}
	h.routes = append(h.routes, &route{rpat, http.HandlerFunc(handler)})
}

/*
	Attempts to find a matching route for the request. If no route matches, and the router's Server is non-nil, it attempts to serve a static file from the Server, otherwise it serves a basic plaintext 404.
*/
func (h *regexpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//iterate through all the routes, looking for a match
    for _, route := range h.routes {
        if route.pattern.MatchString(r.URL.Path) {
            route.handler.ServeHTTP(w, r)
            return
        }
    }
    //if the request doesn't match one of the registerd routes,
    if h.Server != nil {
    	//and if the router has a pointer to a server, attempt to serve a static file for the request
	    h.Server.attemptToServeStaticFile(w, r);
    } else {
    	//otherwise, just serve a basic plaintext 404
    	DefaultNotFound(w, r)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package id3v2

import (
	"bufio"
	"errors"
	"io"
	"io/ioutil"
	"os"

	"github.com/bogem/id3v2/bwpool"
	"github.com/bogem/id3v2/util"
)

// Tag stores all frames of opened file.
type Tag struct {
	frames    map[string]Framer
	sequences map[string]sequencer
	commonIDs map[string]string

	file         *os.File
	originalSize int64
	version      byte
}

// AddFrame adds f to tag with appropriate id. If id is "" or f is nil,
// AddFrame will not add f to tag.
//
// If you want to add attached picture, comment or unsynchronised lyrics/text
// transcription frames, better use AddAttachedPicture, AddCommentFrame
// or AddUnsynchronisedLyricsFrame methods respectively.
func (t *Tag) AddFrame(id string, f Framer) {
	if id == "" || f == nil {
		return
	}

	if id == t.CommonID("Attached picture") || id == t.CommonID("Comments") ||
		id == t.CommonID("Unsynchronised lyrics/text transcription") {
		t.checkSequence(id)
		t.addFrameToSequence(id, f)
	} else {
		t.frames[id] = f
	}
}

func (t *Tag) checkSequence(id string) {
	if t.sequences[id] == nil {
		switch id {
		case t.CommonID("Attached picture"):
			t.sequences[id] = newPictureSequence()
		case t.CommonID("Comments"):
			t.sequences[id] = newCommentSequence()
		case t.CommonID("Unsynchronised lyrics/text transcription"):
			t.sequences[id] = newUSLFSequence()
		}
	}
}

func (t *Tag) addFrameToSequence(id string, f Framer) {
	t.sequences[id].AddFrame(f)
}

func (t *Tag) AddAttachedPicture(pf PictureFrame) {
	id := t.CommonID("Attached picture")
	t.AddFrame(id, pf)
}

func (t *Tag) AddCommentFrame(cf CommentFrame) {
	id := t.CommonID("Comments")
	t.AddFrame(id, cf)
}

func (t *Tag) AddUnsynchronisedLyricsFrame(uslf UnsynchronisedLyricsFrame) {
	id := t.CommonID("Unsynchronised lyrics/text transcription")
	t.AddFrame(id, uslf)
}

// CommonID returns ID3v2.3 or ID3v2.4 (in appropriate to version of Tag) frame ID
// from given description.
// For example, CommonID("Language") will return "TLAN".
// All descriptions you can find in file common_ids.go or in id3 documentation (for fourth version: http://id3.org/id3v2.4.0-frames; for third version: http://id3.org/id3v2.3.0#Declared_ID3v2_frames).
func (t Tag) CommonID(description string) string {
	return t.commonIDs[description]
}

// AllFrames returns map, that contains all frames in tag, that could be parsed.
// The key of this map is an ID of frame and value is an array of frames.
func (t *Tag) AllFrames() map[string][]Framer {
	frames := make(map[string][]Framer)

	for id := range t.frames {
		frames[id] = t.GetFrames(id)
	}

	for id := range t.sequences {
		frames[id] = t.GetFrames(id)
	}

	return frames
}

// DeleteAllFrames deletes all frames in tag.
func (t *Tag) DeleteAllFrames() {
	t.frames = make(map[string]Framer)
	t.sequences = make(map[string]sequencer)
}

// DeleteFrames deletes frames in tag with given id.
func (t *Tag) DeleteFrames(id string) {
	delete(t.frames, id)
	delete(t.sequences, id)
}

// GetLastFrame returns last frame from slice, that is returned from GetFrames function.
// GetLastFrame is suitable for frames, that can be only one in whole tag.
// For example, for text frames.
//
// Example of usage:
//	bpmFramer := tag.GetLastFrame(tag.CommonID("BPM"))
//	if bpmFramer != nil {
//		bpm, ok := bpmFramer.(id3v2.TextFrame)
//		if !ok {
//			log.Fatal("Couldn't assert bpm frame")
//		}
//		fmt.Println(bpm.Text)
//	}
func (t *Tag) GetLastFrame(id string) Framer {
	fs := t.GetFrames(id)
	if len(fs) == 0 || fs == nil {
		return nil
	}
	return fs[len(fs)-1]
}

// GetFrames returns frames with corresponding id.
// It returns nil if there is no frames with given id.
//
// Example of usage:
//	pictures := tag.GetFrames(tag.CommonID("Attached picture"))
//	if pictures != nil {
//		for _, f := range pictures {
//			pic, ok := f.(id3v2.PictureFrame)
//			if !ok {
//				log.Fatal("Couldn't assert picture frame")
//			}
//
//			// Do some operations with picture frame:
//			fmt.Println(pic.Description) // For example, print description of picture frame
//		}
//	}
func (t *Tag) GetFrames(id string) []Framer {
	if f, exists := t.frames[id]; exists {
		return []Framer{f}
	} else if s, exists := t.sequences[id]; exists {
		return s.Frames()
	}
	return nil
}

// GetTextFrame returns text frame with corresponding id.
func (t Tag) GetTextFrame(id string) TextFrame {
	f := t.GetLastFrame(id)
	if f == nil {
		return TextFrame{}
	}
	tf := f.(TextFrame)
	return tf
}

// Count returns the number of frames in tag.
func (t Tag) Count() int {
	n := len(t.frames)
	for _, s := range t.sequences {
		n += s.Count()
	}
	return n
}

// HasAnyFrames checks if there is at least one frame in tag.
// It's much faster than tag.Count() > 0.
func (t Tag) HasAnyFrames() bool {
	return len(t.frames) > 0 || len(t.sequences) > 0
}

func (t Tag) Title() string {
	f := t.GetTextFrame(t.CommonID("Title/Songname/Content description"))
	return f.Text
}

func (t *Tag) SetTitle(title string) {
	t.AddFrame(t.CommonID("Title/Songname/Content description"), TextFrame{Encoding: ENUTF8, Text: title})
}

func (t Tag) Artist() string {
	f := t.GetTextFrame(t.CommonID("Lead artist/Lead performer/Soloist/Performing group"))
	return f.Text
}

func (t *Tag) SetArtist(artist string) {
	t.AddFrame(t.CommonID("Lead artist/Lead performer/Soloist/Performing group"), TextFrame{Encoding: ENUTF8, Text: artist})
}

func (t Tag) Album() string {
	f := t.GetTextFrame(t.CommonID("Album/Movie/Show title"))
	return f.Text
}

func (t *Tag) SetAlbum(album string) {
	t.AddFrame(t.CommonID("Album/Movie/Show title"), TextFrame{Encoding: ENUTF8, Text: album})
}

func (t Tag) Year() string {
	f := t.GetTextFrame(t.CommonID("Year"))
	return f.Text
}

func (t *Tag) SetYear(year string) {
	t.AddFrame(t.CommonID("Year"), TextFrame{Encoding: ENUTF8, Text: year})
}

func (t Tag) Genre() string {
	f := t.GetTextFrame(t.CommonID("Content type"))
	return f.Text
}

func (t *Tag) SetGenre(genre string) {
	t.AddFrame(t.CommonID("Content type"), TextFrame{Encoding: ENUTF8, Text: genre})
}

// Save writes tag to the file. If there are no frames in tag, Save will write
// only music part without any ID3v2 information.
func (t *Tag) Save() error {
	// Create a temp file for mp3 file, which will contain new tag
	newFile, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}

	// Make sure we clean up the temp file if it's still around
	defer os.Remove(newFile.Name())

	// If there is at least one frame, write it
	if t.HasAnyFrames() {
		// Form size of new frames
		framesSize, err := util.FormSize(t.allFramesSize())
		if err != nil {
			return err
		}

		// Write to new file new tag header
		if _, err = newFile.Write(formTagHeader(framesSize, t.version)); err != nil {
			return err
		}

		// Write to new file new frames
		if err = t.writeAllFrames(newFile); err != nil {
			return err
		}
	}

	// Seek to a music part of original file
	originalFile := t.file
	if _, err = originalFile.Seek(t.originalSize, os.SEEK_SET); err != nil {
		return err
	}

	// Write to new file the music part
	if _, err = io.Copy(newFile, originalFile); err != nil {
		return err
	}

	// Get original file mode
	originalFileStat, err := originalFile.Stat()
	if err != nil {
		return err
	}

	// Set original file mode to new file
	if err = os.Chmod(newFile.Name(), originalFileStat.Mode()); err != nil {
		return err
	}

	// Close files to allow replacing
	newFile.Close()
	originalFile.Close()

	// Replace original file with new file
	if err = os.Rename(newFile.Name(), originalFile.Name()); err != nil {
		return err
	}

	// Set t.file to new file with original name
	t.file, err = os.Open(originalFile.Name())
	if err != nil {
		return err
	}

	// Set t.originalSize to new size
	t.originalSize = int64(t.allFramesSize())

	return nil
}

// Close closes the tag's file, rendering it unusable for I/O.
// It returns an error, if any.
func (t *Tag) Close() error {
	return t.file.Close()
}

var errBlankID = errors.New("blank ID")

func (t Tag) allFramesSize() int {
	var n int

	n += t.Count() * frameHeaderSize

	for _, frames := range t.AllFrames() {
		for _, f := range frames {
			n += f.Size()
		}
	}

	return n
}

func (t Tag) writeAllFrames(w io.Writer) error {
	bw := bwpool.Get(w)
	defer bwpool.Put(bw)

	for id, frames := range t.AllFrames() {
		for _, f := range frames {
			err := writeFrame(bw, id, f)
			if err == errBlankID {
				continue
			}
			if err != nil {
				return err
			}
		}
	}

	return bw.Flush()
}

func writeFrame(bw *bufio.Writer, id string, frame Framer) error {
	if id == "" {
		return errBlankID
	}

	if err := writeFrameHeader(bw, id, frame.Size()); err != nil {
		return err
	}
	if _, err := frame.WriteTo(bw); err != nil {
		return err
	}

	return nil
}

func writeFrameHeader(bw *bufio.Writer, id string, frameSize int) error {
	size, err := util.FormSize(frameSize)
	if err != nil {
		return err
	}

	bw.WriteString(id)
	bw.Write(size)
	bw.Write([]byte{0, 0})
	return nil
}
<commit_msg>Add Version and SetVersion methods<commit_after>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package id3v2

import (
	"bufio"
	"errors"
	"io"
	"io/ioutil"
	"os"

	"github.com/bogem/id3v2/bwpool"
	"github.com/bogem/id3v2/util"
)

// Tag stores all frames of opened file.
type Tag struct {
	frames    map[string]Framer
	sequences map[string]sequencer
	commonIDs map[string]string

	file         *os.File
	originalSize int64
	version      byte
}

// AddFrame adds f to tag with appropriate id. If id is "" or f is nil,
// AddFrame will not add f to tag.
//
// If you want to add attached picture, comment or unsynchronised lyrics/text
// transcription frames, better use AddAttachedPicture, AddCommentFrame
// or AddUnsynchronisedLyricsFrame methods respectively.
func (t *Tag) AddFrame(id string, f Framer) {
	if id == "" || f == nil {
		return
	}

	if id == t.CommonID("Attached picture") || id == t.CommonID("Comments") ||
		id == t.CommonID("Unsynchronised lyrics/text transcription") {
		t.checkSequence(id)
		t.addFrameToSequence(id, f)
	} else {
		t.frames[id] = f
	}
}

func (t *Tag) checkSequence(id string) {
	if t.sequences[id] == nil {
		switch id {
		case t.CommonID("Attached picture"):
			t.sequences[id] = newPictureSequence()
		case t.CommonID("Comments"):
			t.sequences[id] = newCommentSequence()
		case t.CommonID("Unsynchronised lyrics/text transcription"):
			t.sequences[id] = newUSLFSequence()
		}
	}
}

func (t *Tag) addFrameToSequence(id string, f Framer) {
	t.sequences[id].AddFrame(f)
}

func (t *Tag) AddAttachedPicture(pf PictureFrame) {
	id := t.CommonID("Attached picture")
	t.AddFrame(id, pf)
}

func (t *Tag) AddCommentFrame(cf CommentFrame) {
	id := t.CommonID("Comments")
	t.AddFrame(id, cf)
}

func (t *Tag) AddUnsynchronisedLyricsFrame(uslf UnsynchronisedLyricsFrame) {
	id := t.CommonID("Unsynchronised lyrics/text transcription")
	t.AddFrame(id, uslf)
}

// CommonID returns ID3v2.3 or ID3v2.4 (in appropriate to version of Tag) frame ID
// from given description.
// For example, CommonID("Language") will return "TLAN".
// All descriptions you can find in file common_ids.go or in id3 documentation (for fourth version: http://id3.org/id3v2.4.0-frames; for third version: http://id3.org/id3v2.3.0#Declared_ID3v2_frames).
func (t Tag) CommonID(description string) string {
	return t.commonIDs[description]
}

// AllFrames returns map, that contains all frames in tag, that could be parsed.
// The key of this map is an ID of frame and value is an array of frames.
func (t *Tag) AllFrames() map[string][]Framer {
	frames := make(map[string][]Framer)

	for id := range t.frames {
		frames[id] = t.GetFrames(id)
	}

	for id := range t.sequences {
		frames[id] = t.GetFrames(id)
	}

	return frames
}

// DeleteAllFrames deletes all frames in tag.
func (t *Tag) DeleteAllFrames() {
	t.frames = make(map[string]Framer)
	t.sequences = make(map[string]sequencer)
}

// DeleteFrames deletes frames in tag with given id.
func (t *Tag) DeleteFrames(id string) {
	delete(t.frames, id)
	delete(t.sequences, id)
}

// GetLastFrame returns last frame from slice, that is returned from GetFrames function.
// GetLastFrame is suitable for frames, that can be only one in whole tag.
// For example, for text frames.
//
// Example of usage:
//	bpmFramer := tag.GetLastFrame(tag.CommonID("BPM"))
//	if bpmFramer != nil {
//		bpm, ok := bpmFramer.(id3v2.TextFrame)
//		if !ok {
//			log.Fatal("Couldn't assert bpm frame")
//		}
//		fmt.Println(bpm.Text)
//	}
func (t *Tag) GetLastFrame(id string) Framer {
	fs := t.GetFrames(id)
	if len(fs) == 0 || fs == nil {
		return nil
	}
	return fs[len(fs)-1]
}

// GetFrames returns frames with corresponding id.
// It returns nil if there is no frames with given id.
//
// Example of usage:
//	pictures := tag.GetFrames(tag.CommonID("Attached picture"))
//	if pictures != nil {
//		for _, f := range pictures {
//			pic, ok := f.(id3v2.PictureFrame)
//			if !ok {
//				log.Fatal("Couldn't assert picture frame")
//			}
//
//			// Do some operations with picture frame:
//			fmt.Println(pic.Description) // For example, print description of picture frame
//		}
//	}
func (t *Tag) GetFrames(id string) []Framer {
	if f, exists := t.frames[id]; exists {
		return []Framer{f}
	} else if s, exists := t.sequences[id]; exists {
		return s.Frames()
	}
	return nil
}

// GetTextFrame returns text frame with corresponding id.
func (t Tag) GetTextFrame(id string) TextFrame {
	f := t.GetLastFrame(id)
	if f == nil {
		return TextFrame{}
	}
	tf := f.(TextFrame)
	return tf
}

// Count returns the number of frames in tag.
func (t Tag) Count() int {
	n := len(t.frames)
	for _, s := range t.sequences {
		n += s.Count()
	}
	return n
}

// HasAnyFrames checks if there is at least one frame in tag.
// It's much faster than tag.Count() > 0.
func (t Tag) HasAnyFrames() bool {
	return len(t.frames) > 0 || len(t.sequences) > 0
}

func (t Tag) Title() string {
	f := t.GetTextFrame(t.CommonID("Title/Songname/Content description"))
	return f.Text
}

func (t *Tag) SetTitle(title string) {
	t.AddFrame(t.CommonID("Title/Songname/Content description"), TextFrame{Encoding: ENUTF8, Text: title})
}

func (t Tag) Artist() string {
	f := t.GetTextFrame(t.CommonID("Lead artist/Lead performer/Soloist/Performing group"))
	return f.Text
}

func (t *Tag) SetArtist(artist string) {
	t.AddFrame(t.CommonID("Lead artist/Lead performer/Soloist/Performing group"), TextFrame{Encoding: ENUTF8, Text: artist})
}

func (t Tag) Album() string {
	f := t.GetTextFrame(t.CommonID("Album/Movie/Show title"))
	return f.Text
}

func (t *Tag) SetAlbum(album string) {
	t.AddFrame(t.CommonID("Album/Movie/Show title"), TextFrame{Encoding: ENUTF8, Text: album})
}

func (t Tag) Year() string {
	f := t.GetTextFrame(t.CommonID("Year"))
	return f.Text
}

func (t *Tag) SetYear(year string) {
	t.AddFrame(t.CommonID("Year"), TextFrame{Encoding: ENUTF8, Text: year})
}

func (t Tag) Genre() string {
	f := t.GetTextFrame(t.CommonID("Content type"))
	return f.Text
}

func (t *Tag) SetGenre(genre string) {
	t.AddFrame(t.CommonID("Content type"), TextFrame{Encoding: ENUTF8, Text: genre})
}

// Version returns current ID3v2 version of tag.
func (t Tag) Version() byte {
	return t.version
}

// SetVersion sets given ID3v2 version to tag.
// If version is less than 3 or more than 4, then this method will do nothing.
// If tag has some frames, which are deprecated or changed in given version,
// then to your notice you can delete, change or just stay them.
func (t *Tag) SetVersion(version byte) {
	if version < 3 || version > 4 {
		return
	}
	t.version = version
}

// Save writes tag to the file. If there are no frames in tag, Save will write
// only music part without any ID3v2 information.
func (t *Tag) Save() error {
	// Create a temp file for mp3 file, which will contain new tag
	newFile, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}

	// Make sure we clean up the temp file if it's still around
	defer os.Remove(newFile.Name())

	// If there is at least one frame, write it
	if t.HasAnyFrames() {
		// Form size of new frames
		framesSize, err := util.FormSize(t.allFramesSize())
		if err != nil {
			return err
		}

		// Write to new file new tag header
		if _, err = newFile.Write(formTagHeader(framesSize, t.version)); err != nil {
			return err
		}

		// Write to new file new frames
		if err = t.writeAllFrames(newFile); err != nil {
			return err
		}
	}

	// Seek to a music part of original file
	originalFile := t.file
	if _, err = originalFile.Seek(t.originalSize, os.SEEK_SET); err != nil {
		return err
	}

	// Write to new file the music part
	if _, err = io.Copy(newFile, originalFile); err != nil {
		return err
	}

	// Get original file mode
	originalFileStat, err := originalFile.Stat()
	if err != nil {
		return err
	}

	// Set original file mode to new file
	if err = os.Chmod(newFile.Name(), originalFileStat.Mode()); err != nil {
		return err
	}

	// Close files to allow replacing
	newFile.Close()
	originalFile.Close()

	// Replace original file with new file
	if err = os.Rename(newFile.Name(), originalFile.Name()); err != nil {
		return err
	}

	// Set t.file to new file with original name
	t.file, err = os.Open(originalFile.Name())
	if err != nil {
		return err
	}

	// Set t.originalSize to new size
	t.originalSize = int64(t.allFramesSize())

	return nil
}

// Close closes the tag's file, rendering it unusable for I/O.
// It returns an error, if any.
func (t *Tag) Close() error {
	return t.file.Close()
}

var errBlankID = errors.New("blank ID")

func (t Tag) allFramesSize() int {
	var n int

	n += t.Count() * frameHeaderSize

	for _, frames := range t.AllFrames() {
		for _, f := range frames {
			n += f.Size()
		}
	}

	return n
}

func (t Tag) writeAllFrames(w io.Writer) error {
	bw := bwpool.Get(w)
	defer bwpool.Put(bw)

	for id, frames := range t.AllFrames() {
		for _, f := range frames {
			err := writeFrame(bw, id, f)
			if err == errBlankID {
				continue
			}
			if err != nil {
				return err
			}
		}
	}

	return bw.Flush()
}

func writeFrame(bw *bufio.Writer, id string, frame Framer) error {
	if id == "" {
		return errBlankID
	}

	if err := writeFrameHeader(bw, id, frame.Size()); err != nil {
		return err
	}
	if _, err := frame.WriteTo(bw); err != nil {
		return err
	}

	return nil
}

func writeFrameHeader(bw *bufio.Writer, id string, frameSize int) error {
	size, err := util.FormSize(frameSize)
	if err != nil {
		return err
	}

	bw.WriteString(id)
	bw.Write(size)
	bw.Write([]byte{0, 0})
	return nil
}
<|endoftext|>


<commit_before>package swp

import (
	"fmt"
)

//go:generate msgp

type TcpState int

const (
	// init sequence
	Closed      TcpState = 0
	Listen      TcpState = 1 // server, passive open.
	SynReceived TcpState = 2
	SynSent     TcpState = 3 // client, active open.

	Established TcpState = 4

	// close sequence
	FinWait1  TcpState = 5
	FinWait2  TcpState = 6
	Closing   TcpState = 7
	CloseWait TcpState = 8
	LastAck   TcpState = 9
)

type TcpEvent int

// TcpEvent

const (
	EventStartListen  TcpEvent = 1 // server enters Listen state
	EventStartConnect TcpEvent = 2

	// client enters SynSent state
	// server enters SynReceived state, client enters SynReceived (simultaneous open)
	EventSyn TcpEvent = 3

	// server enters SynReceived
	// client enters Established, does EventSendEstabAck
	EventSynAck TcpEvent = 4

	// client enters Established
	// server enters Established
	EventEstabAck TcpEvent = 5

	EventStartClose        TcpEvent = 6
	EventApplicationClosed TcpEvent = 7

	// close initiator sends Fin, enters FinWait1
	// responder or simultaneous close, enter CloseWait or Closing
	EventFin    TcpEvent = 8
	EventFinAck TcpEvent = 9

	EventReset TcpEvent = 10

	// common acks of data during Established state
	// aka AckOnly
	EventDataAck TcpEvent = 11
	EventData    TcpEvent = 12 // a data packet. Most common. state is Established.

	// a keepalive
	EventKeepAlive TcpEvent = 14

	// FileHeader describing the file to follow
	EventFileHeader TcpEvent = 15
)

type TcpAction int

const (
	NoAction     TcpAction = 0
	SendSyn      TcpAction = 1
	SendSynAck   TcpAction = 2
	SendEstabAck TcpAction = 3
	SendFin      TcpAction = 4
	SendFinAck   TcpAction = 5
	DoAppClose   TcpAction = 6 // after App has closed, then SendFinAck
	SendDataAck  TcpAction = 7
)

// e is the received event
func (s *TcpState) UpdateTcp(e TcpEvent) TcpAction {
	switch *s {
	// init sequence
	case Closed:
		switch e {
		case EventStartListen:
			*s = Listen
		case EventStartConnect:
			*s = SynSent
			return SendSyn
		case EventReset:
			// stay in closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	case Listen:
		switch e {
		case EventSyn:
			*s = SynReceived
			return SendSynAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case SynReceived:
		switch e {
		case EventEstabAck:
			*s = Established
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case SynSent:
		switch e {
		case EventSynAck:
			*s = Established
			return SendEstabAck
		case EventSyn:
			// simultaneous open
			*s = SynReceived
			return SendEstabAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case Established:
		switch e {
		case EventData, EventDataAck:
			// stay in Established
		case EventKeepAlive:
			return SendDataAck
		case EventStartClose:
			*s = FinWait1
			return SendFin
		case EventFin:
			*s = CloseWait
			return DoAppClose

		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case FinWait1:
		switch e {
		case EventFinAck:
			*s = FinWait2
		case EventFin:
			// simultaneous close
			*s = Closing
			return SendFinAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case FinWait2:
		switch e {
		case EventFin:
			*s = Closed
			return SendFinAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case Closing:
		switch e {
		case EventFinAck:
			*s = Closed
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case CloseWait:
		switch e {
		case EventData:
			// ignore
		case EventDataAck:
			// ignore
		case EventApplicationClosed:
			*s = LastAck
			return SendFin
		case EventFin:
			// duplicate Fin, ignore
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	case LastAck:
		switch e {
		case EventFinAck:
			*s = Closed
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	}
	return NoAction
}
<commit_msg>atg. remove EventFileHeader<commit_after>package swp

import (
	"fmt"
)

//go:generate msgp

type TcpState int

const (
	// init sequence
	Closed      TcpState = 0
	Listen      TcpState = 1 // server, passive open.
	SynReceived TcpState = 2
	SynSent     TcpState = 3 // client, active open.

	Established TcpState = 4

	// close sequence
	FinWait1  TcpState = 5
	FinWait2  TcpState = 6
	Closing   TcpState = 7
	CloseWait TcpState = 8
	LastAck   TcpState = 9
)

type TcpEvent int

// TcpEvent

const (
	EventStartListen  TcpEvent = 1 // server enters Listen state
	EventStartConnect TcpEvent = 2

	// client enters SynSent state
	// server enters SynReceived state, client enters SynReceived (simultaneous open)
	EventSyn TcpEvent = 3

	// server enters SynReceived
	// client enters Established, does EventSendEstabAck
	EventSynAck TcpEvent = 4

	// client enters Established
	// server enters Established
	EventEstabAck TcpEvent = 5

	EventStartClose        TcpEvent = 6
	EventApplicationClosed TcpEvent = 7

	// close initiator sends Fin, enters FinWait1
	// responder or simultaneous close, enter CloseWait or Closing
	EventFin    TcpEvent = 8
	EventFinAck TcpEvent = 9

	EventReset TcpEvent = 10

	// common acks of data during Established state
	// aka AckOnly
	EventDataAck TcpEvent = 11
	EventData    TcpEvent = 12 // a data packet. Most common. state is Established.

	// a keepalive
	EventKeepAlive TcpEvent = 14
)

type TcpAction int

const (
	NoAction     TcpAction = 0
	SendSyn      TcpAction = 1
	SendSynAck   TcpAction = 2
	SendEstabAck TcpAction = 3
	SendFin      TcpAction = 4
	SendFinAck   TcpAction = 5
	DoAppClose   TcpAction = 6 // after App has closed, then SendFinAck
	SendDataAck  TcpAction = 7
)

// e is the received event
func (s *TcpState) UpdateTcp(e TcpEvent) TcpAction {
	switch *s {
	// init sequence
	case Closed:
		switch e {
		case EventStartListen:
			*s = Listen
		case EventStartConnect:
			*s = SynSent
			return SendSyn
		case EventReset:
			// stay in closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	case Listen:
		switch e {
		case EventSyn:
			*s = SynReceived
			return SendSynAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case SynReceived:
		switch e {
		case EventEstabAck:
			*s = Established
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case SynSent:
		switch e {
		case EventSynAck:
			*s = Established
			return SendEstabAck
		case EventSyn:
			// simultaneous open
			*s = SynReceived
			return SendEstabAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case Established:
		switch e {
		case EventData, EventDataAck:
			// stay in Established
		case EventKeepAlive:
			return SendDataAck
		case EventStartClose:
			*s = FinWait1
			return SendFin
		case EventFin:
			*s = CloseWait
			return DoAppClose

		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case FinWait1:
		switch e {
		case EventFinAck:
			*s = FinWait2
		case EventFin:
			// simultaneous close
			*s = Closing
			return SendFinAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case FinWait2:
		switch e {
		case EventFin:
			*s = Closed
			return SendFinAck
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case Closing:
		switch e {
		case EventFinAck:
			*s = Closed
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}

	case CloseWait:
		switch e {
		case EventData:
			// ignore
		case EventDataAck:
			// ignore
		case EventApplicationClosed:
			*s = LastAck
			return SendFin
		case EventFin:
			// duplicate Fin, ignore
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	case LastAck:
		switch e {
		case EventFinAck:
			*s = Closed
		case EventReset:
			*s = Closed
		default:
			panic(fmt.Sprintf("invalid event %s from state %s", e, *s))
		}
	}
	return NoAction
}
<|endoftext|>


<commit_before>package command

import (
	"github.com/hashicorp/vault/version"
	"github.com/mitchellh/cli"
)

// VersionCommand is a Command implementation prints the version.
type VersionCommand struct {
	VersionInfo *version.VersionInfo
	Ui          cli.Ui
}

func (c *VersionCommand) Help() string {
	return ""
}

func (c *VersionCommand) Run(_ []string) int {
	c.Ui.Output(c.VersionInfo.FullVersionNumber(true))
	return 0
}

func (c *VersionCommand) Synopsis() string {
	return "Prints the Vault version"
}
<commit_msg>Add cgo info to vault version output<commit_after>package command

import (
	"github.com/hashicorp/vault/version"
	"github.com/mitchellh/cli"
)

// VersionCommand is a Command implementation prints the version.
type VersionCommand struct {
	VersionInfo *version.VersionInfo
	Ui          cli.Ui
}

func (c *VersionCommand) Help() string {
	return ""
}

func (c *VersionCommand) Run(_ []string) int {
	out := c.VersionInfo.FullVersionNumber(true)
	if version.CgoEnabled {
		out += " (cgo)"
	}
	c.Ui.Output(out)
	return 0
}

func (c *VersionCommand) Synopsis() string {
	return "Prints the Vault version"
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"context"
	"os"
	"io/ioutil"
	"os/user"
	"path"

	"github.com/urfave/cli"
	"github.com/cbegin/graven/domain"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
	"github.com/bgentry/speakeasy"
	"github.com/cbegin/graven/util"
	"strings"
)

type ConfigMap map[string]map[string]string
type Validator func(stdout, stderr string) error

var DeployCommand = cli.Command{
	Name: "deploy",
	Usage:       "Deploys artifacts to a repository",
	Action: deploy,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "login",
			Usage: "Prompts for repo login credentials.",
		},
	},
}

func deploy(c *cli.Context) error {
	project, err := domain.FindProject()
	if err != nil {
		return err
	}

	if err := verifyRepoState(project); err != nil {
		return err
	}

	if c.Bool("login") {
		return loginToGithub()
	}

	if err := pkg(c); err != nil {
		return err
	}

	return deployToGithub(project)
}

func loginToGithub() error {
	token, err := readSecret("Please type or paste a github token (will not echo): ")
	config, err := readConfig()
	if err != nil {
		config = ConfigMap{}
	}
	config["github"] = map[string]string{}
	config["github"]["token"] = token
	err = writeConfig(config)
	if err != nil {
		return fmt.Errorf("Error writing configuration file. %v", err)
	}
	return nil
}

func deployToGithub(project *domain.Project) error {

	gh, ctx, err := authenticate()
	if err != nil {
		return err
	}

	repo, ok := project.Repositories["github"]
	if !ok {
		return fmt.Errorf("Sorry, could not find gihub repo configuration")
	}

	ownerName := repo["owner"]
	repoName := repo["repo"]

	tagName := fmt.Sprintf("v%s", project.Version)
	releaseName := tagName
	release := &github.RepositoryRelease{
		TagName: &tagName,
		Name: &releaseName,
	}

	release, _, err = gh.Repositories.CreateRelease(ctx, ownerName, repoName, release)
	if err != nil {
		return err
	}
	fmt.Printf("Created release %v/%v:%v\n", ownerName, repoName, *release.Name)

	for _, a := range project.Artifacts {
		filename := a.ArtifactFile(project)
		sourceFile, err := os.Open(project.TargetPath(filename))
		if err != nil {
			return err
		}
		opts := &github.UploadOptions{
			Name: filename,
		}
		_, _, err = gh.Repositories.UploadReleaseAsset(ctx, ownerName, repoName, *release.ID, opts, sourceFile)
		if err != nil {
			return err
		}
		fmt.Printf("Uploaded %v/%v/%v\n", ownerName, repoName, filename)
	}

	return err
}

func authenticate() (*github.Client, context.Context, error) {
	config, err := readConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("Error reading configuration (try: deploy --login): %v", err)
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config["github"]["token"]},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	return client, ctx, nil
}

func readSecret(prompt string) (string, error) {
	password, err := speakeasy.Ask(prompt)
	if err != nil {
		return "", fmt.Errorf("Error reading secret from terminal: %v", err)
	}
	return password, nil
}

func readConfig() (ConfigMap, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, err
	}
	file, err := os.Open(path.Join(usr.HomeDir, ".graven.yaml"))
	if err != nil {
		return nil, err
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return nil, err
	}
	config := ConfigMap{}
	err = yaml.Unmarshal(bytes, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

func writeConfig(config ConfigMap) (error) {
	usr, err := user.Current()
	if err != nil {
		return err
	}
	bytes, err := yaml.Marshal(config)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(usr.HomeDir, ".graven.yaml"), bytes, 0600)
	if err != nil {
		return err
	}

	return nil
}

func verifyRepoState(project *domain.Project) error {
	remoteName := "origin"
	branchName := "master"

	// Check if on expected branch (e.g. master)
	if err := verifyGitState(func(stdout, stderr string) error {
		actualBranch := strings.TrimSpace(stdout)
		if actualBranch != branchName {
			return fmt.Errorf("Expected to be on branch %v but found branch %v", branchName, actualBranch)
		}
		return nil
	}, project, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	}

	// Ensure no uncommitted changes
	if err := verifyGitState(func(stdout, stderr string) error {
		if strings.TrimSpace(stdout) != "" || strings.TrimSpace(stderr) != "" {
			return fmt.Errorf("Cannot deploy with uncommitted changes.")
		}

		fmt.Println(stdout)
		fmt.Println(stderr)
		return nil
	}, project, "status", "--porcelain"); err != nil {
		return err
	}

	// Check if changes exist on server
	if err := verifyGitState(func(stdout, stderr string) error {
		fmt.Println(stdout)
		return nil
	}, project, "fetch", "--dry-run", remoteName, branchName); err != nil {
		return err
	}

	if err := verifyGitState(func(stdout, stderr string) error {
		return nil
	}, project, "rev-parse", branchName, fmt.Sprintf("%v/%v", remoteName, branchName)); err != nil {
		return err
	}

	return fmt.Errorf("Testing...")
}

func verifyGitState(validator Validator, project *domain.Project, args... string) error {
	sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", args...)
	if err != nil {
		return fmt.Errorf("ERROR running Git command: %v\n", err)
	}
	return validator(sout, serr)
}<commit_msg>intermediate commit while working on git validation<commit_after>package commands

import (
	"fmt"
	"context"
	"os"
	"io/ioutil"
	"os/user"
	"path"

	"github.com/urfave/cli"
	"github.com/cbegin/graven/domain"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
	"github.com/bgentry/speakeasy"
	"github.com/cbegin/graven/util"
	"strings"
)

type ConfigMap map[string]map[string]string
type Validator func(stdout, stderr string) error

var DeployCommand = cli.Command{
	Name: "deploy",
	Usage:       "Deploys artifacts to a repository",
	Action: deploy,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "login",
			Usage: "Prompts for repo login credentials.",
		},
	},
}

func deploy(c *cli.Context) error {
	project, err := domain.FindProject()
	if err != nil {
		return err
	}

	if err := verifyRepoState(project); err != nil {
		return err
	}

	if c.Bool("login") {
		return loginToGithub()
	}

	if err := pkg(c); err != nil {
		return err
	}

	return deployToGithub(project)
}

func loginToGithub() error {
	token, err := readSecret("Please type or paste a github token (will not echo): ")
	config, err := readConfig()
	if err != nil {
		config = ConfigMap{}
	}
	config["github"] = map[string]string{}
	config["github"]["token"] = token
	err = writeConfig(config)
	if err != nil {
		return fmt.Errorf("Error writing configuration file. %v", err)
	}
	return nil
}

func deployToGithub(project *domain.Project) error {

	gh, ctx, err := authenticate()
	if err != nil {
		return err
	}

	repo, ok := project.Repositories["github"]
	if !ok {
		return fmt.Errorf("Sorry, could not find gihub repo configuration")
	}

	ownerName := repo["owner"]
	repoName := repo["repo"]

	tagName := fmt.Sprintf("v%s", project.Version)
	releaseName := tagName
	release := &github.RepositoryRelease{
		TagName: &tagName,
		Name: &releaseName,
	}

	release, _, err = gh.Repositories.CreateRelease(ctx, ownerName, repoName, release)
	if err != nil {
		return err
	}
	fmt.Printf("Created release %v/%v:%v\n", ownerName, repoName, *release.Name)

	for _, a := range project.Artifacts {
		filename := a.ArtifactFile(project)
		sourceFile, err := os.Open(project.TargetPath(filename))
		if err != nil {
			return err
		}
		opts := &github.UploadOptions{
			Name: filename,
		}
		_, _, err = gh.Repositories.UploadReleaseAsset(ctx, ownerName, repoName, *release.ID, opts, sourceFile)
		if err != nil {
			return err
		}
		fmt.Printf("Uploaded %v/%v/%v\n", ownerName, repoName, filename)
	}

	return err
}

func authenticate() (*github.Client, context.Context, error) {
	config, err := readConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("Error reading configuration (try: deploy --login): %v", err)
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config["github"]["token"]},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	return client, ctx, nil
}

func readSecret(prompt string) (string, error) {
	password, err := speakeasy.Ask(prompt)
	if err != nil {
		return "", fmt.Errorf("Error reading secret from terminal: %v", err)
	}
	return password, nil
}

func readConfig() (ConfigMap, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, err
	}
	file, err := os.Open(path.Join(usr.HomeDir, ".graven.yaml"))
	if err != nil {
		return nil, err
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return nil, err
	}
	config := ConfigMap{}
	err = yaml.Unmarshal(bytes, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

func writeConfig(config ConfigMap) (error) {
	usr, err := user.Current()
	if err != nil {
		return err
	}
	bytes, err := yaml.Marshal(config)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(usr.HomeDir, ".graven.yaml"), bytes, 0600)
	if err != nil {
		return err
	}

	return nil
}

func verifyRepoState(project *domain.Project) error {
	remoteName := "origin"
	branchName := "master"

	// Check if on expected branch (e.g. master)
	if err := verifyGitState(func(stdout, stderr string) error {
		actualBranch := strings.TrimSpace(stdout)
		if actualBranch != branchName {
			return fmt.Errorf("Expected to be on branch %v but found branch %v", branchName, actualBranch)
		}
		return nil
	}, project, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	}

	// Ensure no uncommitted changes
	if err := verifyGitState(func(stdout, stderr string) error {
		if strings.TrimSpace(stdout) != "" || strings.TrimSpace(stderr) != "" {
			return fmt.Errorf("Cannot deploy with uncommitted changes.")
		}

		fmt.Println(stdout)
		fmt.Println(stderr)
		return nil
	}, project, "status", "--porcelain"); err != nil {
		return err
	}

	// Check if changes exist on server
	if err := verifyGitState(func(stdout, stderr string) error {
		fmt.Println(stdout)
		fmt.Println(stderr)
		return nil
	}, project, "fetch", "--dry-run", remoteName, branchName); err != nil {
		return err
	}

	if err := verifyGitState(func(stdout, stderr string) error {
		return nil
	}, project, "rev-parse", branchName, fmt.Sprintf("%v/%v", remoteName, branchName)); err != nil {
		return err
	}

	return fmt.Errorf("Testing...")
}

func verifyGitState(validator Validator, project *domain.Project, args... string) error {
	sout, serr, err := util.RunCommand(project.ProjectPath(), nil, "git", args...)
	if err != nil {
		return fmt.Errorf("ERROR running Git command: %v\n", err)
	}
	return validator(sout, serr)
}<|endoftext|>