github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/binarystorage_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"strings"
    10  
    11  	"github.com/juju/blobstore/v3"
    12  	"github.com/juju/collections/set"
    13  	"github.com/juju/errors"
    14  	"github.com/juju/names/v5"
    15  	jc "github.com/juju/testing/checkers"
    16  	jujutxn "github.com/juju/txn/v3"
    17  	"github.com/juju/utils/v3"
    18  	"github.com/juju/version/v2"
    19  	gc "gopkg.in/check.v1"
    20  
    21  	"github.com/juju/juju/mongo"
    22  	"github.com/juju/juju/state"
    23  	"github.com/juju/juju/state/binarystorage"
    24  	"github.com/juju/juju/storage"
    25  	"github.com/juju/juju/testing"
    26  	"github.com/juju/juju/tools"
    27  )
    28  
    29  type tooler interface {
    30  	AgentTools() (*tools.Tools, error)
    31  	SetAgentVersion(v version.Binary) error
    32  	Refresh() error
    33  }
    34  
    35  func testAgentTools(c *gc.C, obj tooler, agent string) {
    36  	// object starts with zero'd tools.
    37  	t, err := obj.AgentTools()
    38  	c.Assert(t, gc.IsNil)
    39  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    40  
    41  	err = obj.SetAgentVersion(version.Binary{})
    42  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("cannot set agent version for %s: empty series or arch", agent))
    43  
    44  	v2 := version.MustParseBinary("7.8.9-ubuntu-amd64")
    45  	err = obj.SetAgentVersion(v2)
    46  	c.Assert(err, jc.ErrorIsNil)
    47  	t3, err := obj.AgentTools()
    48  	c.Assert(err, jc.ErrorIsNil)
    49  	c.Assert(t3.Version, gc.DeepEquals, v2)
    50  	err = obj.Refresh()
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	t3, err = obj.AgentTools()
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	c.Assert(t3.Version, gc.DeepEquals, v2)
    55  
    56  	if le, ok := obj.(lifer); ok {
    57  		testWhenDying(c, le, noErr, deadErr, func() error {
    58  			return obj.SetAgentVersion(v2)
    59  		})
    60  	}
    61  }
    62  
    63  type binaryStorageSuite struct {
    64  	ConnSuite
    65  
    66  	controllerModelUUID string
    67  	modelUUID           string
    68  	st                  *state.State
    69  }
    70  
    71  var _ = gc.Suite(&binaryStorageSuite{})
    72  
    73  func (s *binaryStorageSuite) SetUpTest(c *gc.C) {
    74  	s.ConnSuite.SetUpTest(c)
    75  
    76  	s.controllerModelUUID = s.State.ControllerModelUUID()
    77  
    78  	// Create a new model and store its UUID.
    79  	s.modelUUID = utils.MustNewUUID().String()
    80  	cfg := testing.CustomModelConfig(c, testing.Attrs{
    81  		"name": "new-model",
    82  		"uuid": s.modelUUID,
    83  	})
    84  	var err error
    85  	_, s.st, err = s.Controller.NewModel(state.ModelArgs{
    86  		Type:                    state.ModelTypeIAAS,
    87  		CloudName:               "dummy",
    88  		CloudRegion:             "dummy-region",
    89  		Config:                  cfg,
    90  		Owner:                   names.NewLocalUserTag("test-admin"),
    91  		StorageProviderRegistry: storage.StaticProviderRegistry{},
    92  	})
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	s.AddCleanup(func(*gc.C) {
    95  		s.st.Close()
    96  	})
    97  }
    98  
    99  type storageOpener func() (binarystorage.StorageCloser, error)
   100  
   101  func (s *binaryStorageSuite) TestToolsStorage(c *gc.C) {
   102  	s.testStorage(c, "toolsmetadata", s.State.ToolsStorage)
   103  }
   104  
   105  func (s *binaryStorageSuite) TestToolsStorageParamsControllerModel(c *gc.C) {
   106  	s.testStorageParams(c, "toolsmetadata", []string{s.State.ModelUUID()}, s.State.ToolsStorage)
   107  }
   108  
   109  func (s *binaryStorageSuite) TestToolsStorageParamsHostedModel(c *gc.C) {
   110  	s.testStorageParams(c, "toolsmetadata", []string{s.modelUUID, s.State.ModelUUID()}, s.st.ToolsStorage)
   111  }
   112  
   113  func (s *binaryStorageSuite) testStorage(c *gc.C, collName string, openStorage storageOpener) {
   114  	session := s.State.MongoSession()
   115  	// if the collection didn't exist, we will create it on demand.
   116  	err := session.DB("juju").C(collName).DropCollection()
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	collectionNames, err := session.DB("juju").CollectionNames()
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	nameSet := set.NewStrings(collectionNames...)
   121  	c.Assert(nameSet.Contains(collName), jc.IsFalse)
   122  
   123  	storage, err := openStorage()
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	defer func() {
   126  		err := storage.Close()
   127  		c.Assert(err, jc.ErrorIsNil)
   128  	}()
   129  
   130  	err = storage.Add(strings.NewReader(""), binarystorage.Metadata{})
   131  	c.Assert(err, jc.ErrorIsNil)
   132  
   133  	collectionNames, err = session.DB("juju").CollectionNames()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	nameSet = set.NewStrings(collectionNames...)
   136  	c.Assert(nameSet.Contains(collName), jc.IsTrue)
   137  }
   138  
   139  func (s *binaryStorageSuite) testStorageParams(c *gc.C, collName string, uuids []string, openStorage storageOpener) {
   140  	var uuidArgs []string
   141  	s.PatchValue(state.BinarystorageNew, func(
   142  		modelUUID string,
   143  		managedStorage blobstore.ManagedStorage,
   144  		metadataCollection mongo.Collection,
   145  		runner jujutxn.Runner,
   146  	) binarystorage.Storage {
   147  		uuidArgs = append(uuidArgs, modelUUID)
   148  		c.Assert(managedStorage, gc.NotNil)
   149  		c.Assert(metadataCollection.Name(), gc.Equals, collName)
   150  		c.Assert(runner, gc.NotNil)
   151  		return nil
   152  	})
   153  
   154  	storage, err := openStorage()
   155  	c.Assert(err, jc.ErrorIsNil)
   156  	storage.Close()
   157  	c.Assert(uuidArgs, jc.DeepEquals, uuids)
   158  }
   159  
   160  func (s *binaryStorageSuite) TestToolsStorageLayered(c *gc.C) {
   161  	modelTools, err := s.st.ToolsStorage()
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	defer modelTools.Close()
   164  
   165  	controllerTools, err := s.State.ToolsStorage()
   166  	c.Assert(err, jc.ErrorIsNil)
   167  	defer controllerTools.Close()
   168  
   169  	err = modelTools.Add(strings.NewReader("abc"), binarystorage.Metadata{Version: "1.0", Size: 3})
   170  	c.Assert(err, jc.ErrorIsNil)
   171  	err = controllerTools.Add(strings.NewReader("defg"), binarystorage.Metadata{Version: "1.0", Size: 4})
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	err = controllerTools.Add(strings.NewReader("def"), binarystorage.Metadata{Version: "2.0", Size: 3})
   174  	c.Assert(err, jc.ErrorIsNil)
   175  
   176  	all, err := modelTools.AllMetadata()
   177  	c.Assert(err, jc.ErrorIsNil)
   178  	c.Assert(all, jc.DeepEquals, []binarystorage.Metadata{
   179  		{Version: "1.0", Size: 3},
   180  		{Version: "2.0", Size: 3},
   181  	})
   182  
   183  	assertContents := func(v, contents string) {
   184  		_, rc, err := modelTools.Open(v)
   185  		c.Assert(err, jc.ErrorIsNil)
   186  		c.Assert(rc, gc.NotNil)
   187  		defer rc.Close()
   188  		data, err := io.ReadAll(rc)
   189  		c.Assert(err, jc.ErrorIsNil)
   190  		c.Assert(string(data), gc.Equals, contents)
   191  	}
   192  	assertContents("1.0", "abc")
   193  	assertContents("2.0", "def")
   194  }