github.com/imran-kn/cilium-fork@v1.6.9/pkg/envoy/envoy_test.go (about)

     1  // Copyright 2018 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  // +build !privileged_tests
    16  
    17  package envoy
    18  
    19  import (
    20  	"context"
    21  	"io/ioutil"
    22  	"net"
    23  	"os"
    24  	"path/filepath"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/cilium/cilium/pkg/checker"
    29  	"github.com/cilium/cilium/pkg/completion"
    30  	"github.com/cilium/cilium/pkg/envoy/xds"
    31  	"github.com/cilium/cilium/pkg/flowdebug"
    32  	"github.com/cilium/cilium/pkg/identity"
    33  	"github.com/cilium/cilium/pkg/option"
    34  	"github.com/cilium/cilium/pkg/policy"
    35  	"github.com/cilium/cilium/pkg/proxy/accesslog"
    36  
    37  	. "gopkg.in/check.v1"
    38  )
    39  
    40  // Hook up gocheck into the "go test" runner.
    41  func Test(t *testing.T) { TestingT(t) }
    42  
    43  type EnvoySuite struct {
    44  	waitGroup *completion.WaitGroup
    45  }
    46  
    47  var _ = Suite(&EnvoySuite{})
    48  
    49  func (s *EnvoySuite) waitForProxyCompletion() error {
    50  	start := time.Now()
    51  	log.Debug("Waiting for proxy updates to complete...")
    52  	err := s.waitGroup.Wait()
    53  	log.Debug("Wait time for proxy updates: ", time.Since(start))
    54  	return err
    55  }
    56  
    57  type dummyEndpointInfoRegistry struct{}
    58  
    59  func (r *dummyEndpointInfoRegistry) FillEndpointIdentityByID(id identity.NumericIdentity, info *accesslog.EndpointInfo) bool {
    60  	return false
    61  }
    62  
    63  func (r *dummyEndpointInfoRegistry) FillEndpointIdentityByIP(ip net.IP, info *accesslog.EndpointInfo) bool {
    64  	return false
    65  }
    66  
    67  func (s *EnvoySuite) TestEnvoy(c *C) {
    68  	option.Config.Populate()
    69  	option.Config.ProxyConnectTimeout = 1
    70  	c.Assert(option.Config.ProxyConnectTimeout, Not(Equals), 0)
    71  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    72  	defer cancel()
    73  
    74  	s.waitGroup = completion.NewWaitGroup(ctx)
    75  
    76  	if os.Getenv("CILIUM_ENABLE_ENVOY_UNIT_TEST") == "" {
    77  		c.Skip("skipping envoy unit test; CILIUM_ENABLE_ENVOY_UNIT_TEST not set")
    78  	}
    79  
    80  	flowdebug.Enable()
    81  
    82  	stateLogDir, err := ioutil.TempDir("", "envoy_go_test")
    83  	c.Assert(err, IsNil)
    84  
    85  	log.Debugf("state log directory: %s", stateLogDir)
    86  
    87  	xdsServer := StartXDSServer(stateLogDir)
    88  	defer xdsServer.stop()
    89  	StartAccessLogServer(stateLogDir, xdsServer, &dummyEndpointInfoRegistry{})
    90  
    91  	// launch debug variant of the Envoy proxy
    92  	envoyProxy := StartEnvoy(stateLogDir, filepath.Join(stateLogDir, "cilium-envoy.log"), 42)
    93  	c.Assert(envoyProxy, NotNil)
    94  	log.Debug("started Envoy")
    95  
    96  	log.Debug("adding listener1")
    97  	xdsServer.AddListener("listener1", policy.ParserTypeHTTP, 8081, true, false, s.waitGroup)
    98  
    99  	log.Debug("adding listener2")
   100  	xdsServer.AddListener("listener2", policy.ParserTypeHTTP, 8082, true, false, s.waitGroup)
   101  
   102  	log.Debug("adding listener3")
   103  	xdsServer.AddListener("listener3", policy.ParserTypeHTTP, 8083, false, false, s.waitGroup)
   104  
   105  	err = s.waitForProxyCompletion()
   106  	c.Assert(err, IsNil)
   107  	log.Debug("completed adding listener1, listener2, listener3")
   108  	s.waitGroup = completion.NewWaitGroup(ctx)
   109  
   110  	// Remove listener3
   111  	log.Debug("removing listener 3")
   112  	xdsServer.RemoveListener("listener3", s.waitGroup)
   113  
   114  	err = s.waitForProxyCompletion()
   115  	c.Assert(err, IsNil)
   116  	log.Debug("completed removing listener 3")
   117  	s.waitGroup = completion.NewWaitGroup(ctx)
   118  
   119  	// Add listener3 again
   120  	log.Debug("adding listener 3")
   121  	xdsServer.AddListener("listener3", policy.L7ParserType("test.headerparser"), 8083, false, false, s.waitGroup)
   122  
   123  	err = s.waitForProxyCompletion()
   124  	c.Assert(err, IsNil)
   125  	log.Debug("completed adding listener 3")
   126  	s.waitGroup = completion.NewWaitGroup(ctx)
   127  
   128  	log.Debug("stopping Envoy")
   129  	err = envoyProxy.StopEnvoy()
   130  	c.Assert(err, IsNil)
   131  
   132  	time.Sleep(2 * time.Second) // Wait for Envoy to really terminate.
   133  
   134  	// Remove listener3 again, and wait for timeout after stopping Envoy.
   135  	log.Debug("removing listener 3")
   136  	xdsServer.RemoveListener("listener3", s.waitGroup)
   137  	err = s.waitForProxyCompletion()
   138  	c.Assert(err, NotNil)
   139  	log.Debugf("failed to remove listener 3: %s", err)
   140  }
   141  
   142  func (s *EnvoySuite) TestEnvoyNACK(c *C) {
   143  	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Second)
   144  	defer cancel()
   145  
   146  	s.waitGroup = completion.NewWaitGroup(ctx)
   147  
   148  	if os.Getenv("CILIUM_ENABLE_ENVOY_UNIT_TEST") == "" {
   149  		c.Skip("skipping envoy unit test; CILIUM_ENABLE_ENVOY_UNIT_TEST not set")
   150  	}
   151  
   152  	flowdebug.Enable()
   153  
   154  	stateLogDir, err := ioutil.TempDir("", "envoy_go_test")
   155  	c.Assert(err, IsNil)
   156  
   157  	log.Debugf("state log directory: %s", stateLogDir)
   158  
   159  	xdsServer := StartXDSServer(stateLogDir)
   160  	defer xdsServer.stop()
   161  	StartAccessLogServer(stateLogDir, xdsServer, &dummyEndpointInfoRegistry{})
   162  
   163  	// launch debug variant of the Envoy proxy
   164  	envoyProxy := StartEnvoy(stateLogDir, filepath.Join(stateLogDir, "cilium-envoy.log"), 42)
   165  	c.Assert(envoyProxy, NotNil)
   166  	log.Debug("started Envoy")
   167  
   168  	rName := "listener:22"
   169  
   170  	log.Debug("adding ", rName)
   171  	xdsServer.AddListener(rName, policy.ParserTypeHTTP, 22, true, false, s.waitGroup)
   172  
   173  	err = s.waitForProxyCompletion()
   174  	c.Assert(err, Not(IsNil))
   175  	c.Assert(err, checker.DeepEquals, &xds.ProxyError{Err: xds.ErrNackReceived, Detail: "Error adding/updating listener(s) listener:22: cannot bind '[::]:22': Address already in use"})
   176  
   177  	s.waitGroup = completion.NewWaitGroup(ctx)
   178  	// Remove listener1
   179  	log.Debug("removing ", rName)
   180  	xdsServer.RemoveListener(rName, s.waitGroup)
   181  	err = s.waitForProxyCompletion()
   182  	c.Assert(err, IsNil)
   183  }