github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/container_run_network_windows_test.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "regexp" 22 "strings" 23 "testing" 24 25 "github.com/Microsoft/hcsshim" 26 "github.com/containerd/nerdctl/pkg/defaults" 27 "github.com/containerd/nerdctl/pkg/netutil" 28 "github.com/containerd/nerdctl/pkg/testutil" 29 "gotest.tools/v3/assert" 30 ) 31 32 // TestRunInternetConnectivity tests Internet connectivity by pinging github.com. 33 func TestRunInternetConnectivity(t *testing.T) { 34 base := testutil.NewBase(t) 35 36 type testCase struct { 37 args []string 38 } 39 testCases := []testCase{ 40 { 41 args: []string{"--net", "nat"}, 42 }, 43 } 44 for _, tc := range testCases { 45 tc := tc // IMPORTANT 46 name := "default" 47 if len(tc.args) > 0 { 48 name = strings.Join(tc.args, "_") 49 } 50 t.Run(name, func(t *testing.T) { 51 args := []string{"run", "--rm"} 52 args = append(args, tc.args...) 53 // TODO(aznashwan): smarter way to ensure internet connectivity is working. 54 // ping doesn't seem to work on GitHub Actions ("Request timed out.") 55 args = append(args, testutil.CommonImage, "curl.exe -sSL https://github.com") 56 cmd := base.Cmd(args...) 57 cmd.AssertOutContains("<!DOCTYPE html>") 58 }) 59 } 60 } 61 62 func TestRunPort(t *testing.T) { 63 // NOTE: currently no isolation between the loopback and host namespaces on Windows. 64 baseTestRunPort(t, testutil.NginxAlpineImage, testutil.NginxAlpineIndexHTMLSnippet, false) 65 } 66 67 // Checks whether an HNS endpoint with a name matching exists. 68 func listHnsEndpointsRegex(hnsEndpointNameRegex string) ([]hcsshim.HNSEndpoint, error) { 69 r, err := regexp.Compile(hnsEndpointNameRegex) 70 if err != nil { 71 return nil, err 72 } 73 hnsEndpoints, err := hcsshim.HNSListEndpointRequest() 74 if err != nil { 75 return nil, fmt.Errorf("failed to list HNS endpoints for request: %s", err) 76 } 77 78 res := []hcsshim.HNSEndpoint{} 79 for _, endp := range hnsEndpoints { 80 if r.Match([]byte(endp.Name)) { 81 res = append(res, endp) 82 } 83 } 84 return res, nil 85 } 86 87 // Asserts whether the container with the provided has any HNS endpoints with the expected 88 // naming format (`${container_id}_${network_name}`) for all of the provided network names. 89 // The container ID can be a regex. 90 func assertHnsEndpointsExistence(t *testing.T, shouldExist bool, containerIDRegex string, networkNames ...string) { 91 for _, netName := range networkNames { 92 endpointName := fmt.Sprintf("%s_%s", containerIDRegex, netName) 93 94 testName := fmt.Sprintf("hns_endpoint_%s_shouldExist_%t", endpointName, shouldExist) 95 t.Run(testName, func(t *testing.T) { 96 matchingEndpoints, err := listHnsEndpointsRegex(endpointName) 97 assert.NilError(t, err) 98 if shouldExist { 99 assert.Equal(t, len(matchingEndpoints), 1) 100 assert.Equal(t, matchingEndpoints[0].Name, endpointName) 101 } else { 102 assert.Equal(t, len(matchingEndpoints), 0) 103 } 104 }) 105 } 106 } 107 108 // Tests whether HNS endpoints are properly created and managed throughout the lifecycle of a container. 109 func TestHnsEndpointsExistDuringContainerLifecycle(t *testing.T) { 110 base := testutil.NewBase(t) 111 112 testNet, err := getTestingNetwork() 113 assert.NilError(t, err) 114 115 tID := testutil.Identifier(t) 116 defer base.Cmd("rm", "-f", tID).Run() 117 cmd := base.Cmd( 118 "create", 119 "--name", tID, 120 "--net", testNet.Name, 121 testutil.CommonImage, 122 "bash", "-c", 123 // NOTE: the BusyBox image used in Windows testing's `sleep` binary 124 // does not support the `infinity` argument. 125 "tail", "-f", 126 ) 127 t.Logf("Creating HNS lifecycle test container with command: %q", strings.Join(cmd.Command, " ")) 128 containerId := strings.TrimSpace(cmd.Run().Stdout()) 129 t.Logf("HNS endpoint lifecycle test container ID: %q", containerId) 130 131 // HNS endpoints should be allocated on container creation. 132 assertHnsEndpointsExistence(t, true, containerId, testNet.Name) 133 134 // Starting and stopping the container should NOT affect/change the endpoints. 135 base.Cmd("start", containerId).AssertOK() 136 assertHnsEndpointsExistence(t, true, containerId, testNet.Name) 137 138 base.Cmd("stop", containerId).AssertOK() 139 assertHnsEndpointsExistence(t, true, containerId, testNet.Name) 140 141 // Removing the container should remove the HNS endpoints. 142 base.Cmd("rm", containerId).AssertOK() 143 assertHnsEndpointsExistence(t, false, containerId, testNet.Name) 144 } 145 146 // Returns a network to be used for testing. 147 // Note: currently hardcoded to return the default network, as `network create` 148 // does not work on Windows. 149 func getTestingNetwork() (*netutil.NetworkConfig, error) { 150 // NOTE: cannot currently `nerdctl network create` on Windows so we use a pre-existing network: 151 cniEnv, err := netutil.NewCNIEnv(defaults.CNIPath(), defaults.CNINetConfPath()) 152 if err != nil { 153 return nil, err 154 } 155 156 return cniEnv.GetDefaultNetworkConfig() 157 } 158 159 // Tests whether HNS endpoints are properly removed when running `run --rm`. 160 func TestHnsEndpointsRemovedAfterAttachedRun(t *testing.T) { 161 base := testutil.NewBase(t) 162 163 testNet, err := getTestingNetwork() 164 assert.NilError(t, err) 165 166 // NOTE: because we cannot set/obtain the ID of the container to check for the exact HNS 167 // endpoint name, we record the number of HNS endpoints on the testing network and 168 // ensure it remains constant until after the test. 169 existingEndpoints, err := listHnsEndpointsRegex(fmt.Sprintf(".*_%s", testNet.Name)) 170 assert.NilError(t, err) 171 originalEndpointsCount := len(existingEndpoints) 172 173 tID := testutil.Identifier(t) 174 base.Cmd( 175 "run", 176 "--name", 177 tID, 178 "--rm", 179 "--net", testNet.Name, 180 testutil.CommonImage, 181 "ipconfig", "/all", 182 ).AssertOK() 183 184 existingEndpoints, err = listHnsEndpointsRegex(fmt.Sprintf(".*_%s", testNet.Name)) 185 assert.NilError(t, err) 186 assert.Equal(t, originalEndpointsCount, len(existingEndpoints), "the number of HNS endpoints should equal pre-test amount") 187 }