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 }