github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/environs/configstore/cachefile_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package configstore_test
     5  
     6  import (
     7  	"fmt"
     8  	"path/filepath"
     9  
    10  	"github.com/juju/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/environs/configstore"
    15  	"github.com/juju/juju/feature"
    16  )
    17  
    18  var _ = gc.Suite(&cacheFileInterfaceSuite{})
    19  
    20  type cacheFileInterfaceSuite struct {
    21  	interfaceSuite
    22  	dir   string
    23  	store configstore.Storage
    24  }
    25  
    26  func (s *cacheFileInterfaceSuite) SetUpTest(c *gc.C) {
    27  	s.interfaceSuite.SetUpTest(c)
    28  	s.SetFeatureFlags(feature.JES)
    29  	s.dir = c.MkDir()
    30  	s.NewStore = func(c *gc.C) configstore.Storage {
    31  		store, err := configstore.NewDisk(s.dir)
    32  		c.Assert(err, jc.ErrorIsNil)
    33  		return store
    34  	}
    35  	s.store = s.NewStore(c)
    36  }
    37  
    38  func (s *cacheFileInterfaceSuite) writeEnv(c *gc.C, name, envUUID, srvUUID, user, password string) configstore.EnvironInfo {
    39  	info := s.store.CreateInfo(name)
    40  	info.SetAPIEndpoint(configstore.APIEndpoint{
    41  		Addresses:   []string{"address1", "address2"},
    42  		Hostnames:   []string{"hostname1", "hostname2"},
    43  		CACert:      testing.CACert,
    44  		EnvironUUID: envUUID,
    45  		ServerUUID:  srvUUID,
    46  	})
    47  	info.SetAPICredentials(configstore.APICredentials{
    48  		User:     user,
    49  		Password: password,
    50  	})
    51  	err := info.Write()
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	return info
    54  }
    55  
    56  func (s *cacheFileInterfaceSuite) TestServerUUIDWrite(c *gc.C) {
    57  	envUUID := testing.EnvironmentTag.Id()
    58  	info := s.writeEnv(c, "testing", envUUID, envUUID, "tester", "secret")
    59  
    60  	// Now make sure the cache file exists and the jenv doesn't
    61  	envDir := filepath.Join(s.dir, "environments")
    62  	filename := configstore.CacheFilename(envDir)
    63  	c.Assert(info.Location(), gc.Equals, fmt.Sprintf("file %q", filename))
    64  
    65  	cache := s.readCacheFile(c)
    66  	c.Assert(cache.Server, gc.HasLen, 1)
    67  	c.Assert(cache.ServerData, gc.HasLen, 1)
    68  	c.Assert(cache.Environment, gc.HasLen, 1)
    69  }
    70  
    71  func (s *cacheFileInterfaceSuite) TestServerEnvNameExists(c *gc.C) {
    72  	envUUID := testing.EnvironmentTag.Id()
    73  	s.writeEnv(c, "testing", envUUID, envUUID, "tester", "secret")
    74  
    75  	info := s.store.CreateInfo("testing")
    76  	// In order to trigger the writing to the cache file, we need to store
    77  	// a server uuid.
    78  	info.SetAPIEndpoint(configstore.APIEndpoint{
    79  		EnvironUUID: envUUID,
    80  		ServerUUID:  envUUID,
    81  	})
    82  	err := info.Write()
    83  	c.Assert(err, gc.ErrorMatches, "environment info already exists")
    84  }
    85  
    86  func (s *cacheFileInterfaceSuite) TestWriteServerOnly(c *gc.C) {
    87  	envUUID := testing.EnvironmentTag.Id()
    88  	s.writeEnv(c, "testing", "", envUUID, "tester", "secret")
    89  	cache := s.readCacheFile(c)
    90  	c.Assert(cache.Server, gc.HasLen, 1)
    91  	c.Assert(cache.ServerData, gc.HasLen, 1)
    92  	c.Assert(cache.Environment, gc.HasLen, 0)
    93  }
    94  
    95  func (s *cacheFileInterfaceSuite) TestWriteEnvAfterServer(c *gc.C) {
    96  	envUUID := testing.EnvironmentTag.Id()
    97  	s.writeEnv(c, "testing", "", envUUID, "tester", "secret")
    98  	info := s.store.CreateInfo("testing")
    99  
   100  	info.SetAPIEndpoint(configstore.APIEndpoint{
   101  		EnvironUUID: envUUID,
   102  		ServerUUID:  envUUID,
   103  	})
   104  	err := info.Write()
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	cache := s.readCacheFile(c)
   107  	c.Assert(cache.Server, gc.HasLen, 1)
   108  	c.Assert(cache.ServerData, gc.HasLen, 1)
   109  	c.Assert(cache.Environment, gc.HasLen, 1)
   110  }
   111  
   112  func (s *cacheFileInterfaceSuite) TestWriteDupEnvAfterServer(c *gc.C) {
   113  	envUUID := testing.EnvironmentTag.Id()
   114  	s.writeEnv(c, "testing", "", envUUID, "tester", "secret")
   115  	info := s.store.CreateInfo("testing")
   116  
   117  	info.SetAPIEndpoint(configstore.APIEndpoint{
   118  		EnvironUUID: "fake-uuid",
   119  		ServerUUID:  "fake-uuid",
   120  	})
   121  	err := info.Write()
   122  	c.Assert(err, gc.ErrorMatches, "environment info already exists")
   123  }
   124  
   125  func (s *cacheFileInterfaceSuite) TestServerUUIDRead(c *gc.C) {
   126  	envUUID := testing.EnvironmentTag.Id()
   127  	s.writeEnv(c, "testing", envUUID, envUUID, "tester", "secret")
   128  
   129  	info, err := s.store.ReadInfo("testing")
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	c.Assert(info.APICredentials(), jc.DeepEquals, configstore.APICredentials{
   132  		User:     "tester",
   133  		Password: "secret",
   134  	})
   135  	c.Assert(info.APIEndpoint(), jc.DeepEquals, configstore.APIEndpoint{
   136  		Addresses:   []string{"address1", "address2"},
   137  		Hostnames:   []string{"hostname1", "hostname2"},
   138  		CACert:      testing.CACert,
   139  		EnvironUUID: envUUID,
   140  		ServerUUID:  envUUID,
   141  	})
   142  }
   143  
   144  func (s *cacheFileInterfaceSuite) TestServerDetailsShared(c *gc.C) {
   145  	envUUID := testing.EnvironmentTag.Id()
   146  	s.writeEnv(c, "testing", envUUID, envUUID, "tester", "secret")
   147  	info := s.writeEnv(c, "second", "fake-uuid", envUUID, "tester", "new-secret")
   148  	endpoint := info.APIEndpoint()
   149  	endpoint.Addresses = []string{"address2", "address3"}
   150  	endpoint.Hostnames = []string{"hostname2", "hostname3"}
   151  	info.SetAPIEndpoint(endpoint)
   152  	err := info.Write()
   153  	c.Assert(err, jc.ErrorIsNil)
   154  
   155  	info, err = s.store.ReadInfo("testing")
   156  	c.Assert(err, jc.ErrorIsNil)
   157  	c.Assert(info.APICredentials(), jc.DeepEquals, configstore.APICredentials{
   158  		User:     "tester",
   159  		Password: "new-secret",
   160  	})
   161  	c.Assert(info.APIEndpoint(), jc.DeepEquals, configstore.APIEndpoint{
   162  		Addresses:   []string{"address2", "address3"},
   163  		Hostnames:   []string{"hostname2", "hostname3"},
   164  		CACert:      testing.CACert,
   165  		EnvironUUID: envUUID,
   166  		ServerUUID:  envUUID,
   167  	})
   168  
   169  	cache := s.readCacheFile(c)
   170  	c.Assert(cache.Server, gc.HasLen, 1)
   171  	c.Assert(cache.ServerData, gc.HasLen, 1)
   172  	c.Assert(cache.Environment, gc.HasLen, 2)
   173  }
   174  
   175  func (s *cacheFileInterfaceSuite) TestMigrateJENV(c *gc.C) {
   176  	envUUID := testing.EnvironmentTag.Id()
   177  	info := s.writeEnv(c, "testing", envUUID, "", "tester", "secret")
   178  	envDir := filepath.Join(s.dir, "environments")
   179  	jenvFilename := configstore.JENVFilename(envDir, "testing")
   180  	c.Assert(info.Location(), gc.Equals, fmt.Sprintf("file %q", jenvFilename))
   181  
   182  	// Add server details and write again will migrate the info to the
   183  	// cache file.
   184  	endpoint := info.APIEndpoint()
   185  	endpoint.ServerUUID = envUUID
   186  	info.SetAPIEndpoint(endpoint)
   187  	err := info.Write()
   188  	c.Assert(err, jc.ErrorIsNil)
   189  
   190  	c.Assert(jenvFilename, jc.DoesNotExist)
   191  	cache := s.readCacheFile(c)
   192  
   193  	envInfo, ok := cache.Environment["testing"]
   194  	c.Assert(ok, jc.IsTrue)
   195  	c.Assert(envInfo.User, gc.Equals, "tester")
   196  	c.Assert(envInfo.EnvironmentUUID, gc.Equals, envUUID)
   197  	c.Assert(envInfo.ServerUUID, gc.Equals, envUUID)
   198  	// Server entry also written.
   199  	srvInfo, ok := cache.Server["testing"]
   200  	c.Assert(ok, jc.IsTrue)
   201  	c.Assert(srvInfo.User, gc.Equals, "tester")
   202  	c.Assert(srvInfo.ServerUUID, gc.Equals, envUUID)
   203  
   204  	readInfo, err := s.store.ReadInfo("testing")
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	c.Assert(readInfo.APIEndpoint(), jc.DeepEquals, info.APIEndpoint())
   207  }
   208  
   209  func (s *cacheFileInterfaceSuite) readCacheFile(c *gc.C) configstore.CacheFile {
   210  	envDir := filepath.Join(s.dir, "environments")
   211  	filename := configstore.CacheFilename(envDir)
   212  	cache, err := configstore.ReadCacheFile(filename)
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	return cache
   215  }
   216  
   217  func (s *cacheFileInterfaceSuite) TestExistingJENVBlocksNew(c *gc.C) {
   218  	envUUID := testing.EnvironmentTag.Id()
   219  	info := s.writeEnv(c, "testing", envUUID, "", "tester", "secret")
   220  	envDir := filepath.Join(s.dir, "environments")
   221  	jenvFilename := configstore.JENVFilename(envDir, "testing")
   222  	c.Assert(info.Location(), gc.Equals, fmt.Sprintf("file %q", jenvFilename))
   223  
   224  	info = s.store.CreateInfo("testing")
   225  	// In order to trigger the writing to the cache file, we need to store
   226  	// a server uuid.
   227  	info.SetAPIEndpoint(configstore.APIEndpoint{
   228  		EnvironUUID: envUUID,
   229  		ServerUUID:  envUUID,
   230  	})
   231  	err := info.Write()
   232  	c.Assert(err, gc.ErrorMatches, "environment info already exists")
   233  }
   234  
   235  func (s *cacheFileInterfaceSuite) TestList(c *gc.C) {
   236  	// List returns both JENV environments and the cache file environments.
   237  	s.writeEnv(c, "jenv-1", "fake-uuid1", "", "tester", "secret")
   238  	s.writeEnv(c, "jenv-2", "fake-uuid2", "", "tester", "secret")
   239  	s.writeEnv(c, "cache-1", "fake-uuid3", "fake-server", "tester", "secret")
   240  	s.writeEnv(c, "cache-2", "fake-uuid4", "fake-server", "tester", "secret")
   241  
   242  	environments, err := s.store.List()
   243  	c.Assert(err, jc.ErrorIsNil)
   244  	c.Assert(environments, jc.SameContents, []string{"jenv-1", "jenv-2", "cache-1", "cache-2"})
   245  
   246  	// Confirm that the sources are from where we'd expect.
   247  	envDir := filepath.Join(s.dir, "environments")
   248  	c.Assert(configstore.JENVFilename(envDir, "jenv-1"), jc.IsNonEmptyFile)
   249  	c.Assert(configstore.JENVFilename(envDir, "jenv-2"), jc.IsNonEmptyFile)
   250  	cache := s.readCacheFile(c)
   251  	names := make([]string, 0)
   252  	for name := range cache.Environment {
   253  		names = append(names, name)
   254  	}
   255  	c.Assert(names, jc.SameContents, []string{"cache-1", "cache-2"})
   256  }
   257  
   258  func (s *cacheFileInterfaceSuite) TestDestroy(c *gc.C) {
   259  	info := s.writeEnv(c, "cache-1", "fake-uuid", "fake-server", "tester", "secret")
   260  
   261  	err := info.Destroy()
   262  	c.Assert(err, jc.ErrorIsNil)
   263  
   264  	cache := s.readCacheFile(c)
   265  	c.Assert(cache.Server, gc.HasLen, 0)
   266  	c.Assert(cache.ServerData, gc.HasLen, 0)
   267  	c.Assert(cache.Environment, gc.HasLen, 0)
   268  }
   269  
   270  func (s *cacheFileInterfaceSuite) TestDestroyTwice(c *gc.C) {
   271  	info := s.writeEnv(c, "cache-1", "fake-uuid", "fake-server", "tester", "secret")
   272  
   273  	err := info.Destroy()
   274  	c.Assert(err, jc.ErrorIsNil)
   275  	err = info.Destroy()
   276  	c.Assert(err, gc.ErrorMatches, "environment info has already been removed")
   277  }
   278  
   279  func (s *cacheFileInterfaceSuite) TestDestroyKeepsSharedData(c *gc.C) {
   280  	info := s.writeEnv(c, "cache-1", "fake-uuid1", "fake-server", "tester", "secret")
   281  	s.writeEnv(c, "cache-2", "fake-uuid2", "fake-server", "tester", "secret")
   282  
   283  	err := info.Destroy()
   284  	c.Assert(err, jc.ErrorIsNil)
   285  
   286  	cache := s.readCacheFile(c)
   287  	c.Assert(cache.Server, gc.HasLen, 0)
   288  	c.Assert(cache.ServerData, gc.HasLen, 1)
   289  	c.Assert(cache.Environment, gc.HasLen, 1)
   290  }
   291  
   292  func (s *cacheFileInterfaceSuite) TestDestroyServerRemovesEnvironments(c *gc.C) {
   293  	// Bit more setup with this test.
   294  	// Create three server references, to two different systems, so we have
   295  	// one system through two different users.
   296  	info := s.writeEnv(c, "cache-1", "fake-server", "fake-server", "tester", "secret")
   297  	s.writeEnv(c, "cache-2", "fake-server", "fake-server", "other", "secret")
   298  	s.writeEnv(c, "cache-3", "fake-server2", "fake-server2", "tester", "secret")
   299  
   300  	// And a few environments on each server
   301  	s.writeEnv(c, "cache-4", "fake-env-1", "fake-server", "tester", "secret")
   302  	s.writeEnv(c, "cache-5", "fake-env-2", "fake-server", "other", "secret")
   303  	s.writeEnv(c, "cache-6", "fake-env-3", "fake-server2", "tester", "secret")
   304  	s.writeEnv(c, "cache-7", "fake-env-4", "fake-server2", "tester", "secret")
   305  
   306  	err := info.Destroy()
   307  	c.Assert(err, jc.ErrorIsNil)
   308  
   309  	cache := s.readCacheFile(c)
   310  	c.Assert(cache.Server, gc.HasLen, 1)
   311  	c.Assert(cache.ServerData, gc.HasLen, 1)
   312  	expected := []string{"cache-3", "cache-6", "cache-7"}
   313  	names := []string{}
   314  	for name := range cache.Environment {
   315  		names = append(names, name)
   316  	}
   317  	c.Assert(names, jc.SameContents, expected)
   318  }