github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/testing/environ.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package testing
     5  
     6  import (
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	gc "launchpad.net/gocheck"
    12  
    13  	"launchpad.net/juju-core/environs/config"
    14  	"launchpad.net/juju-core/juju/osenv"
    15  	"launchpad.net/juju-core/testing/testbase"
    16  	"launchpad.net/juju-core/utils/ssh"
    17  )
    18  
    19  // FakeAuthKeys holds the authorized key used for testing
    20  // purposes in FakeConfig. It is valid for parsing with the utils/ssh
    21  // authorized-key utilities.
    22  const FakeAuthKeys = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQDP8fPSAMFm2PQGoVUks/FENVUMww1QTK6m++Y2qX9NGHm43kwEzxfoWR77wo6fhBhgFHsQ6ogE/cYLx77hOvjTchMEP74EVxSce0qtDjI7SwYbOpAButRId3g/Ef4STz8= joe@0.1.2.4`
    23  
    24  func init() {
    25  	_, err := ssh.ParseAuthorisedKey(FakeAuthKeys)
    26  	if err != nil {
    27  		panic("FakeAuthKeys does not hold a valid authorized key: " + err.Error())
    28  	}
    29  }
    30  
    31  // FakeConfig() returns an environment configuration for a
    32  // fake provider with all required attributes set.
    33  func FakeConfig() Attrs {
    34  	return Attrs{
    35  		"type":                      "someprovider",
    36  		"name":                      "testenv",
    37  		"authorized-keys":           FakeAuthKeys,
    38  		"firewall-mode":             config.FwInstance,
    39  		"admin-secret":              "fish",
    40  		"ca-cert":                   CACert,
    41  		"ca-private-key":            CAKey,
    42  		"ssl-hostname-verification": true,
    43  		"development":               false,
    44  		"state-port":                19034,
    45  		"api-port":                  17777,
    46  		"default-series":            config.DefaultSeries,
    47  	}
    48  }
    49  
    50  // EnvironConfig returns a default environment configuration suitable for
    51  // setting in the state.
    52  func EnvironConfig(c *gc.C) *config.Config {
    53  	return CustomEnvironConfig(c, Attrs{})
    54  }
    55  
    56  // CustomEnvironConfig returns an environment configuration with
    57  // additional specified keys added.
    58  func CustomEnvironConfig(c *gc.C, extra Attrs) *config.Config {
    59  	attrs := FakeConfig().Merge(Attrs{
    60  		"agent-version": "1.2.3",
    61  	}).Merge(extra).Delete("admin-secret", "ca-private-key")
    62  	cfg, err := config.New(config.NoDefaults, attrs)
    63  	c.Assert(err, gc.IsNil)
    64  	return cfg
    65  }
    66  
    67  const (
    68  	SampleEnvName = "erewhemos"
    69  	EnvDefault    = "default:\n  " + SampleEnvName + "\n"
    70  )
    71  
    72  const DefaultMongoPassword = "conn-from-name-secret"
    73  
    74  // Environment names below are explicit as it makes them more readable.
    75  const SingleEnvConfigNoDefault = `
    76  environments:
    77      erewhemos:
    78          type: dummy
    79          state-server: true
    80          authorized-keys: i-am-a-key
    81          admin-secret: ` + DefaultMongoPassword + `
    82  `
    83  
    84  const SingleEnvConfig = EnvDefault + SingleEnvConfigNoDefault
    85  
    86  const MultipleEnvConfigNoDefault = `
    87  environments:
    88      erewhemos:
    89          type: dummy
    90          state-server: true
    91          authorized-keys: i-am-a-key
    92          admin-secret: ` + DefaultMongoPassword + `
    93      erewhemos-2:
    94          type: dummy
    95          state-server: true
    96          authorized-keys: i-am-a-key
    97          admin-secret: ` + DefaultMongoPassword + `
    98  `
    99  
   100  const MultipleEnvConfig = EnvDefault + MultipleEnvConfigNoDefault
   101  
   102  const SampleCertName = "erewhemos"
   103  
   104  type TestFile struct {
   105  	Name, Data string
   106  }
   107  
   108  type FakeHome struct {
   109  	oldHomeEnv     string
   110  	oldEnvironment map[string]string
   111  	oldJujuHome    string
   112  	files          []TestFile
   113  }
   114  
   115  // MakeFakeHomeNoEnvironments creates a new temporary directory through the
   116  // test checker, and overrides the HOME environment variable to point to this
   117  // new temporary directory.
   118  //
   119  // No ~/.juju/environments.yaml exists, but CAKeys are written for each of the
   120  // 'certNames' specified, and the id_rsa.pub file is written to to the .ssh
   121  // dir.
   122  func MakeFakeHomeNoEnvironments(c *gc.C, certNames ...string) *FakeHome {
   123  	fake := MakeEmptyFakeHome(c)
   124  
   125  	for _, name := range certNames {
   126  		err := ioutil.WriteFile(osenv.JujuHomePath(name+"-cert.pem"), []byte(CACert), 0600)
   127  		c.Assert(err, gc.IsNil)
   128  		err = ioutil.WriteFile(osenv.JujuHomePath(name+"-private-key.pem"), []byte(CAKey), 0600)
   129  		c.Assert(err, gc.IsNil)
   130  	}
   131  
   132  	err := os.Mkdir(HomePath(".ssh"), 0777)
   133  	c.Assert(err, gc.IsNil)
   134  	err = ioutil.WriteFile(HomePath(".ssh", "id_rsa.pub"), []byte("auth key\n"), 0666)
   135  	c.Assert(err, gc.IsNil)
   136  
   137  	return fake
   138  }
   139  
   140  // MakeFakeHome creates a new temporary directory through the test checker,
   141  // and overrides the HOME environment variable to point to this new temporary
   142  // directory.
   143  //
   144  // A new ~/.juju/environments.yaml file is created with the content of the
   145  // `envConfig` parameter, and CAKeys are written for each of the 'certNames'
   146  // specified.
   147  func MakeFakeHome(c *gc.C, envConfig string, certNames ...string) *FakeHome {
   148  	fake := MakeFakeHomeNoEnvironments(c, certNames...)
   149  
   150  	envs := osenv.JujuHomePath("environments.yaml")
   151  	err := ioutil.WriteFile(envs, []byte(envConfig), 0644)
   152  	c.Assert(err, gc.IsNil)
   153  
   154  	return fake
   155  }
   156  
   157  func MakeEmptyFakeHome(c *gc.C) *FakeHome {
   158  	fake := MakeEmptyFakeHomeWithoutJuju(c)
   159  	err := os.Mkdir(osenv.JujuHome(), 0700)
   160  	c.Assert(err, gc.IsNil)
   161  	return fake
   162  }
   163  
   164  func MakeEmptyFakeHomeWithoutJuju(c *gc.C) *FakeHome {
   165  	oldHomeEnv := osenv.Home()
   166  	oldEnvironment := make(map[string]string)
   167  	for _, name := range []string{
   168  		osenv.JujuHomeEnvKey,
   169  		osenv.JujuEnvEnvKey,
   170  		osenv.JujuLoggingConfigEnvKey,
   171  	} {
   172  		oldEnvironment[name] = os.Getenv(name)
   173  	}
   174  	fakeHome := c.MkDir()
   175  	osenv.SetHome(fakeHome)
   176  	os.Setenv(osenv.JujuHomeEnvKey, "")
   177  	os.Setenv(osenv.JujuEnvEnvKey, "")
   178  	os.Setenv(osenv.JujuLoggingConfigEnvKey, "")
   179  	jujuHome := filepath.Join(fakeHome, ".juju")
   180  	oldJujuHome := osenv.SetJujuHome(jujuHome)
   181  	return &FakeHome{
   182  		oldHomeEnv:     oldHomeEnv,
   183  		oldEnvironment: oldEnvironment,
   184  		oldJujuHome:    oldJujuHome,
   185  		files:          []TestFile{},
   186  	}
   187  }
   188  
   189  func HomePath(names ...string) string {
   190  	all := append([]string{osenv.Home()}, names...)
   191  	return filepath.Join(all...)
   192  }
   193  
   194  func (h *FakeHome) Restore() {
   195  	osenv.SetJujuHome(h.oldJujuHome)
   196  	for name, value := range h.oldEnvironment {
   197  		os.Setenv(name, value)
   198  	}
   199  	osenv.SetHome(h.oldHomeEnv)
   200  }
   201  
   202  func (h *FakeHome) AddFiles(c *gc.C, files []TestFile) {
   203  	for _, f := range files {
   204  		path := HomePath(f.Name)
   205  		err := os.MkdirAll(filepath.Dir(path), 0700)
   206  		c.Assert(err, gc.IsNil)
   207  		err = ioutil.WriteFile(path, []byte(f.Data), 0666)
   208  		c.Assert(err, gc.IsNil)
   209  		h.files = append(h.files, f)
   210  	}
   211  }
   212  
   213  // FileContents returns the test file contents for the
   214  // given specified path (which may be relative, so
   215  // we compare with the base filename only).
   216  func (h *FakeHome) FileContents(c *gc.C, path string) string {
   217  	for _, f := range h.files {
   218  		if filepath.Base(f.Name) == filepath.Base(path) {
   219  			return f.Data
   220  		}
   221  	}
   222  	c.Fatalf("path attribute holds unknown test file: %q", path)
   223  	panic("unreachable")
   224  }
   225  
   226  // FileExists returns if the given relative file path exists
   227  // in the fake home.
   228  func (h *FakeHome) FileExists(path string) bool {
   229  	for _, f := range h.files {
   230  		if f.Name == path {
   231  			return true
   232  		}
   233  	}
   234  	return false
   235  }
   236  
   237  func MakeFakeHomeWithFiles(c *gc.C, files []TestFile) *FakeHome {
   238  	fake := MakeEmptyFakeHome(c)
   239  	fake.AddFiles(c, files)
   240  	return fake
   241  }
   242  
   243  func MakeSampleHome(c *gc.C) *FakeHome {
   244  	return MakeFakeHome(c, SingleEnvConfig, SampleCertName)
   245  }
   246  
   247  func MakeMultipleEnvHome(c *gc.C) *FakeHome {
   248  	return MakeFakeHome(c, MultipleEnvConfig, SampleCertName, SampleCertName+"-2")
   249  }
   250  
   251  type FakeHomeSuite struct {
   252  	testbase.LoggingSuite
   253  	Home *FakeHome
   254  }
   255  
   256  func (s *FakeHomeSuite) SetUpTest(c *gc.C) {
   257  	s.LoggingSuite.SetUpTest(c)
   258  	s.Home = MakeSampleHome(c)
   259  	s.AddCleanup(func(*gc.C) { s.Home.Restore() })
   260  }