github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/caasmodeloperator/modeloperator_test.go (about)

     1  // Copyright 2020 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasmodeloperator_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/loggo"
     9  	jc "github.com/juju/testing/checkers"
    10  	"github.com/juju/version/v2"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/agent"
    14  	modeloperatorapi "github.com/juju/juju/api/controller/caasmodeloperator"
    15  	"github.com/juju/juju/caas"
    16  	"github.com/juju/juju/core/resources"
    17  	"github.com/juju/juju/core/watcher"
    18  	"github.com/juju/juju/core/watcher/watchertest"
    19  	"github.com/juju/juju/worker/caasmodeloperator"
    20  )
    21  
    22  type dummyAPI struct {
    23  	provInfo      func() (modeloperatorapi.ModelOperatorProvisioningInfo, error)
    24  	setPassword   func(password string) error
    25  	watchProvInfo func() (watcher.NotifyWatcher, error)
    26  }
    27  
    28  type dummyBroker struct {
    29  	ensureModelOperator func(string, string, *caas.ModelOperatorConfig) error
    30  	modelOperator       func() (*caas.ModelOperatorConfig, error)
    31  	modelOperatorExists func() (bool, error)
    32  }
    33  
    34  type ModelOperatorManagerSuite struct{}
    35  
    36  var _ = gc.Suite(&ModelOperatorManagerSuite{})
    37  
    38  func (b *dummyBroker) EnsureModelOperator(modelUUID, agentPath string, c *caas.ModelOperatorConfig) error {
    39  	if b.ensureModelOperator == nil {
    40  		return nil
    41  	}
    42  	return b.ensureModelOperator(modelUUID, agentPath, c)
    43  }
    44  
    45  func (b *dummyBroker) ModelOperator() (*caas.ModelOperatorConfig, error) {
    46  	if b.modelOperator == nil {
    47  		return nil, nil
    48  	}
    49  	return b.modelOperator()
    50  }
    51  
    52  func (b *dummyBroker) ModelOperatorExists() (bool, error) {
    53  	if b.modelOperatorExists == nil {
    54  		return false, nil
    55  	}
    56  	return b.modelOperatorExists()
    57  }
    58  
    59  func (a *dummyAPI) ModelOperatorProvisioningInfo() (modeloperatorapi.ModelOperatorProvisioningInfo, error) {
    60  	if a.provInfo == nil {
    61  		return modeloperatorapi.ModelOperatorProvisioningInfo{}, nil
    62  	}
    63  	return a.provInfo()
    64  }
    65  
    66  func (a *dummyAPI) WatchModelOperatorProvisioningInfo() (watcher.NotifyWatcher, error) {
    67  	if a.watchProvInfo == nil {
    68  		return watcher.NewMultiNotifyWatcher(), nil
    69  	}
    70  	return a.watchProvInfo()
    71  }
    72  
    73  func (a *dummyAPI) SetPassword(p string) error {
    74  	if a.setPassword == nil {
    75  		return nil
    76  	}
    77  	return a.setPassword(p)
    78  }
    79  
    80  func (m *ModelOperatorManagerSuite) TestModelOperatorManagerApplying(c *gc.C) {
    81  	const n = 3
    82  	var (
    83  		iteration = 0 // ... n
    84  
    85  		apiAddresses = [n][]string{{"fe80:abcd::1"}, {"fe80:abcd::2"}, {"fe80:abcd::3"}}
    86  		imagePath    = [n]string{"juju/jujud:1", "juju/jujud:2", "juju/jujud:3"}
    87  		modelUUID    = "deadbeef-0bad-400d-8000-4b1d0d06f00d"
    88  		ver          = [n]version.Number{version.MustParse("2.8.2"), version.MustParse("2.9.1"), version.MustParse("2.9.99")}
    89  
    90  		password   = ""
    91  		lastConfig = (*caas.ModelOperatorConfig)(nil)
    92  	)
    93  
    94  	changed := make(chan struct{})
    95  	api := &dummyAPI{
    96  		provInfo: func() (modeloperatorapi.ModelOperatorProvisioningInfo, error) {
    97  			return modeloperatorapi.ModelOperatorProvisioningInfo{
    98  				APIAddresses: apiAddresses[iteration],
    99  				ImageDetails: resources.DockerImageDetails{RegistryPath: imagePath[iteration]},
   100  				Version:      ver[iteration],
   101  			}, nil
   102  		},
   103  		watchProvInfo: func() (watcher.NotifyWatcher, error) {
   104  			return watchertest.NewMockNotifyWatcher(changed), nil
   105  		},
   106  	}
   107  
   108  	broker := &dummyBroker{
   109  		ensureModelOperator: func(_, _ string, conf *caas.ModelOperatorConfig) error {
   110  			defer func() {
   111  				iteration++
   112  			}()
   113  			lastConfig = conf
   114  
   115  			c.Check(conf.ImageDetails.RegistryPath, gc.Equals, imagePath[iteration])
   116  
   117  			ac, err := agent.ParseConfigData(conf.AgentConf)
   118  			c.Check(err, jc.ErrorIsNil)
   119  			if err != nil {
   120  				return err
   121  			}
   122  			addresses, _ := ac.APIAddresses()
   123  			c.Check(addresses, gc.DeepEquals, apiAddresses[iteration])
   124  			c.Check(ac.UpgradedToVersion(), gc.Equals, ver[iteration])
   125  
   126  			if password == "" {
   127  				password = ac.OldPassword()
   128  			}
   129  			c.Check(ac.OldPassword(), gc.Equals, password)
   130  			c.Check(ac.OldPassword(), gc.HasLen, 24)
   131  
   132  			return nil
   133  		},
   134  		modelOperatorExists: func() (bool, error) {
   135  			return iteration > 0, nil
   136  		},
   137  		modelOperator: func() (*caas.ModelOperatorConfig, error) {
   138  			if iteration == 0 {
   139  				return nil, errors.NotFoundf("model operator")
   140  			}
   141  			return lastConfig, nil
   142  		},
   143  	}
   144  
   145  	worker, err := caasmodeloperator.NewModelOperatorManager(loggo.Logger{},
   146  		api, broker, modelUUID, &mockAgentConfig{})
   147  	c.Assert(err, jc.ErrorIsNil)
   148  
   149  	for i := 0; i < n; i++ {
   150  		changed <- struct{}{}
   151  	}
   152  
   153  	worker.Kill()
   154  	err = worker.Wait()
   155  	c.Assert(err, jc.ErrorIsNil)
   156  
   157  	c.Assert(iteration, gc.Equals, n)
   158  }