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 }