Skip to content

Commit

Permalink
test: api_network_test: add new check points
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Jia <chuanchang.jia@gmail.com>
  • Loading branch information
chuanchang committed Oct 23, 2018
1 parent b093808 commit 5013265
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 118 deletions.
115 changes: 0 additions & 115 deletions apis/opts/networks.go
Original file line number Diff line number Diff line change
@@ -1,115 +0,0 @@
package opts

import (
"fmt"
"net"
"strings"

"github.com/alibaba/pouch/apis/types"
)

// ParseNetworks parses network configurations of container.
func ParseNetworks(networks []string) (*types.NetworkingConfig, string, error) {
var networkMode string
if len(networks) == 0 {
networkMode = "bridge"
}
networkingConfig := &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
}
for _, network := range networks {
name, parameter, mode, err := parseNetwork(network)
if err != nil {
return nil, "", err
}

if networkMode == "" || mode == "mode" {
networkMode = name
}

if name == "container" {
networkMode = fmt.Sprintf("%s:%s", name, parameter)
} else if ipaddr := net.ParseIP(parameter); ipaddr != nil {
networkingConfig.EndpointsConfig[name] = &types.EndpointSettings{
IPAddress: parameter,
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: parameter,
},
}
}
}

return networkingConfig, networkMode, nil
}

// network format as below:
// [network]:[ip_address], such as: mynetwork:172.17.0.2 or mynetwork(ip alloc by ipam) or 172.17.0.2(default network is bridge)
// [network_mode]:[parameter], such as: host(use host network) or container:containerID(use exist container network)
// [network_mode]:[parameter]:mode, such as: mynetwork:172.17.0.2:mode(if the container has multi-networks, the network is the default network mode)
func parseNetwork(network string) (string, string, string, error) {
var (
name string
parameter string
mode string
)
if network == "" {
return "", "", "", fmt.Errorf("invalid network: cannot be empty")
}
arr := strings.Split(network, ":")
switch len(arr) {
case 1:
if ipaddr := net.ParseIP(arr[0]); ipaddr != nil {
parameter = arr[0]
} else {
name = arr[0]
}
case 2:
name = arr[0]
if name == "container" {
parameter = arr[1]
} else if ipaddr := net.ParseIP(arr[1]); ipaddr != nil {
parameter = arr[1]
} else {
mode = arr[1]
}
default:
name = arr[0]
parameter = arr[1]
mode = arr[2]
}

return name, parameter, mode, nil
}

// ValidateNetworks verifies network configurations of container.
func ValidateNetworks(nwConfig *types.NetworkingConfig) error {
if nwConfig == nil || len(nwConfig.EndpointsConfig) == 0 {
return nil
}

// FIXME(ziren): this limitation may be removed in future
// Now not create more then one interface for container is not allowed
if len(nwConfig.EndpointsConfig) > 1 {
l := make([]string, 0, len(nwConfig.EndpointsConfig))
for k := range nwConfig.EndpointsConfig {
l = append(l, k)
}

return fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
}

// len(nwConfig.EndpointsConfig) == 1
for k, v := range nwConfig.EndpointsConfig {
if v == nil {
return fmt.Errorf("no EndpointSettings for %s", k)
}
if v.IPAMConfig != nil {
if v.IPAMConfig.IPV4Address != "" && net.ParseIP(v.IPAMConfig.IPV4Address).To4() == nil {
return fmt.Errorf("invalid IPv4 address: %s", v.IPAMConfig.IPV4Address)
}
// TODO: check IPv6Address
}
}

return nil
}
158 changes: 155 additions & 3 deletions apis/opts/networks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,68 @@ func TestParseNetworks(t *testing.T) {
args args
want *types.NetworkingConfig
want1 string
err error
wantErr bool
}{
// TODO: Add test cases.
{
name: "networks is null then return 'bridge' mode",
args: args{
networks: []string{},
},
want: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
},
want1: "bridge",
wantErr: false,
},
{
name: "invalid network: cannot be empty",
args: args{
networks: []string{""},
},
err: fmt.Errorf("invalid network: cannot be empty"),
wantErr: true,
},
{
name: "if networkMode is null or mode is 'mode' then return name as mode",
args: args{
networks: []string{"foo:bar:mode"},
},
want: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
},
want1: "foo",
wantErr: false,
},
{
name: "if name is 'container' then return name and parameter as mode",
args: args{
networks: []string{"container:e8e153651a0d:mode"},
},
want: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
},
want1: "container:e8e153651a0d",
wantErr: false,
},
{
name: "name is not 'container'",
args: args{
networks: []string{"foo:127.0.0.1"},
},
want: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{
"foo": {
IPAddress: "127.0.0.1",
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: "127.0.0.1",
},
},
},
},
want1: "foo",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -35,6 +94,9 @@ func TestParseNetworks(t *testing.T) {
if got1 != tt.want1 {
t.Errorf("ParseNetworks() got1 = %v, want %v", got1, tt.want1)
}
if (err != nil) && !reflect.DeepEqual(err, tt.err) {
t.Errorf("ParseNetworks() = %v, want %v", err, tt.err)
}
})
}
}
Expand All @@ -46,15 +108,105 @@ func TestVerifyNetworks(t *testing.T) {
tests := []struct {
name string
args args
err error
wantErr bool
}{
// TODO: Add test cases.
{
name: "return expected nil 1",
args: args{
nwConfig: &types.NetworkingConfig{},
},
wantErr: false,
},
{
name: "return expected nil 2",
args: args{
nwConfig: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
},
},
wantErr: false,
},
{
name: "test IPAMConfig.IPV4Address",
args: args{
nwConfig: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{
"Networks": {
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: "127.0.0.1",
},
},
},
},
},
wantErr: false,
},
{
name: "test IPAddress, Gateway, IPV4Address and IPV6Address",
args: args{
nwConfig: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{
"Networks": {
Links: []string{},
Aliases: []string{},
EndpointID: "",
NetworkID: "",
MacAddress: "",
IPAddress: "127.0.0.1",
Gateway: "192.168.1.1",
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: "192.168.1.1",
IPV6Address: "2001:0db8:85a3:08d3:1319:8a2e:0370:1234",
LinkLocalIps: []string{
"1.2.3.4",
},
},
},
},
},
},
wantErr: false,
},
{
name: "container cannot be connected to network endpoints",
args: args{
nwConfig: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{
"foo": {},
"bar": {},
},
},
},
wantErr: true,
err: fmt.Errorf("Container cannot be connected to network endpoints: bar, foo"),
},
{
name: "invalid IPv4 address",
args: args{
nwConfig: &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{
"foo": {
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: "foo.bar",
},
},
},
},
},
wantErr: true,
err: fmt.Errorf("invalid IPv4 address: foo.bar"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ValidateNetworks(tt.args.nwConfig); (err != nil) != tt.wantErr {
err := ValidateNetworks(tt.args.nwConfig)
if (err != nil) != tt.wantErr {
t.Errorf("VerifyNetworks() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr && !reflect.DeepEqual(err, tt.err) {
t.Errorf("ParseNetworks() = %v, want %v", err, tt.err)
}
})
}
}
Expand Down

0 comments on commit 5013265

Please sign in to comment.