github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/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 "strings" 9 10 "github.com/juju/cmd/v3" 11 "github.com/juju/errors" 12 "github.com/juju/gnuflag" 13 14 jujucmd "github.com/juju/juju/cmd" 15 "github.com/juju/juju/core/network" 16 ) 17 18 const ( 19 portFormat = "<port>[/<protocol>] or <from>-<to>[/<protocol>] or icmp" 20 ) 21 22 // portCommand implements the open-port and close-port commands. 23 type portCommand struct { 24 cmd.CommandBase 25 info *cmd.Info 26 action func(*portCommand) error 27 portRange network.PortRange 28 endpoints string 29 formatFlag string // deprecated 30 31 } 32 33 func (c *portCommand) Info() *cmd.Info { 34 return jujucmd.Info(c.info) 35 } 36 37 func (c *portCommand) SetFlags(f *gnuflag.FlagSet) { 38 f.StringVar(&c.formatFlag, "format", "", "deprecated format flag") 39 f.StringVar(&c.endpoints, "endpoints", "", "a comma-delimited list of application endpoints to target with this operation") 40 } 41 42 func (c *portCommand) Init(args []string) error { 43 if args == nil { 44 return errors.Errorf("no port or range specified") 45 } 46 47 portRange, err := network.ParsePortRange(strings.ToLower(args[0])) 48 if err != nil { 49 return errors.Trace(err) 50 } 51 c.portRange = portRange 52 53 return cmd.CheckEmpty(args[1:]) 54 } 55 56 func (c *portCommand) Run(ctx *cmd.Context) error { 57 if c.formatFlag != "" { 58 fmt.Fprintf(ctx.Stderr, "--format flag deprecated for command %q", c.Info().Name) 59 } 60 return c.action(c) 61 } 62 63 var openPortInfo = &cmd.Info{ 64 Name: "open-port", 65 Args: portFormat, 66 Purpose: "register a request to open a port or port range", 67 Doc: ` 68 open-port registers a request to open the specified port or port range. 69 70 By default, the specified port or port range will be opened for all defined 71 application endpoints. The --endpoints option can be used to constrain the 72 open request to a comma-delimited list of application endpoints. 73 `, 74 } 75 76 func NewOpenPortCommand(ctx Context) (cmd.Command, error) { 77 return &portCommand{ 78 info: openPortInfo, 79 action: makePortRangeCommand(ctx.OpenPortRange), 80 }, nil 81 } 82 83 var closePortInfo = &cmd.Info{ 84 Name: "close-port", 85 Args: portFormat, 86 Purpose: "register a request to close a port or port range", 87 Doc: ` 88 close-port registers a request to close the specified port or port range. 89 90 By default, the specified port or port range will be closed for all defined 91 application endpoints. The --endpoints option can be used to constrain the 92 close request to a comma-delimited list of application endpoints. 93 `, 94 } 95 96 func NewClosePortCommand(ctx Context) (cmd.Command, error) { 97 return &portCommand{ 98 info: closePortInfo, 99 action: makePortRangeCommand(ctx.ClosePortRange), 100 }, nil 101 } 102 103 func makePortRangeCommand(op func(string, network.PortRange) error) func(*portCommand) error { 104 return func(c *portCommand) error { 105 // Operation applies to all endpoints 106 if c.endpoints == "" { 107 return op("", c.portRange) 108 } 109 110 for _, endpoint := range strings.Split(c.endpoints, ",") { 111 endpoint = strings.TrimSpace(endpoint) 112 if err := op(endpoint, c.portRange); err != nil { 113 return errors.Trace(err) 114 } 115 } 116 117 return nil 118 } 119 }