launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/worker/uniter/jujuc/ports.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"fmt"
     8  	"launchpad.net/errgo/errors"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"launchpad.net/gnuflag"
    13  
    14  	"launchpad.net/juju-core/cmd"
    15  )
    16  
    17  const portFormat = "<port>[/<protocol>]"
    18  
    19  // portCommand implements the open-port and close-port commands.
    20  type portCommand struct {
    21  	cmd.CommandBase
    22  	info       *cmd.Info
    23  	action     func(*portCommand) error
    24  	Protocol   string
    25  	Port       int
    26  	formatFlag string // deprecated
    27  }
    28  
    29  func (c *portCommand) Info() *cmd.Info {
    30  	return c.info
    31  }
    32  
    33  func badPort(value interface{}) error {
    34  	return errors.Newf(`port must be in the range [1, 65535]; got "%v"`, value)
    35  }
    36  
    37  func (c *portCommand) SetFlags(f *gnuflag.FlagSet) {
    38  	f.StringVar(&c.formatFlag, "format", "", "deprecated format flag")
    39  }
    40  
    41  func (c *portCommand) Init(args []string) error {
    42  	if args == nil {
    43  		return errors.New("no port specified")
    44  	}
    45  	parts := strings.Split(args[0], "/")
    46  	if len(parts) > 2 {
    47  		return errors.Newf("expected %s; got %q", portFormat, args[0])
    48  	}
    49  	port, err := strconv.Atoi(parts[0])
    50  	if err != nil {
    51  		return badPort(parts[0])
    52  	}
    53  	if port < 1 || port > 65535 {
    54  		return badPort(port)
    55  	}
    56  	protocol := "tcp"
    57  	if len(parts) == 2 {
    58  		protocol = strings.ToLower(parts[1])
    59  		if protocol != "tcp" && protocol != "udp" {
    60  			return errors.Newf(`protocol must be "tcp" or "udp"; got %q`, protocol)
    61  		}
    62  	}
    63  	c.Port = port
    64  	c.Protocol = protocol
    65  	return cmd.CheckEmpty(args[1:])
    66  }
    67  
    68  func (c *portCommand) Run(ctx *cmd.Context) error {
    69  	if c.formatFlag != "" {
    70  		fmt.Fprintf(ctx.Stderr, "--format flag deprecated for command %q", c.Info().Name)
    71  	}
    72  	return c.action(c)
    73  }
    74  
    75  var openPortInfo = &cmd.Info{
    76  	Name:    "open-port",
    77  	Args:    portFormat,
    78  	Purpose: "register a port to open",
    79  	Doc:     "The port will only be open while the service is exposed.",
    80  }
    81  
    82  func NewOpenPortCommand(ctx Context) cmd.Command {
    83  	return &portCommand{
    84  		info: openPortInfo,
    85  		action: func(c *portCommand) error {
    86  			return ctx.OpenPort(c.Protocol, c.Port)
    87  		},
    88  	}
    89  }
    90  
    91  var closePortInfo = &cmd.Info{
    92  	Name:    "close-port",
    93  	Args:    portFormat,
    94  	Purpose: "ensure a port is always closed",
    95  }
    96  
    97  func NewClosePortCommand(ctx Context) cmd.Command {
    98  	return &portCommand{
    99  		info: closePortInfo,
   100  		action: func(c *portCommand) error {
   101  			return ctx.ClosePort(c.Protocol, c.Port)
   102  		},
   103  	}
   104  }