github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/uniter/runner/jujuc/ports_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Copyright 2014 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  package jujuc_test
     6  
     7  import (
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/juju/cmd"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/network"
    16  	"github.com/juju/juju/testing"
    17  	"github.com/juju/juju/worker/uniter/runner/jujuc"
    18  )
    19  
    20  type PortsSuite struct {
    21  	ContextSuite
    22  }
    23  
    24  var _ = gc.Suite(&PortsSuite{})
    25  
    26  var portsTests = []struct {
    27  	cmd    []string
    28  	expect []network.PortRange
    29  }{
    30  	{[]string{"open-port", "80"}, makeRanges("80/tcp")},
    31  	{[]string{"open-port", "99/tcp"}, makeRanges("80/tcp", "99/tcp")},
    32  	{[]string{"open-port", "100-200"}, makeRanges("80/tcp", "99/tcp", "100-200/tcp")},
    33  	{[]string{"open-port", "443/udp"}, makeRanges("80/tcp", "99/tcp", "100-200/tcp", "443/udp")},
    34  	{[]string{"close-port", "80/TCP"}, makeRanges("99/tcp", "100-200/tcp", "443/udp")},
    35  	{[]string{"close-port", "100-200/tcP"}, makeRanges("99/tcp", "443/udp")},
    36  	{[]string{"close-port", "443"}, makeRanges("99/tcp", "443/udp")},
    37  	{[]string{"close-port", "443/udp"}, makeRanges("99/tcp")},
    38  	{[]string{"open-port", "123/udp"}, makeRanges("99/tcp", "123/udp")},
    39  	{[]string{"close-port", "9999/UDP"}, makeRanges("99/tcp", "123/udp")},
    40  }
    41  
    42  func makeRanges(stringRanges ...string) []network.PortRange {
    43  	var results []network.PortRange
    44  	for _, s := range stringRanges {
    45  		if strings.Contains(s, "-") {
    46  			parts := strings.Split(s, "-")
    47  			fromPort, _ := strconv.Atoi(parts[0])
    48  			parts = strings.Split(parts[1], "/")
    49  			toPort, _ := strconv.Atoi(parts[0])
    50  			proto := parts[1]
    51  			results = append(results, network.PortRange{
    52  				FromPort: fromPort,
    53  				ToPort:   toPort,
    54  				Protocol: proto,
    55  			})
    56  		} else {
    57  			parts := strings.Split(s, "/")
    58  			port, _ := strconv.Atoi(parts[0])
    59  			proto := parts[1]
    60  			results = append(results, network.PortRange{
    61  				FromPort: port,
    62  				ToPort:   port,
    63  				Protocol: proto,
    64  			})
    65  		}
    66  	}
    67  	network.SortPortRanges(results)
    68  	return results
    69  }
    70  
    71  func (s *PortsSuite) TestOpenClose(c *gc.C) {
    72  	hctx := s.GetHookContext(c, -1, "")
    73  	for _, t := range portsTests {
    74  		com, err := jujuc.NewCommand(hctx, cmdString(t.cmd[0]))
    75  		c.Assert(err, jc.ErrorIsNil)
    76  		ctx := testing.Context(c)
    77  		code := cmd.Main(com, ctx, t.cmd[1:])
    78  		c.Assert(code, gc.Equals, 0)
    79  		c.Assert(bufferString(ctx.Stdout), gc.Equals, "")
    80  		c.Assert(bufferString(ctx.Stderr), gc.Equals, "")
    81  		hctx.info.CheckPorts(c, t.expect)
    82  	}
    83  }
    84  
    85  var badPortsTests = []struct {
    86  	args []string
    87  	err  string
    88  }{
    89  	{nil, "no port or range specified"},
    90  	{[]string{"0"}, `port must be in the range \[1, 65535\]; got "0"`},
    91  	{[]string{"65536"}, `port must be in the range \[1, 65535\]; got "65536"`},
    92  	{[]string{"two"}, `expected <port>\[/<protocol>\] or <from>-<to>\[/<protocol>\]; got "two"`},
    93  	{[]string{"80/http"}, `protocol must be "tcp" or "udp"; got "http"`},
    94  	{[]string{"blah/blah/blah"}, `expected <port>\[/<protocol>\] or <from>-<to>\[/<protocol>\]; got "blah/blah/blah"`},
    95  	{[]string{"123", "haha"}, `unrecognized args: \["haha"\]`},
    96  	{[]string{"1-0"}, `invalid port range 1-0/tcp; expected fromPort <= toPort`},
    97  	{[]string{"-42"}, `flag provided but not defined: -4`},
    98  	{[]string{"99999/UDP"}, `port must be in the range \[1, 65535\]; got "99999"`},
    99  	{[]string{"9999/foo"}, `protocol must be "tcp" or "udp"; got "foo"`},
   100  	{[]string{"80-90/http"}, `protocol must be "tcp" or "udp"; got "http"`},
   101  	{[]string{"20-10/tcp"}, `invalid port range 20-10/tcp; expected fromPort <= toPort`},
   102  }
   103  
   104  func (s *PortsSuite) TestBadArgs(c *gc.C) {
   105  	for _, name := range []string{"open-port", "close-port"} {
   106  		for _, t := range badPortsTests {
   107  			hctx := s.GetHookContext(c, -1, "")
   108  			com, err := jujuc.NewCommand(hctx, cmdString(name))
   109  			c.Assert(err, jc.ErrorIsNil)
   110  			err = testing.InitCommand(com, t.args)
   111  			c.Assert(err, gc.ErrorMatches, t.err)
   112  		}
   113  	}
   114  }
   115  
   116  func (s *PortsSuite) TestHelp(c *gc.C) {
   117  	hctx := s.GetHookContext(c, -1, "")
   118  	open, err := jujuc.NewCommand(hctx, cmdString("open-port"))
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	flags := testing.NewFlagSet()
   121  	c.Assert(string(open.Info().Help(flags)), gc.Equals, `
   122  Usage: open-port <port>[/<protocol>] or <from>-<to>[/<protocol>]
   123  
   124  Summary:
   125  register a port or range to open
   126  
   127  Details:
   128  The port range will only be open while the service is exposed.
   129  `[1:])
   130  
   131  	close, err := jujuc.NewCommand(hctx, cmdString("close-port"))
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	c.Assert(string(close.Info().Help(flags)), gc.Equals, `
   134  Usage: close-port <port>[/<protocol>] or <from>-<to>[/<protocol>]
   135  
   136  Summary:
   137  ensure a port or range is always closed
   138  `[1:])
   139  }
   140  
   141  // Since the deprecation warning gets output during Run, we really need
   142  // some valid commands to run
   143  var portsFormatDeprectaionTests = []struct {
   144  	cmd []string
   145  }{
   146  	{[]string{"open-port", "--format", "foo", "80"}},
   147  	{[]string{"close-port", "--format", "foo", "80/TCP"}},
   148  }
   149  
   150  func (s *PortsSuite) TestOpenCloseDeprecation(c *gc.C) {
   151  	hctx := s.GetHookContext(c, -1, "")
   152  	for _, t := range portsFormatDeprectaionTests {
   153  		name := t.cmd[0]
   154  		com, err := jujuc.NewCommand(hctx, cmdString(name))
   155  		c.Assert(err, jc.ErrorIsNil)
   156  		ctx := testing.Context(c)
   157  		code := cmd.Main(com, ctx, t.cmd[1:])
   158  		c.Assert(code, gc.Equals, 0)
   159  		c.Assert(testing.Stdout(ctx), gc.Equals, "")
   160  		c.Assert(testing.Stderr(ctx), gc.Equals, "--format flag deprecated for command \""+name+"\"")
   161  	}
   162  }