github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/caasapplicationprovisioner/worker_test.go (about)

     1  // Copyright 2020 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasapplicationprovisioner_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock/testclock"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/loggo"
    12  	"github.com/juju/names/v5"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/worker/v3"
    15  	"github.com/juju/worker/v3/workertest"
    16  	"go.uber.org/mock/gomock"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/caas"
    20  	"github.com/juju/juju/core/life"
    21  	"github.com/juju/juju/core/watcher"
    22  	"github.com/juju/juju/core/watcher/watchertest"
    23  	"github.com/juju/juju/rpc/params"
    24  	coretesting "github.com/juju/juju/testing"
    25  	"github.com/juju/juju/worker/caasapplicationprovisioner"
    26  	"github.com/juju/juju/worker/caasapplicationprovisioner/mocks"
    27  )
    28  
    29  var _ = gc.Suite(&CAASApplicationSuite{})
    30  
    31  type CAASApplicationSuite struct {
    32  	coretesting.BaseSuite
    33  
    34  	clock    *testclock.Clock
    35  	modelTag names.ModelTag
    36  	logger   loggo.Logger
    37  }
    38  
    39  func (s *CAASApplicationSuite) SetUpTest(c *gc.C) {
    40  	s.clock = testclock.NewClock(time.Now())
    41  	s.modelTag = names.NewModelTag("ffffffff-ffff-ffff-ffff-ffffffffffff")
    42  	s.logger = loggo.GetLogger("test")
    43  }
    44  
    45  func (s *CAASApplicationSuite) TestWorkerStart(c *gc.C) {
    46  	ctrl := gomock.NewController(c)
    47  	defer ctrl.Finish()
    48  
    49  	appChan := make(chan []string, 1)
    50  	done := make(chan struct{})
    51  
    52  	facade := mocks.NewMockCAASProvisionerFacade(ctrl)
    53  	runner := mocks.NewMockRunner(ctrl)
    54  
    55  	facade.EXPECT().WatchApplications().DoAndReturn(func() (watcher.StringsWatcher, error) {
    56  		appChan <- []string{"test"}
    57  		return watchertest.NewMockStringsWatcher(appChan), nil
    58  	})
    59  	facade.EXPECT().ProvisionerConfig().Return(params.CAASApplicationProvisionerConfig{
    60  		UnmanagedApplications: params.Entities{},
    61  	}, nil)
    62  	facade.EXPECT().Life("test").Return(life.Alive, nil)
    63  	runner.EXPECT().Worker("test", gomock.Any()).Return(nil, errors.NotFoundf(""))
    64  	runner.EXPECT().StartWorker("test", gomock.Any()).DoAndReturn(
    65  		func(_ string, startFunc func() (worker.Worker, error)) error {
    66  			startFunc()
    67  			return nil
    68  		},
    69  	)
    70  	runner.EXPECT().Wait().AnyTimes().DoAndReturn(func() error {
    71  		<-done
    72  		return nil
    73  	})
    74  	runner.EXPECT().Kill().AnyTimes()
    75  
    76  	called := false
    77  	newWorker := func(config caasapplicationprovisioner.AppWorkerConfig) func() (worker.Worker, error) {
    78  		c.Assert(called, jc.IsFalse)
    79  		called = true
    80  		mc := jc.NewMultiChecker()
    81  		mc.AddExpr("_.Facade", gc.NotNil)
    82  		mc.AddExpr("_.Broker", gc.NotNil)
    83  		mc.AddExpr("_.Clock", gc.NotNil)
    84  		mc.AddExpr("_.Logger", gc.NotNil)
    85  		mc.AddExpr("_.ShutDownCleanUpFunc", gc.NotNil)
    86  		c.Check(config, mc, caasapplicationprovisioner.AppWorkerConfig{
    87  			Name:     "test",
    88  			ModelTag: s.modelTag,
    89  		})
    90  		return func() (worker.Worker, error) {
    91  			close(done)
    92  			return workertest.NewErrorWorker(nil), nil
    93  		}
    94  	}
    95  	config := caasapplicationprovisioner.Config{
    96  		Facade:       facade,
    97  		Broker:       struct{ caas.Broker }{},
    98  		ModelTag:     s.modelTag,
    99  		Clock:        s.clock,
   100  		Logger:       s.logger,
   101  		NewAppWorker: newWorker,
   102  	}
   103  	provisioner, err := caasapplicationprovisioner.NewProvisionerWorkerForTest(config, runner)
   104  	c.Assert(err, jc.ErrorIsNil)
   105  	c.Assert(provisioner, gc.NotNil)
   106  
   107  	select {
   108  	case <-done:
   109  		c.Assert(called, jc.IsTrue)
   110  	case <-time.After(coretesting.LongWait):
   111  		c.Fatalf("timed out waiting for worker to start")
   112  	}
   113  
   114  	workertest.CleanKill(c, provisioner)
   115  }
   116  
   117  func (s *CAASApplicationSuite) TestWorkerStartUnmanaged(c *gc.C) {
   118  	ctrl := gomock.NewController(c)
   119  	defer ctrl.Finish()
   120  
   121  	appChan := make(chan []string, 1)
   122  	done := make(chan struct{})
   123  
   124  	facade := mocks.NewMockCAASProvisionerFacade(ctrl)
   125  	runner := mocks.NewMockRunner(ctrl)
   126  
   127  	facade.EXPECT().WatchApplications().DoAndReturn(func() (watcher.StringsWatcher, error) {
   128  		appChan <- []string{"test"}
   129  		return watchertest.NewMockStringsWatcher(appChan), nil
   130  	})
   131  	facade.EXPECT().ProvisionerConfig().Return(params.CAASApplicationProvisionerConfig{
   132  		UnmanagedApplications: params.Entities{Entities: []params.Entity{{Tag: "application-test"}}},
   133  	}, nil)
   134  	facade.EXPECT().Life("test").Return(life.Alive, nil)
   135  	runner.EXPECT().Worker("test", gomock.Any()).Return(nil, errors.NotFoundf(""))
   136  	runner.EXPECT().StartWorker("test", gomock.Any()).DoAndReturn(
   137  		func(_ string, startFunc func() (worker.Worker, error)) error {
   138  			startFunc()
   139  			return nil
   140  		},
   141  	)
   142  	runner.EXPECT().Wait().AnyTimes().DoAndReturn(func() error {
   143  		<-done
   144  		return nil
   145  	})
   146  	runner.EXPECT().Kill().AnyTimes()
   147  
   148  	called := false
   149  	newWorker := func(config caasapplicationprovisioner.AppWorkerConfig) func() (worker.Worker, error) {
   150  		c.Assert(called, jc.IsFalse)
   151  		called = true
   152  		mc := jc.NewMultiChecker()
   153  		mc.AddExpr("_.Facade", gc.NotNil)
   154  		mc.AddExpr("_.Broker", gc.NotNil)
   155  		mc.AddExpr("_.Clock", gc.NotNil)
   156  		mc.AddExpr("_.Logger", gc.NotNil)
   157  		mc.AddExpr("_.ShutDownCleanUpFunc", gc.NotNil)
   158  		c.Check(config, mc, caasapplicationprovisioner.AppWorkerConfig{
   159  			Name:       "test",
   160  			ModelTag:   s.modelTag,
   161  			StatusOnly: true,
   162  		})
   163  		return func() (worker.Worker, error) {
   164  			close(done)
   165  			return workertest.NewErrorWorker(nil), nil
   166  		}
   167  	}
   168  	config := caasapplicationprovisioner.Config{
   169  		Facade:       facade,
   170  		Broker:       struct{ caas.Broker }{},
   171  		ModelTag:     s.modelTag,
   172  		Clock:        s.clock,
   173  		Logger:       s.logger,
   174  		NewAppWorker: newWorker,
   175  	}
   176  	provisioner, err := caasapplicationprovisioner.NewProvisionerWorkerForTest(config, runner)
   177  	c.Assert(err, jc.ErrorIsNil)
   178  	c.Assert(provisioner, gc.NotNil)
   179  
   180  	select {
   181  	case <-done:
   182  		c.Assert(called, jc.IsTrue)
   183  	case <-time.After(coretesting.LongWait):
   184  		c.Fatalf("timed out waiting for worker to start")
   185  	}
   186  
   187  	workertest.CleanKill(c, provisioner)
   188  }
   189  
   190  func (s *CAASApplicationSuite) TestWorkerStartOnceNotify(c *gc.C) {
   191  	ctrl := gomock.NewController(c)
   192  	defer ctrl.Finish()
   193  
   194  	appChan := make(chan []string, 5)
   195  	done := make(chan struct{})
   196  
   197  	appChan <- []string{"test"}
   198  	appChan <- []string{"test"}
   199  	appChan <- []string{"test"}
   200  	appChan <- []string{"test"}
   201  	appChan <- []string{"test"}
   202  	facade := mocks.NewMockCAASProvisionerFacade(ctrl)
   203  	runner := mocks.NewMockRunner(ctrl)
   204  
   205  	var notifyWorker = &mockNotifyWorker{Worker: workertest.NewErrorWorker(nil)}
   206  
   207  	gomock.InOrder(
   208  		facade.EXPECT().WatchApplications().DoAndReturn(func() (watcher.StringsWatcher, error) {
   209  			return watchertest.NewMockStringsWatcher(appChan), nil
   210  		}),
   211  		facade.EXPECT().ProvisionerConfig().Return(params.CAASApplicationProvisionerConfig{}, nil),
   212  		facade.EXPECT().Life("test").Return(life.Alive, nil),
   213  		runner.EXPECT().Worker("test", gomock.Any()).Return(nil, errors.NotFoundf("")),
   214  		runner.EXPECT().StartWorker("test", gomock.Any()).DoAndReturn(
   215  			func(_ string, startFunc func() (worker.Worker, error)) error {
   216  				startFunc()
   217  				return nil
   218  			},
   219  		),
   220  
   221  		facade.EXPECT().Life("test").Return(life.Alive, nil),
   222  		runner.EXPECT().Worker("test", gomock.Any()).Return(notifyWorker, nil),
   223  
   224  		facade.EXPECT().Life("test").Return(life.Alive, nil),
   225  		runner.EXPECT().Worker("test", gomock.Any()).Return(notifyWorker, nil),
   226  
   227  		facade.EXPECT().Life("test").Return(life.Alive, nil),
   228  		runner.EXPECT().Worker("test", gomock.Any()).Return(notifyWorker, nil),
   229  
   230  		facade.EXPECT().Life("test").Return(life.Alive, nil),
   231  		runner.EXPECT().Worker("test", gomock.Any()).DoAndReturn(
   232  			func(_ string, abort <-chan struct{}) (worker.Worker, error) {
   233  				close(done)
   234  				return nil, worker.ErrDead
   235  			},
   236  		),
   237  	)
   238  	runner.EXPECT().Wait().AnyTimes().DoAndReturn(func() error {
   239  		<-done
   240  		return nil
   241  	})
   242  	runner.EXPECT().Kill().AnyTimes()
   243  
   244  	called := 0
   245  	newWorker := func(config caasapplicationprovisioner.AppWorkerConfig) func() (worker.Worker, error) {
   246  		called++
   247  		mc := jc.NewMultiChecker()
   248  		mc.AddExpr("_.Facade", gc.NotNil)
   249  		mc.AddExpr("_.Broker", gc.NotNil)
   250  		mc.AddExpr("_.Clock", gc.NotNil)
   251  		mc.AddExpr("_.Logger", gc.NotNil)
   252  		mc.AddExpr("_.ShutDownCleanUpFunc", gc.NotNil)
   253  		c.Check(config, mc, caasapplicationprovisioner.AppWorkerConfig{
   254  			Name:     "test",
   255  			ModelTag: s.modelTag,
   256  		})
   257  		return func() (worker.Worker, error) {
   258  			return notifyWorker, nil
   259  		}
   260  	}
   261  	config := caasapplicationprovisioner.Config{
   262  		Facade:       facade,
   263  		Broker:       struct{ caas.Broker }{},
   264  		ModelTag:     s.modelTag,
   265  		Clock:        s.clock,
   266  		Logger:       s.logger,
   267  		NewAppWorker: newWorker,
   268  	}
   269  	provisioner, err := caasapplicationprovisioner.NewProvisionerWorkerForTest(config, runner)
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	c.Assert(provisioner, gc.NotNil)
   272  
   273  	select {
   274  	case <-done:
   275  	case <-time.After(coretesting.LongWait):
   276  		c.Fatalf("timed out waiting for worker to start")
   277  	}
   278  
   279  	c.Assert(called, gc.Equals, 1)
   280  	c.Assert(notifyWorker, gc.NotNil)
   281  	select {
   282  	case <-time.After(coretesting.ShortWait):
   283  		workertest.CleanKill(c, provisioner)
   284  		notifyWorker.CheckCallNames(c, "Notify", "Notify", "Notify")
   285  	}
   286  }