github.phpd.cn/cilium/cilium@v1.6.12/test/helpers/docker.go (about) 1 // Copyright 2017 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package helpers 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/cilium/cilium/test/helpers/constants" 22 "github.com/onsi/ginkgo" 23 ) 24 25 // ContainerExec executes cmd in the container with the provided name along with 26 // any other additional arguments needed. 27 func (s *SSHMeta) ContainerExec(name string, cmd string, optionalArgs ...string) *CmdRes { 28 optionalArgsCoalesced := "" 29 if len(optionalArgs) > 0 { 30 optionalArgsCoalesced = strings.Join(optionalArgs, " ") 31 } 32 dockerCmd := fmt.Sprintf("docker exec -i %s %s %s", optionalArgsCoalesced, name, cmd) 33 return s.Exec(dockerCmd) 34 } 35 36 // ContainerRun is a wrapper to a one execution docker run container. It runs 37 // an instance of the specific Docker image with the provided network, name and 38 // options. 39 func (s *SSHMeta) ContainerRun(name, image, net, options string, cmdParams ...string) *CmdRes { 40 cmdOnStart := "" 41 if len(cmdParams) > 0 { 42 cmdOnStart = strings.Join(cmdParams, " ") 43 } 44 cmd := fmt.Sprintf( 45 "docker run --name %s --net %s %s %s %s", name, net, options, image, cmdOnStart) 46 return s.ExecWithSudo(cmd) 47 } 48 49 // ContainerCreate is a wrapper for `docker run`. It runs an instance of the 50 // specified Docker image with the provided network, name, options and container 51 // startup commands. 52 func (s *SSHMeta) ContainerCreate(name, image, net, options string, cmdParams ...string) *CmdRes { 53 cmdOnStart := "" 54 if len(cmdParams) > 0 { 55 cmdOnStart = strings.Join(cmdParams, " ") 56 } 57 if _, ok := constants.AllImages[image]; !ok { 58 ginkgo.Fail(fmt.Sprintf("Image %s is not in the set of pre-pulled Docker images; add this image to `AllImages` in `test/helpers/constants/images.go` and / or update the VM image to pull this image if necessary", image), 1) 59 } 60 61 cmd := fmt.Sprintf( 62 "docker run -d --name %s --net %s %s %s %s", name, net, options, image, cmdOnStart) 63 log.Debugf("spinning up container with command '%v'", cmd) 64 return s.ExecWithSudo(cmd) 65 } 66 67 // ContainerRm is a wrapper around `docker rm -f`. It forcibly removes the 68 // Docker container of the provided name. 69 func (s *SSHMeta) ContainerRm(name string) *CmdRes { 70 cmd := fmt.Sprintf("docker rm -f %s", name) 71 return s.ExecWithSudo(cmd) 72 } 73 74 // ContainerInspect runs `docker inspect` for the container with the provided 75 // name. 76 func (s *SSHMeta) ContainerInspect(name string) *CmdRes { 77 return s.ExecWithSudo(fmt.Sprintf("docker inspect %s", name)) 78 } 79 80 // ContainerInspectNet returns a map of Docker networking information fields and 81 // their associated values for the container of the provided name. An error 82 // is returned if the networking information could not be retrieved. 83 func (s *SSHMeta) ContainerInspectNet(name string) (map[string]string, error) { 84 res := s.ContainerInspect(name) 85 properties := map[string]string{ 86 "EndpointID": "EndpointID", 87 "GlobalIPv6Address": IPv6, 88 "IPAddress": IPv4, 89 "NetworkID": "NetworkID", 90 "IPv6Gateway": "IPv6Gateway", 91 } 92 93 if !res.WasSuccessful() { 94 return nil, fmt.Errorf("could not inspect container %s", name) 95 } 96 filter := fmt.Sprintf(`{ [0].NetworkSettings.Networks.%s }`, CiliumDockerNetwork) 97 result := map[string]string{ 98 Name: name, 99 } 100 data, err := res.FindResults(filter) 101 if err != nil { 102 return nil, err 103 } 104 for _, val := range data { 105 iface := val.Interface() 106 for k, v := range iface.(map[string]interface{}) { 107 if key, ok := properties[k]; ok { 108 result[key] = fmt.Sprintf("%s", v) 109 } 110 } 111 } 112 return result, nil 113 } 114 115 // NetworkCreate creates a Docker network of the provided name with the 116 // specified subnet. It is a wrapper around `docker network create`. 117 func (s *SSHMeta) NetworkCreate(name string, subnet string) *CmdRes { 118 if subnet == "" { 119 subnet = "::1/112" 120 } 121 cmd := fmt.Sprintf( 122 "docker network create --ipv6 --subnet %s --driver cilium --ipam-driver cilium %s", 123 subnet, name) 124 res := s.ExecWithSudo(cmd) 125 if !res.WasSuccessful() { 126 s.logger.Warningf("Unable to create docker network %s: %s", name, res.CombineOutput().String()) 127 } 128 129 return res 130 } 131 132 // NetworkDelete deletes the Docker network of the provided name. It is a wrapper 133 // around `docker network rm`. 134 func (s *SSHMeta) NetworkDelete(name string) *CmdRes { 135 return s.ExecWithSudo(fmt.Sprintf("docker network rm %s", name)) 136 } 137 138 // NetworkGet returns all of the Docker network configuration for the provided 139 // network. It is a wrapper around `docker network inspect`. 140 func (s *SSHMeta) NetworkGet(name string) *CmdRes { 141 return s.ExecWithSudo(fmt.Sprintf("docker network inspect %s", name)) 142 } 143 144 func (s *SSHMeta) execCmd(cmd string) *CmdRes { 145 return s.ExecWithSudo(cmd) 146 } 147 148 // SampleContainersActions creates or deletes various containers used for 149 // testing Cilium and adds said containers to the provided Docker network. 150 func (s *SSHMeta) SampleContainersActions(mode string, networkName string, createOptions ...string) { 151 createOptionsString := "" 152 for _, opt := range createOptions { 153 createOptionsString = fmt.Sprintf("%s %s", createOptionsString, opt) 154 } 155 156 images := map[string]string{ 157 Httpd1: constants.HttpdImage, 158 Httpd2: constants.HttpdImage, 159 Httpd3: constants.HttpdImage, 160 App1: constants.NetperfImage, 161 App2: constants.NetperfImage, 162 App3: constants.NetperfImage, 163 } 164 165 switch mode { 166 case Create: 167 for k, v := range images { 168 s.ContainerCreate(k, v, networkName, fmt.Sprintf("-l id.%s %s", k, createOptionsString)) 169 } 170 s.WaitEndpointsReady() 171 case Delete: 172 for k := range images { 173 s.ContainerRm(k) 174 } 175 s.WaitEndpointsDeleted() 176 } 177 } 178 179 // GatherDockerLogs dumps docker containers logs output to the directory 180 // testResultsPath 181 func (s *SSHMeta) GatherDockerLogs() { 182 res := s.Exec("docker ps -a --format {{.Names}}") 183 if !res.WasSuccessful() { 184 log.WithField("error", res.CombineOutput()).Errorf("cannot get docker logs") 185 return 186 } 187 commands := map[string]string{} 188 for _, k := range res.ByLines() { 189 if k != "" { 190 key := fmt.Sprintf("docker logs %s", k) 191 commands[key] = fmt.Sprintf("container_%s.log", k) 192 } 193 } 194 195 testPath, err := CreateReportDirectory() 196 if err != nil { 197 s.logger.WithError(err).Errorf( 198 "cannot create test results path '%s'", testPath) 199 return 200 } 201 reportMap(testPath, commands, s) 202 }