go.ligato.io/vpp-agent/v3@v3.5.0/tests/e2e/e2etest/etcd.go (about)

     1  //  Copyright (c) 2020 Cisco and/or its affiliates.
     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 e2etest
    16  
    17  import (
    18  	"path/filepath"
    19  
    20  	docker "github.com/fsouza/go-dockerclient"
    21  	"github.com/go-errors/errors"
    22  )
    23  
    24  const (
    25  	etcdImage       = "gcr.io/etcd-development/etcd:v3.5.5"
    26  	etcdStopTimeout = 1 // seconds
    27  )
    28  
    29  // Etcd is represents running ETCD
    30  type Etcd struct {
    31  	ComponentRuntime
    32  	ctx *TestCtx
    33  }
    34  
    35  // NewEtcd creates and starts new ETCD container
    36  func NewEtcd(ctx *TestCtx, optMods ...EtcdOptModifier) (*Etcd, error) {
    37  	// compute options
    38  	opts := DefaultEtcdOpt(ctx)
    39  	for _, mod := range optMods {
    40  		mod(opts)
    41  	}
    42  
    43  	// create struct for ETCD server
    44  	etcd := &Etcd{
    45  		ComponentRuntime: opts.Runtime,
    46  		ctx:              ctx,
    47  	}
    48  
    49  	// get runtime specific options and start ETCD in runtime environment
    50  	startOpts, err := opts.RuntimeStartOptions(ctx, opts)
    51  	if err != nil {
    52  		return nil, errors.Errorf("can't get ETCD start option for runtime due to: %v", err)
    53  	}
    54  	err = etcd.Start(startOpts)
    55  	if err != nil {
    56  		return nil, errors.Errorf("can't start ETCD due to: %v", err)
    57  	}
    58  	return etcd, nil
    59  }
    60  
    61  // Put inserts key-value pair into the ETCD inside its running docker container
    62  func (ec *Etcd) Put(key string, value string) error {
    63  	_, _, err := ec.ExecCmd("etcdctl", "put", key, value)
    64  	return err
    65  }
    66  
    67  // Get retrieves value for the key from the ETCD that is running in its docker container
    68  func (ec *Etcd) Get(key string) (string, error) {
    69  	stdout, _, err := ec.ExecCmd("etcdctl", "get", key)
    70  	return stdout, err
    71  }
    72  
    73  // GetAll retrieves all key-value pairs from the ETCD that is running in its docker container
    74  func (ec *Etcd) GetAll() (string, error) {
    75  	stdout, _, err := ec.ExecCmd("etcdctl", "get", "", "--prefix=true")
    76  	return stdout, err
    77  }
    78  
    79  // ETCDStartOptionsForContainerRuntime translates EtcdOpt to options for ComponentRuntime.Start(option)
    80  // method implemented by ContainerRuntime
    81  func ETCDStartOptionsForContainerRuntime(ctx *TestCtx, options interface{}) (interface{}, error) {
    82  	opts, ok := options.(*EtcdOpt)
    83  	if !ok {
    84  		return nil, errors.Errorf("expected EtcdOpt but got %+v", options)
    85  	}
    86  
    87  	// construct command string and container host config
    88  	cmd := []string{
    89  		"/usr/local/bin/etcd",
    90  	}
    91  	hostConfig := &docker.HostConfig{}
    92  	if opts.UseHTTPS {
    93  		cmd = append(cmd,
    94  			"--client-cert-auth",
    95  			"--trusted-ca-file=/etc/certs/ca.pem",
    96  			"--cert-file=/etc/certs/cert1.pem",
    97  			"--key-file=/etc/certs/cert1-key.pem",
    98  			"--advertise-client-urls=https://127.0.0.1:2379",
    99  			"--listen-client-urls=https://127.0.0.1:2379",
   100  		)
   101  		hostConfig.Binds = []string{filepath.Join(ctx.DataDir, "certs") + ":/etc/certs:ro"}
   102  	} else { // HTTP connection
   103  		cmd = append(cmd,
   104  			"--advertise-client-urls=http://0.0.0.0:2379",
   105  			"--listen-client-urls=http://0.0.0.0:2379",
   106  		)
   107  	}
   108  	if opts.UseTestContainerForNetworking {
   109  		hostConfig.NetworkMode = "container:vpp-agent-e2e-test"
   110  	} else { // separate container networking (default)
   111  		hostConfig.PortBindings = map[docker.Port][]docker.PortBinding{
   112  			"2379/tcp": {{HostIP: "0.0.0.0", HostPort: "2379"}},
   113  		}
   114  	}
   115  	containerOptions := &docker.CreateContainerOptions{
   116  		Name: "e2e-test-etcd",
   117  		Config: &docker.Config{
   118  			Env:   []string{"ETCDCTL_API=3"},
   119  			Image: etcdImage,
   120  			Cmd:   cmd,
   121  		},
   122  		HostConfig: hostConfig,
   123  	}
   124  
   125  	return &ContainerStartOptions{
   126  		ContainerOptions: containerOptions,
   127  		Pull:             true,
   128  	}, nil
   129  }