github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/environ/environ_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package environ_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/worker.v1/workertest"
    13  
    14  	"github.com/juju/juju/environs"
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker/environ"
    17  )
    18  
    19  type TrackerSuite struct {
    20  	coretesting.BaseSuite
    21  }
    22  
    23  var _ = gc.Suite(&TrackerSuite{})
    24  
    25  func (s *TrackerSuite) TestValidateObserver(c *gc.C) {
    26  	config := environ.Config{}
    27  	s.testValidate(c, config, func(err error) {
    28  		c.Check(err, jc.Satisfies, errors.IsNotValid)
    29  		c.Check(err, gc.ErrorMatches, "nil Observer not valid")
    30  	})
    31  }
    32  
    33  func (s *TrackerSuite) TestValidateNewEnvironFunc(c *gc.C) {
    34  	config := environ.Config{
    35  		Observer: &runContext{},
    36  	}
    37  	s.testValidate(c, config, func(err error) {
    38  		c.Check(err, jc.Satisfies, errors.IsNotValid)
    39  		c.Check(err, gc.ErrorMatches, "nil NewEnvironFunc not valid")
    40  	})
    41  }
    42  
    43  func (s *TrackerSuite) testValidate(c *gc.C, config environ.Config, check func(err error)) {
    44  	err := config.Validate()
    45  	check(err)
    46  
    47  	tracker, err := environ.NewTracker(config)
    48  	c.Check(tracker, gc.IsNil)
    49  	check(err)
    50  }
    51  
    52  func (s *TrackerSuite) TestModelConfigFails(c *gc.C) {
    53  	fix := &fixture{
    54  		observerErrs: []error{
    55  			errors.New("no you"),
    56  		},
    57  	}
    58  	fix.Run(c, func(context *runContext) {
    59  		tracker, err := environ.NewTracker(environ.Config{
    60  			Observer:       context,
    61  			NewEnvironFunc: newMockEnviron,
    62  		})
    63  		c.Check(err, gc.ErrorMatches, "cannot create environ: no you")
    64  		c.Check(tracker, gc.IsNil)
    65  		context.CheckCallNames(c, "ModelConfig")
    66  	})
    67  }
    68  
    69  func (s *TrackerSuite) TestModelConfigInvalid(c *gc.C) {
    70  	fix := &fixture{}
    71  	fix.Run(c, func(context *runContext) {
    72  		tracker, err := environ.NewTracker(environ.Config{
    73  			Observer: context,
    74  			NewEnvironFunc: func(environs.OpenParams) (environs.Environ, error) {
    75  				return nil, errors.NotValidf("config")
    76  			},
    77  		})
    78  		c.Check(err, gc.ErrorMatches, `cannot create environ: config not valid`)
    79  		c.Check(tracker, gc.IsNil)
    80  		context.CheckCallNames(c, "ModelConfig", "CloudSpec")
    81  	})
    82  }
    83  
    84  func (s *TrackerSuite) TestModelConfigValid(c *gc.C) {
    85  	fix := &fixture{
    86  		initialConfig: coretesting.Attrs{
    87  			"name": "this-particular-name",
    88  		},
    89  	}
    90  	fix.Run(c, func(context *runContext) {
    91  		tracker, err := environ.NewTracker(environ.Config{
    92  			Observer:       context,
    93  			NewEnvironFunc: newMockEnviron,
    94  		})
    95  		c.Assert(err, jc.ErrorIsNil)
    96  		defer workertest.CleanKill(c, tracker)
    97  
    98  		gotEnviron := tracker.Environ()
    99  		c.Assert(gotEnviron, gc.NotNil)
   100  		c.Check(gotEnviron.Config().Name(), gc.Equals, "this-particular-name")
   101  	})
   102  }
   103  
   104  func (s *TrackerSuite) TestCloudSpec(c *gc.C) {
   105  	cloudSpec := environs.CloudSpec{
   106  		Name:   "foo",
   107  		Type:   "bar",
   108  		Region: "baz",
   109  	}
   110  	fix := &fixture{cloud: cloudSpec}
   111  	fix.Run(c, func(context *runContext) {
   112  		tracker, err := environ.NewTracker(environ.Config{
   113  			Observer: context,
   114  			NewEnvironFunc: func(args environs.OpenParams) (environs.Environ, error) {
   115  				c.Assert(args.Cloud, jc.DeepEquals, cloudSpec)
   116  				return nil, errors.NotValidf("cloud spec")
   117  			},
   118  		})
   119  		c.Check(err, gc.ErrorMatches, `cannot create environ: cloud spec not valid`)
   120  		c.Check(tracker, gc.IsNil)
   121  		context.CheckCallNames(c, "ModelConfig", "CloudSpec")
   122  	})
   123  }
   124  
   125  func (s *TrackerSuite) TestWatchFails(c *gc.C) {
   126  	fix := &fixture{
   127  		observerErrs: []error{
   128  			nil, nil, errors.New("grrk splat"),
   129  		},
   130  	}
   131  	fix.Run(c, func(context *runContext) {
   132  		tracker, err := environ.NewTracker(environ.Config{
   133  			Observer:       context,
   134  			NewEnvironFunc: newMockEnviron,
   135  		})
   136  		c.Assert(err, jc.ErrorIsNil)
   137  		defer workertest.DirtyKill(c, tracker)
   138  
   139  		err = workertest.CheckKilled(c, tracker)
   140  		c.Check(err, gc.ErrorMatches, "cannot watch environ config: grrk splat")
   141  		context.CheckCallNames(c, "ModelConfig", "CloudSpec", "WatchForModelConfigChanges")
   142  	})
   143  }
   144  
   145  func (s *TrackerSuite) TestWatchCloses(c *gc.C) {
   146  	fix := &fixture{}
   147  	fix.Run(c, func(context *runContext) {
   148  		tracker, err := environ.NewTracker(environ.Config{
   149  			Observer:       context,
   150  			NewEnvironFunc: newMockEnviron,
   151  		})
   152  		c.Assert(err, jc.ErrorIsNil)
   153  		defer workertest.DirtyKill(c, tracker)
   154  
   155  		context.CloseModelConfigNotify()
   156  		err = workertest.CheckKilled(c, tracker)
   157  		c.Check(err, gc.ErrorMatches, "environ config watch closed")
   158  		context.CheckCallNames(c, "ModelConfig", "CloudSpec", "WatchForModelConfigChanges")
   159  	})
   160  }
   161  
   162  func (s *TrackerSuite) TestWatchedModelConfigFails(c *gc.C) {
   163  	fix := &fixture{
   164  		observerErrs: []error{
   165  			nil, nil, nil, errors.New("blam ouch"),
   166  		},
   167  	}
   168  	fix.Run(c, func(context *runContext) {
   169  		tracker, err := environ.NewTracker(environ.Config{
   170  			Observer:       context,
   171  			NewEnvironFunc: newMockEnviron,
   172  		})
   173  		c.Check(err, jc.ErrorIsNil)
   174  		defer workertest.DirtyKill(c, tracker)
   175  
   176  		context.SendModelConfigNotify()
   177  		err = workertest.CheckKilled(c, tracker)
   178  		c.Check(err, gc.ErrorMatches, "cannot read environ config: blam ouch")
   179  		context.CheckCallNames(c, "ModelConfig", "CloudSpec", "WatchForModelConfigChanges", "ModelConfig")
   180  	})
   181  }
   182  
   183  func (s *TrackerSuite) TestWatchedModelConfigIncompatible(c *gc.C) {
   184  	fix := &fixture{}
   185  	fix.Run(c, func(context *runContext) {
   186  		tracker, err := environ.NewTracker(environ.Config{
   187  			Observer: context,
   188  			NewEnvironFunc: func(environs.OpenParams) (environs.Environ, error) {
   189  				env := &mockEnviron{}
   190  				env.SetErrors(errors.New("SetConfig is broken"))
   191  				return env, nil
   192  			},
   193  		})
   194  		c.Check(err, jc.ErrorIsNil)
   195  		defer workertest.DirtyKill(c, tracker)
   196  
   197  		context.SendModelConfigNotify()
   198  		err = workertest.CheckKilled(c, tracker)
   199  		c.Check(err, gc.ErrorMatches, "cannot update environ config: SetConfig is broken")
   200  		context.CheckCallNames(c, "ModelConfig", "CloudSpec", "WatchForModelConfigChanges", "ModelConfig")
   201  	})
   202  }
   203  
   204  func (s *TrackerSuite) TestWatchedModelConfigUpdates(c *gc.C) {
   205  	fix := &fixture{
   206  		initialConfig: coretesting.Attrs{
   207  			"name": "original-name",
   208  		},
   209  	}
   210  	fix.Run(c, func(context *runContext) {
   211  		tracker, err := environ.NewTracker(environ.Config{
   212  			Observer:       context,
   213  			NewEnvironFunc: newMockEnviron,
   214  		})
   215  		c.Check(err, jc.ErrorIsNil)
   216  		defer workertest.CleanKill(c, tracker)
   217  
   218  		context.SetConfig(c, coretesting.Attrs{
   219  			"name": "updated-name",
   220  		})
   221  		gotEnviron := tracker.Environ()
   222  		c.Assert(gotEnviron.Config().Name(), gc.Equals, "original-name")
   223  
   224  		timeout := time.After(coretesting.LongWait)
   225  		attempt := time.After(0)
   226  		context.SendModelConfigNotify()
   227  		for {
   228  			select {
   229  			case <-attempt:
   230  				name := gotEnviron.Config().Name()
   231  				if name == "original-name" {
   232  					attempt = time.After(coretesting.ShortWait)
   233  					continue
   234  				}
   235  				c.Check(name, gc.Equals, "updated-name")
   236  			case <-timeout:
   237  				c.Fatalf("timed out waiting for environ to be updated")
   238  			}
   239  			break
   240  		}
   241  		context.CheckCallNames(c, "ModelConfig", "CloudSpec", "WatchForModelConfigChanges", "ModelConfig")
   242  	})
   243  }