github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/runner/jujuc/network-get_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc_test
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/cmd/cmdtesting"
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/worker/uniter/runner/jujuc"
    18  )
    19  
    20  type NetworkGetSuite struct {
    21  	ContextSuite
    22  }
    23  
    24  var _ = gc.Suite(&NetworkGetSuite{})
    25  
    26  func (s *NetworkGetSuite) SetUpSuite(c *gc.C) {
    27  	s.ContextSuite.SetUpSuite(c)
    28  	lookupHost := func(host string) (addrs []string, err error) {
    29  		return []string{"10.3.3.3"}, nil
    30  	}
    31  	testing.PatchValue(&jujuc.LookupHost, lookupHost)
    32  }
    33  
    34  func (s *NetworkGetSuite) createCommand(c *gc.C) cmd.Command {
    35  	hctx := s.GetHookContext(c, -1, "")
    36  
    37  	presetBindings := make(map[string]params.NetworkInfoResult)
    38  	presetBindings["known-relation"] = params.NetworkInfoResult{
    39  		Info: []params.NetworkInfo{
    40  			{MACAddress: "00:11:22:33:44:00",
    41  				InterfaceName: "eth0",
    42  				Addresses: []params.InterfaceAddress{
    43  					{
    44  						Address: "10.10.0.23",
    45  						CIDR:    "10.10.0.0/24",
    46  					},
    47  					{
    48  						Address: "192.168.1.111",
    49  						CIDR:    "192.168.1.0/24",
    50  					},
    51  				},
    52  			},
    53  			{MACAddress: "00:11:22:33:44:11",
    54  				InterfaceName: "eth1",
    55  				Addresses: []params.InterfaceAddress{
    56  					{
    57  						Address: "10.10.1.23",
    58  						CIDR:    "10.10.1.0/24",
    59  					},
    60  					{
    61  						Address: "192.168.2.111",
    62  						CIDR:    "192.168.2.0/24",
    63  					},
    64  				},
    65  			},
    66  		},
    67  	}
    68  	presetBindings["known-extra"] = params.NetworkInfoResult{
    69  		Info: []params.NetworkInfo{
    70  			{MACAddress: "00:11:22:33:44:22",
    71  				InterfaceName: "eth2",
    72  				Addresses: []params.InterfaceAddress{
    73  					{
    74  						Address: "10.20.1.42",
    75  						CIDR:    "10.20.1.42/24",
    76  					},
    77  					{
    78  						Address: "fc00::1",
    79  						CIDR:    "fc00::/64",
    80  					},
    81  				},
    82  			},
    83  		},
    84  	}
    85  	presetBindings["valid-no-config"] = params.NetworkInfoResult{}
    86  	// Simulate known but unspecified bindings.
    87  	presetBindings["known-unbound"] = params.NetworkInfoResult{
    88  		Info: []params.NetworkInfo{
    89  			{MACAddress: "00:11:22:33:44:33",
    90  				InterfaceName: "eth3",
    91  				Addresses: []params.InterfaceAddress{
    92  					{
    93  						Address: "10.33.1.8",
    94  						CIDR:    "10.33.1.8/24",
    95  					},
    96  				},
    97  			},
    98  		},
    99  	}
   100  	// Simulate info with egress and ingress data.
   101  	presetBindings["ingress-egress"] = params.NetworkInfoResult{
   102  		Info: []params.NetworkInfo{
   103  			{MACAddress: "00:11:22:33:44:33",
   104  				InterfaceName: "eth3",
   105  				Addresses: []params.InterfaceAddress{
   106  					{
   107  						Address: "10.33.1.8",
   108  						CIDR:    "10.33.1.8/24",
   109  					},
   110  				},
   111  			},
   112  		},
   113  		IngressAddresses: []string{"100.1.2.3", "100.4.3.2"},
   114  		EgressSubnets:    []string{"192.168.1.0/8", "10.0.0.0/8"},
   115  	}
   116  
   117  	// This should not happen. A hostname should never populate the address
   118  	// field. However, until the code is updated to prevent addresses from
   119  	// being populated by Hostnames (e.g. Change the Address field type from
   120  	// `string` to `net.IP` which will ensure all code paths exclude string
   121  	// population) we will have this check in place to ensure that hostnames
   122  	// are resolved to IPs and that hostnames populate a distinct field.
   123  	// `network-get --primary-address` and the like should only ever return
   124  	// IPs.
   125  	presetBindings["resolvable-hostname"] = params.NetworkInfoResult{
   126  		Info: []params.NetworkInfo{
   127  			{MACAddress: "00:11:22:33:44:33",
   128  				InterfaceName: "eth3",
   129  				Addresses: []params.InterfaceAddress{
   130  					{
   131  						Address: "resolvable-hostname",
   132  						CIDR:    "10.33.1.8/24",
   133  					},
   134  				},
   135  			},
   136  		},
   137  		IngressAddresses: []string{"resolvable-hostname"},
   138  	}
   139  
   140  	hctx.info.NetworkInterface.NetworkInfoResults = presetBindings
   141  
   142  	com, err := jujuc.NewCommand(hctx, cmdString("network-get"))
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	return jujuc.NewJujucCommandWrappedForTest(com)
   145  }
   146  
   147  func (s *NetworkGetSuite) TestNetworkGet(c *gc.C) {
   148  	for i, t := range []struct {
   149  		summary  string
   150  		args     []string
   151  		code     int
   152  		out      string
   153  		checkctx func(*gc.C, *cmd.Context)
   154  	}{{
   155  		summary: "no arguments",
   156  		code:    2,
   157  		out:     `no arguments specified`,
   158  	}, {
   159  		summary: "empty binding name specified",
   160  		code:    2,
   161  		args:    []string{""},
   162  		out:     `no binding name specified`,
   163  	}, {
   164  		summary: "unknown binding given, no extra args given",
   165  		code:    1,
   166  		args:    []string{"unknown"},
   167  		out:     `no network config found for binding "unknown"`,
   168  	}, {
   169  		summary: "unknown binding given, with additional args",
   170  		args:    []string{"unknown", "--ingress-address"},
   171  		code:    1,
   172  		out:     `no network config found for binding "unknown"`,
   173  	}, {
   174  		summary: "API server returns no config for this binding, with --ingress-address",
   175  		args:    []string{"valid-no-config", "--ingress-address"},
   176  		code:    1,
   177  		out:     `no network config found for binding "valid-no-config"`,
   178  	}, {
   179  		summary: "API server returns no config for this binding, no address args",
   180  		args:    []string{"valid-no-config"},
   181  		code:    1,
   182  		out:     `no network config found for binding "valid-no-config"`,
   183  	}, {
   184  		summary: "explicitly bound, extra-binding name given with single flag arg",
   185  		args:    []string{"known-extra", "--ingress-address"},
   186  		out:     "10.20.1.42",
   187  	}, {
   188  		summary: "explicitly bound, extra-binding name given with multiple flag args",
   189  		args:    []string{"known-extra", "--ingress-address", "--bind-address"},
   190  		out: `
   191  bind-address: 10.20.1.42
   192  ingress-address: 10.20.1.42`[1:],
   193  	}, {
   194  		summary: "explicitly bound, extra-binding name given without extra args",
   195  		args:    []string{"known-extra"},
   196  		out: `
   197  bind-addresses:
   198  - macaddress: "00:11:22:33:44:22"
   199    interfacename: eth2
   200    addresses:
   201    - hostname: ""
   202      address: 10.20.1.42
   203      cidr: 10.20.1.42/24
   204    - hostname: ""
   205      address: fc00::1
   206      cidr: fc00::/64`[1:],
   207  	}, {
   208  		summary: "explicitly bound relation name given with single flag arg",
   209  		args:    []string{"known-relation", "--ingress-address"},
   210  		out:     "10.10.0.23",
   211  	}, {
   212  		summary: "explicitly bound relation name given without extra args",
   213  		args:    []string{"known-relation"},
   214  		out: `
   215  bind-addresses:
   216  - macaddress: "00:11:22:33:44:00"
   217    interfacename: eth0
   218    addresses:
   219    - hostname: ""
   220      address: 10.10.0.23
   221      cidr: 10.10.0.0/24
   222    - hostname: ""
   223      address: 192.168.1.111
   224      cidr: 192.168.1.0/24
   225  - macaddress: "00:11:22:33:44:11"
   226    interfacename: eth1
   227    addresses:
   228    - hostname: ""
   229      address: 10.10.1.23
   230      cidr: 10.10.1.0/24
   231    - hostname: ""
   232      address: 192.168.2.111
   233      cidr: 192.168.2.0/24`[1:],
   234  	}, {
   235  		summary: "no user requested binding falls back to binding address, with ingress-address arg",
   236  		args:    []string{"known-unbound", "--ingress-address"},
   237  		out:     "10.33.1.8",
   238  	}, {
   239  		summary: "no user requested binding falls back to primary address, without address args",
   240  		args:    []string{"known-unbound"},
   241  		out: `
   242  bind-addresses:
   243  - macaddress: "00:11:22:33:44:33"
   244    interfacename: eth3
   245    addresses:
   246    - hostname: ""
   247      address: 10.33.1.8
   248      cidr: 10.33.1.8/24`[1:],
   249  	}, {
   250  		summary: "explicit ingress and egress information",
   251  		args:    []string{"ingress-egress", "--ingress-address", "--bind-address", "--egress-subnets"},
   252  		out: `
   253  bind-address: 10.33.1.8
   254  egress-subnets:
   255  - 192.168.1.0/8
   256  - 10.0.0.0/8
   257  ingress-address: 100.1.2.3`[1:],
   258  	}, {
   259  		summary: "explicit ingress and egress information, no extra args",
   260  		args:    []string{"ingress-egress"},
   261  		out: `
   262  bind-addresses:
   263  - macaddress: "00:11:22:33:44:33"
   264    interfacename: eth3
   265    addresses:
   266    - hostname: ""
   267      address: 10.33.1.8
   268      cidr: 10.33.1.8/24
   269  egress-subnets:
   270  - 192.168.1.0/8
   271  - 10.0.0.0/8
   272  ingress-addresses:
   273  - 100.1.2.3
   274  - 100.4.3.2`[1:],
   275  	}, {
   276  		summary: "a resolvable hostname as address, no args",
   277  		args:    []string{"resolvable-hostname"},
   278  		out: `
   279  bind-addresses:
   280  - macaddress: "00:11:22:33:44:33"
   281    interfacename: eth3
   282    addresses:
   283    - hostname: resolvable-hostname
   284      address: 10.3.3.3
   285      cidr: 10.33.1.8/24
   286  ingress-addresses:
   287  - 10.3.3.3`[1:],
   288  	}} {
   289  		c.Logf("test %d: %s", i, t.summary)
   290  		com := s.createCommand(c)
   291  		ctx := cmdtesting.Context(c)
   292  		code := cmd.Main(com, ctx, t.args)
   293  		c.Check(code, gc.Equals, t.code)
   294  		if code == 0 {
   295  			c.Check(bufferString(ctx.Stderr), gc.Equals, "")
   296  			expect := t.out
   297  			if expect != "" {
   298  				expect = expect + "\n"
   299  			}
   300  			c.Check(bufferString(ctx.Stdout), gc.Equals, expect)
   301  		} else {
   302  			c.Check(bufferString(ctx.Stdout), gc.Equals, "")
   303  			expect := fmt.Sprintf(`(.|\n)*ERROR %s\n`, t.out)
   304  			c.Check(bufferString(ctx.Stderr), gc.Matches, expect)
   305  		}
   306  	}
   307  }
   308  
   309  func (s *NetworkGetSuite) TestHelp(c *gc.C) {
   310  
   311  	helpLine := `Usage: network-get [options] <binding-name> [--ingress-address] [--bind-address] [--egress-subnets]`
   312  
   313  	com := s.createCommand(c)
   314  	ctx := cmdtesting.Context(c)
   315  	code := cmd.Main(com, ctx, []string{"--help"})
   316  	c.Check(code, gc.Equals, 0)
   317  
   318  	c.Check(strings.Split(bufferString(ctx.Stdout), "\n")[0], gc.Equals, helpLine)
   319  	c.Check(bufferString(ctx.Stderr), gc.Equals, "")
   320  }