github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/proxyupdater/proxyupdater_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package proxyupdater_test
     5  
     6  import (
     7  	"io/ioutil"
     8  	"os"
     9  	"path"
    10  	"runtime"
    11  	"strings"
    12  	"time"
    13  
    14  	jc "github.com/juju/testing/checkers"
    15  	"github.com/juju/utils/packaging/commands"
    16  	pacconfig "github.com/juju/utils/packaging/config"
    17  	"github.com/juju/utils/proxy"
    18  	proxyutils "github.com/juju/utils/proxy"
    19  	"github.com/juju/utils/series"
    20  	gc "gopkg.in/check.v1"
    21  
    22  	coretesting "github.com/juju/juju/testing"
    23  	"github.com/juju/juju/watcher"
    24  	"github.com/juju/juju/worker"
    25  	"github.com/juju/juju/worker/proxyupdater"
    26  	"github.com/juju/juju/worker/workertest"
    27  )
    28  
    29  type ProxyUpdaterSuite struct {
    30  	coretesting.BaseSuite
    31  
    32  	api              *fakeAPI
    33  	proxyFile        string
    34  	detectedSettings proxy.Settings
    35  	config           proxyupdater.Config
    36  }
    37  
    38  var _ = gc.Suite(&ProxyUpdaterSuite{})
    39  
    40  func newNotAWatcher() notAWatcher {
    41  	return notAWatcher{workertest.NewFakeWatcher(2, 2)}
    42  }
    43  
    44  type notAWatcher struct {
    45  	workertest.NotAWatcher
    46  }
    47  
    48  func (w notAWatcher) Changes() watcher.NotifyChannel {
    49  	return w.NotAWatcher.Changes()
    50  }
    51  
    52  type fakeAPI struct {
    53  	Proxy    proxyutils.Settings
    54  	APTProxy proxyutils.Settings
    55  	Err      error
    56  	Watcher  *notAWatcher
    57  }
    58  
    59  func NewFakeAPI() *fakeAPI {
    60  	f := &fakeAPI{}
    61  	return f
    62  }
    63  
    64  func (api fakeAPI) ProxyConfig() (proxyutils.Settings, proxyutils.Settings, error) {
    65  	return api.Proxy, api.APTProxy, api.Err
    66  
    67  }
    68  
    69  func (api fakeAPI) WatchForProxyConfigAndAPIHostPortChanges() (watcher.NotifyWatcher, error) {
    70  	if api.Watcher == nil {
    71  		w := newNotAWatcher()
    72  		api.Watcher = &w
    73  	}
    74  	return api.Watcher, nil
    75  }
    76  
    77  func (s *ProxyUpdaterSuite) SetUpTest(c *gc.C) {
    78  	s.BaseSuite.SetUpTest(c)
    79  	s.api = NewFakeAPI()
    80  
    81  	s.config = proxyupdater.Config{
    82  		Directory: c.MkDir(),
    83  		Filename:  "juju-proxy-settings",
    84  		API:       s.api,
    85  	}
    86  	s.PatchValue(&pacconfig.AptProxyConfigFile, path.Join(s.config.Directory, "juju-apt-proxy"))
    87  	s.proxyFile = path.Join(s.config.Directory, s.config.Filename)
    88  }
    89  
    90  func (s *ProxyUpdaterSuite) TearDownTest(c *gc.C) {
    91  	s.BaseSuite.TearDownTest(c)
    92  	if s.api.Watcher != nil {
    93  		s.api.Watcher.Close()
    94  	}
    95  }
    96  
    97  func (s *ProxyUpdaterSuite) waitProxySettings(c *gc.C, expected proxy.Settings) {
    98  	maxWait := time.After(coretesting.LongWait)
    99  	for {
   100  		select {
   101  		case <-maxWait:
   102  			c.Fatalf("timeout while waiting for proxy settings to change")
   103  			return
   104  		case <-time.After(10 * time.Millisecond):
   105  			obtained := proxy.DetectProxies()
   106  			if obtained != expected {
   107  				if obtained != s.detectedSettings {
   108  					c.Logf("proxy settings are \n%#v, should be \n%#v, still waiting", obtained, expected)
   109  				}
   110  				s.detectedSettings = obtained
   111  				continue
   112  			}
   113  			return
   114  		}
   115  	}
   116  }
   117  
   118  func (s *ProxyUpdaterSuite) waitForFile(c *gc.C, filename, expected string) {
   119  	//TODO(bogdanteleaga): Find a way to test this on windows
   120  	if runtime.GOOS == "windows" {
   121  		c.Skip("Proxy settings are written to the registry on windows")
   122  	}
   123  	maxWait := time.After(coretesting.LongWait)
   124  	for {
   125  		select {
   126  		case <-maxWait:
   127  			c.Fatalf("timeout while waiting for proxy settings to change")
   128  			return
   129  		case <-time.After(10 * time.Millisecond):
   130  			fileContent, err := ioutil.ReadFile(filename)
   131  			if os.IsNotExist(err) {
   132  				continue
   133  			}
   134  			c.Assert(err, jc.ErrorIsNil)
   135  			if string(fileContent) != expected {
   136  				c.Logf("file content not matching, still waiting")
   137  				continue
   138  			}
   139  			return
   140  		}
   141  	}
   142  }
   143  
   144  func (s *ProxyUpdaterSuite) TestRunStop(c *gc.C) {
   145  	updater, err := proxyupdater.NewWorker(s.config)
   146  	c.Assert(err, jc.ErrorIsNil)
   147  	workertest.CleanKill(c, updater)
   148  }
   149  
   150  func (s *ProxyUpdaterSuite) updateConfig(c *gc.C) (proxy.Settings, proxy.Settings) {
   151  	s.api.Proxy = proxy.Settings{
   152  		Http:    "http proxy",
   153  		Https:   "https proxy",
   154  		Ftp:     "ftp proxy",
   155  		NoProxy: "localhost,no proxy",
   156  	}
   157  
   158  	s.api.APTProxy = proxy.Settings{
   159  		Http:  "http://apt.http.proxy",
   160  		Https: "https://apt.https.proxy",
   161  		Ftp:   "ftp://apt.ftp.proxy",
   162  	}
   163  
   164  	return s.api.Proxy, s.api.APTProxy
   165  }
   166  
   167  func (s *ProxyUpdaterSuite) TestInitialState(c *gc.C) {
   168  	proxySettings, aptProxySettings := s.updateConfig(c)
   169  
   170  	updater, err := proxyupdater.NewWorker(s.config)
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	defer worker.Stop(updater)
   173  
   174  	s.waitProxySettings(c, proxySettings)
   175  	s.waitForFile(c, s.proxyFile, proxySettings.AsScriptEnvironment()+"\n")
   176  
   177  	paccmder, err := commands.NewPackageCommander(series.HostSeries())
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	s.waitForFile(c, pacconfig.AptProxyConfigFile, paccmder.ProxyConfigContents(aptProxySettings)+"\n")
   180  }
   181  
   182  func (s *ProxyUpdaterSuite) TestWriteSystemFiles(c *gc.C) {
   183  	proxySettings, aptProxySettings := s.updateConfig(c)
   184  
   185  	updater, err := proxyupdater.NewWorker(s.config)
   186  	c.Assert(err, jc.ErrorIsNil)
   187  	defer worker.Stop(updater)
   188  
   189  	s.waitProxySettings(c, proxySettings)
   190  	s.waitForFile(c, s.proxyFile, proxySettings.AsScriptEnvironment()+"\n")
   191  
   192  	paccmder, err := commands.NewPackageCommander(series.HostSeries())
   193  	c.Assert(err, jc.ErrorIsNil)
   194  	s.waitForFile(c, pacconfig.AptProxyConfigFile, paccmder.ProxyConfigContents(aptProxySettings)+"\n")
   195  }
   196  
   197  func (s *ProxyUpdaterSuite) TestEnvironmentVariables(c *gc.C) {
   198  	setenv := func(proxy, value string) {
   199  		os.Setenv(proxy, value)
   200  		os.Setenv(strings.ToUpper(proxy), value)
   201  	}
   202  	setenv("http_proxy", "foo")
   203  	setenv("https_proxy", "foo")
   204  	setenv("ftp_proxy", "foo")
   205  	setenv("no_proxy", "foo")
   206  
   207  	proxySettings, _ := s.updateConfig(c)
   208  	updater, err := proxyupdater.NewWorker(s.config)
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	defer worker.Stop(updater)
   211  	s.waitProxySettings(c, proxySettings)
   212  
   213  	assertEnv := func(proxy, value string) {
   214  		c.Assert(os.Getenv(proxy), gc.Equals, value)
   215  		c.Assert(os.Getenv(strings.ToUpper(proxy)), gc.Equals, value)
   216  	}
   217  	assertEnv("http_proxy", proxySettings.Http)
   218  	assertEnv("https_proxy", proxySettings.Https)
   219  	assertEnv("ftp_proxy", proxySettings.Ftp)
   220  	assertEnv("no_proxy", proxySettings.NoProxy)
   221  }
   222  
   223  func (s *ProxyUpdaterSuite) TestExternalFuncCalled(c *gc.C) {
   224  	proxySettings, _ := s.updateConfig(c)
   225  
   226  	var externalSettings proxy.Settings
   227  	updated := make(chan struct{})
   228  	s.config.ExternalUpdate = func(values proxy.Settings) error {
   229  		externalSettings = values
   230  		close(updated)
   231  		return nil
   232  	}
   233  	updater, err := proxyupdater.NewWorker(s.config)
   234  	c.Assert(err, jc.ErrorIsNil)
   235  	defer worker.Stop(updater)
   236  
   237  	select {
   238  	case <-time.After(time.Second):
   239  		c.Fatal("function not called")
   240  	case <-updated:
   241  	}
   242  
   243  	c.Assert(externalSettings, jc.DeepEquals, proxySettings)
   244  }