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  }