github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/environs/jujutest/tests.go (about)

     1  // Copyright 2011, 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujutest
     5  
     6  import (
     7  	stdcontext "context"
     8  	"path/filepath"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	"github.com/juju/utils/v3"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/cloud"
    15  	"github.com/juju/juju/core/instance"
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/environs/bootstrap"
    18  	environscloudspec "github.com/juju/juju/environs/cloudspec"
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/environs/context"
    21  	"github.com/juju/juju/environs/filestorage"
    22  	"github.com/juju/juju/environs/simplestreams"
    23  	sstesting "github.com/juju/juju/environs/simplestreams/testing"
    24  	"github.com/juju/juju/environs/storage"
    25  	envtesting "github.com/juju/juju/environs/testing"
    26  	"github.com/juju/juju/juju/testing"
    27  	"github.com/juju/juju/jujuclient"
    28  	coretesting "github.com/juju/juju/testing"
    29  	jujuversion "github.com/juju/juju/version"
    30  )
    31  
    32  // Tests is a gocheck suite containing tests verifying juju functionality
    33  // against the environment with the given configuration. The
    34  // tests are not designed to be run against a live server - the Environ
    35  // is opened once for each test, and some potentially expensive operations
    36  // may be executed.
    37  type Tests struct {
    38  	TestConfig     coretesting.Attrs
    39  	Credential     cloud.Credential
    40  	CloudEndpoint  string
    41  	CloudRegion    string
    42  	ControllerUUID string
    43  	Env            environs.Environ
    44  	envtesting.ToolsFixture
    45  	sstesting.TestDataSuite
    46  
    47  	// ControllerStore holds the controller related information
    48  	// such as controllers, accounts, etc., used when preparing
    49  	// the environment. This is initialized by SetUpSuite.
    50  	ControllerStore jujuclient.ClientStore
    51  	toolsStorage    storage.Storage
    52  
    53  	// ProviderCallContext holds the context to be used to make
    54  	// calls to a cloud provider.
    55  	ProviderCallContext context.ProviderCallContext
    56  
    57  	// BootstrapContext holds the context to bootstrap a test environment.
    58  	BootstrapContext environs.BootstrapContext
    59  }
    60  
    61  // Open opens an instance of the testing environment.
    62  func (t *Tests) Open(c *gc.C, ctx stdcontext.Context, cfg *config.Config) environs.Environ {
    63  	e, err := environs.New(ctx, environs.OpenParams{
    64  		Cloud:  t.CloudSpec(),
    65  		Config: cfg,
    66  	})
    67  	c.Assert(err, gc.IsNil, gc.Commentf("opening environ %#v", cfg.AllAttrs()))
    68  	c.Assert(e, gc.NotNil)
    69  	return e
    70  }
    71  
    72  func (t *Tests) CloudSpec() environscloudspec.CloudSpec {
    73  	credential := t.Credential
    74  	if credential.AuthType() == "" {
    75  		credential = cloud.NewEmptyCredential()
    76  	}
    77  	return environscloudspec.CloudSpec{
    78  		Type:       t.TestConfig["type"].(string),
    79  		Name:       t.TestConfig["type"].(string),
    80  		Region:     t.CloudRegion,
    81  		Endpoint:   t.CloudEndpoint,
    82  		Credential: &credential,
    83  	}
    84  }
    85  
    86  // PrepareParams returns the environs.PrepareParams that will be used to call
    87  // environs.Prepare.
    88  func (t *Tests) PrepareParams(c *gc.C) bootstrap.PrepareParams {
    89  	testConfigCopy := t.TestConfig.Merge(nil)
    90  
    91  	return bootstrap.PrepareParams{
    92  		ControllerConfig: coretesting.FakeControllerConfig(),
    93  		ModelConfig:      testConfigCopy,
    94  		Cloud:            t.CloudSpec(),
    95  		ControllerName:   t.TestConfig["name"].(string),
    96  		AdminSecret:      AdminSecret,
    97  	}
    98  }
    99  
   100  // Prepare prepares an instance of the testing environment.
   101  func (t *Tests) Prepare(c *gc.C) environs.Environ {
   102  	t.Env = t.PrepareWithParams(c, t.PrepareParams(c))
   103  	return t.Env
   104  }
   105  
   106  // PrepareWithParams prepares an instance of the testing environment.
   107  func (t *Tests) PrepareWithParams(c *gc.C, params bootstrap.PrepareParams) environs.Environ {
   108  	e, err := bootstrap.PrepareController(false, t.BootstrapContext, t.ControllerStore, params)
   109  	c.Assert(err, gc.IsNil, gc.Commentf("preparing environ %#v", params.ModelConfig))
   110  	c.Assert(e, gc.NotNil)
   111  	t.Env = e.(environs.Environ)
   112  	return t.Env
   113  }
   114  
   115  func (t *Tests) AssertPrepareFailsWithConfig(c *gc.C, badConfig coretesting.Attrs, errorMatches string) error {
   116  	args := t.PrepareParams(c)
   117  	args.ModelConfig = coretesting.Attrs(args.ModelConfig).Merge(badConfig)
   118  
   119  	e, err := bootstrap.PrepareController(false, t.BootstrapContext, t.ControllerStore, args)
   120  	c.Assert(err, gc.ErrorMatches, errorMatches)
   121  	c.Assert(e, gc.IsNil)
   122  	return err
   123  }
   124  
   125  func (t *Tests) SetUpTest(c *gc.C) {
   126  	storageDir := c.MkDir()
   127  	baseURLPath := filepath.Join(storageDir, "tools")
   128  	t.DefaultBaseURL = utils.MakeFileURL(baseURLPath)
   129  	t.ToolsFixture.SetUpTest(c)
   130  	stor, err := filestorage.NewFileStorageWriter(storageDir)
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	t.UploadFakeTools(c, stor, "released", "released")
   133  	t.toolsStorage = stor
   134  	t.ControllerStore = jujuclient.NewMemStore()
   135  	t.ControllerUUID = coretesting.FakeControllerConfig().ControllerUUID()
   136  
   137  	ss := simplestreams.NewSimpleStreams(sstesting.TestDataSourceFactory())
   138  	ctx := stdcontext.WithValue(stdcontext.TODO(), bootstrap.SimplestreamsFetcherContextKey, ss)
   139  	t.BootstrapContext = envtesting.BootstrapContext(ctx, c)
   140  	t.ProviderCallContext = context.NewCloudCallContext(ctx)
   141  }
   142  
   143  func (t *Tests) TearDownTest(c *gc.C) {
   144  	t.ToolsFixture.TearDownTest(c)
   145  }
   146  
   147  func (t *Tests) TestStartStop(c *gc.C) {
   148  	e := t.Prepare(c)
   149  	cfg, err := e.Config().Apply(map[string]interface{}{
   150  		"agent-version": jujuversion.Current.String(),
   151  	})
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	err = e.SetConfig(cfg)
   154  	c.Assert(err, jc.ErrorIsNil)
   155  
   156  	insts, err := e.Instances(t.ProviderCallContext, nil)
   157  	c.Assert(err, jc.ErrorIsNil)
   158  	c.Assert(insts, gc.HasLen, 0)
   159  
   160  	inst0, hc := testing.AssertStartInstance(c, e, t.ProviderCallContext, t.ControllerUUID, "0")
   161  	c.Assert(inst0, gc.NotNil)
   162  	id0 := inst0.Id()
   163  	// Sanity check for hardware characteristics.
   164  	c.Assert(hc.Arch, gc.NotNil)
   165  	c.Assert(hc.Mem, gc.NotNil)
   166  	c.Assert(hc.CpuCores, gc.NotNil)
   167  
   168  	inst1, _ := testing.AssertStartInstance(c, e, t.ProviderCallContext, t.ControllerUUID, "1")
   169  	c.Assert(inst1, gc.NotNil)
   170  	id1 := inst1.Id()
   171  
   172  	insts, err = e.Instances(t.ProviderCallContext, []instance.Id{id0, id1})
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(insts, gc.HasLen, 2)
   175  	c.Assert(insts[0].Id(), gc.Equals, id0)
   176  	c.Assert(insts[1].Id(), gc.Equals, id1)
   177  
   178  	// order of results is not specified
   179  	insts, err = e.AllInstances(t.ProviderCallContext)
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Assert(insts, gc.HasLen, 2)
   182  	c.Assert(insts[0].Id(), gc.Not(gc.Equals), insts[1].Id())
   183  
   184  	err = e.StopInstances(t.ProviderCallContext, inst0.Id())
   185  	c.Assert(err, jc.ErrorIsNil)
   186  
   187  	insts, err = e.Instances(t.ProviderCallContext, []instance.Id{id0, id1})
   188  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   189  	c.Assert(insts[0], gc.IsNil)
   190  	c.Assert(insts[1].Id(), gc.Equals, id1)
   191  
   192  	insts, err = e.AllInstances(t.ProviderCallContext)
   193  	c.Assert(err, jc.ErrorIsNil)
   194  	c.Assert(insts[0].Id(), gc.Equals, id1)
   195  }
   196  
   197  func (t *Tests) TestBootstrap(c *gc.C) {
   198  	credential := t.Credential
   199  	if credential.AuthType() == "" {
   200  		credential = cloud.NewEmptyCredential()
   201  	}
   202  
   203  	var regions []cloud.Region
   204  	if t.CloudRegion != "" {
   205  		regions = []cloud.Region{{
   206  			Name:     t.CloudRegion,
   207  			Endpoint: t.CloudEndpoint,
   208  		}}
   209  	}
   210  
   211  	args := bootstrap.BootstrapParams{
   212  		ControllerConfig: coretesting.FakeControllerConfig(),
   213  		Cloud: cloud.Cloud{
   214  			Name:      t.TestConfig["type"].(string),
   215  			Type:      t.TestConfig["type"].(string),
   216  			AuthTypes: []cloud.AuthType{credential.AuthType()},
   217  			Regions:   regions,
   218  			Endpoint:  t.CloudEndpoint,
   219  		},
   220  		CloudRegion:             t.CloudRegion,
   221  		CloudCredential:         &credential,
   222  		CloudCredentialName:     "credential",
   223  		AdminSecret:             AdminSecret,
   224  		CAPrivateKey:            coretesting.CAKey,
   225  		SupportedBootstrapBases: coretesting.FakeSupportedJujuBases,
   226  	}
   227  
   228  	e := t.Prepare(c)
   229  	err := bootstrap.Bootstrap(t.BootstrapContext, e, t.ProviderCallContext, args)
   230  	c.Assert(err, jc.ErrorIsNil)
   231  
   232  	controllerInstances, err := e.ControllerInstances(t.ProviderCallContext, t.ControllerUUID)
   233  	c.Assert(err, jc.ErrorIsNil)
   234  	c.Assert(controllerInstances, gc.Not(gc.HasLen), 0)
   235  
   236  	e2 := t.Open(c, t.BootstrapContext.Context(), e.Config())
   237  	controllerInstances2, err := e2.ControllerInstances(t.ProviderCallContext, t.ControllerUUID)
   238  	c.Assert(err, jc.ErrorIsNil)
   239  	c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0)
   240  	c.Assert(controllerInstances2, jc.SameContents, controllerInstances)
   241  
   242  	err = environs.Destroy(e2.Config().Name(), e2, t.ProviderCallContext, t.ControllerStore)
   243  	c.Assert(err, jc.ErrorIsNil)
   244  
   245  	// Prepare again because Destroy invalidates old environments.
   246  	e3 := t.Prepare(c)
   247  
   248  	err = bootstrap.Bootstrap(t.BootstrapContext, e3, t.ProviderCallContext, args)
   249  	c.Assert(err, jc.ErrorIsNil)
   250  
   251  	err = environs.Destroy(e3.Config().Name(), e3, t.ProviderCallContext, t.ControllerStore)
   252  	c.Assert(err, jc.ErrorIsNil)
   253  }