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