// InitJujuHome initializes the charm, environs/config and utils/ssh packages // to use default paths based on the $JUJU_HOME or $HOME environment variables. // This function should be called before calling NewConn or Conn.Deploy. func InitJujuHome() error { jujuHome := osenv.JujuHomeDir() if jujuHome == "" { return stderrors.New( "cannot determine juju home, required environment variables are not set") } osenv.SetJujuHome(jujuHome) charm.CacheDir = osenv.JujuHomePath("charmcache") if err := ssh.LoadClientKeys(osenv.JujuHomePath("ssh")); err != nil { return fmt.Errorf("cannot load ssh client keys: %v", err) } return nil }
func (s *JujuHomeSuite) TestErrorHome(c *gc.C) { // Invalid juju home leads to panic when retrieving. f := func() { _ = osenv.JujuHome() } c.Assert(f, gc.PanicMatches, "juju home hasn't been initialized") f = func() { _ = osenv.JujuHomePath("environments.yaml") } c.Assert(f, gc.PanicMatches, "juju home hasn't been initialized") }
// maybeReadAttrFromFile sets defined[attr] to: // // 1) The content of the file defined[attr+"-path"], if that's set // 2) The value of defined[attr] if it is already set. // 3) The content of defaultPath if it exists and defined[attr] is unset // 4) Preserves the content of defined[attr], otherwise // // The defined[attr+"-path"] key is always deleted. func maybeReadAttrFromFile(defined map[string]interface{}, attr, defaultPath string) error { pathAttr := attr + "-path" path, _ := defined[pathAttr].(string) delete(defined, pathAttr) hasPath := path != "" if !hasPath { // No path and attribute is already set; leave it be. if s, _ := defined[attr].(string); s != "" { return nil } path = defaultPath } path, err := utils.NormalizePath(path) if err != nil { return err } if !filepath.IsAbs(path) { path = osenv.JujuHomePath(path) } data, err := ioutil.ReadFile(path) if err != nil { if os.IsNotExist(err) && !hasPath { // If the default path isn't found, it's // not an error. return nil } return err } if len(data) == 0 { return fmt.Errorf("file %q is empty", path) } defined[attr] = string(data) return nil }
// MakeFakeHomeNoEnvironments creates a new temporary directory through the // test checker, and overrides the HOME environment variable to point to this // new temporary directory. // // No ~/.juju/environments.yaml exists, but CAKeys are written for each of the // 'certNames' specified, and the id_rsa.pub file is written to to the .ssh // dir. func MakeFakeHomeNoEnvironments(c *gc.C, certNames ...string) *FakeHome { fake := MakeEmptyFakeHome(c) for _, name := range certNames { err := ioutil.WriteFile(osenv.JujuHomePath(name+"-cert.pem"), []byte(CACert), 0600) c.Assert(err, gc.IsNil) err = ioutil.WriteFile(osenv.JujuHomePath(name+"-private-key.pem"), []byte(CAKey), 0600) c.Assert(err, gc.IsNil) } err := os.Mkdir(HomePath(".ssh"), 0777) c.Assert(err, gc.IsNil) err = ioutil.WriteFile(HomePath(".ssh", "id_rsa.pub"), []byte("auth key\n"), 0666) c.Assert(err, gc.IsNil) return fake }
// MakeFakeHome creates a new temporary directory through the test checker, // and overrides the HOME environment variable to point to this new temporary // directory. // // A new ~/.juju/environments.yaml file is created with the content of the // `envConfig` parameter, and CAKeys are written for each of the 'certNames' // specified. func MakeFakeHome(c *gc.C, envConfig string, certNames ...string) *FakeHome { fake := MakeFakeHomeNoEnvironments(c, certNames...) envs := osenv.JujuHomePath("environments.yaml") err := ioutil.WriteFile(envs, []byte(envConfig), 0644) c.Assert(err, gc.IsNil) return fake }
// WriteConfig writes a juju config file to the "home" directory. func (s *JujuConnSuite) WriteConfig(configData string) { if s.RootDir == "" { panic("SetUpTest has not been called; will not overwrite $JUJU_HOME/environments.yaml") } path := osenv.JujuHomePath("environments.yaml") err := ioutil.WriteFile(path, []byte(configData), 0600) if err != nil { panic(err) } }
func (*NewAPIClientSuite) TestWithBootstrapConfigAndNoEnvironmentsFile(c *gc.C) { defer coretesting.MakeSampleHome(c).Restore() store := configstore.NewMem() bootstrapEnv(c, coretesting.SampleEnvName, store) info, err := store.ReadInfo(coretesting.SampleEnvName) c.Assert(err, gc.IsNil) c.Assert(info.BootstrapConfig(), gc.NotNil) c.Assert(info.APIEndpoint().Addresses, gc.HasLen, 0) err = os.Remove(osenv.JujuHomePath("environments.yaml")) c.Assert(err, gc.IsNil) apiOpen := func(*api.Info, api.DialOpts) (juju.APIState, error) { return &mockAPIState{}, nil } st, err := juju.NewAPIFromStore(coretesting.SampleEnvName, store, apiOpen) c.Check(err, gc.IsNil) st.Close() }
func (s *JujuHomeSuite) TestHomePath(c *gc.C) { testJujuHome := c.MkDir() defer osenv.SetJujuHome(osenv.SetJujuHome(testJujuHome)) envPath := osenv.JujuHomePath("environments.yaml") c.Assert(envPath, gc.Equals, filepath.Join(testJujuHome, "environments.yaml")) }
func (s *JujuConnSuite) setUpConn(c *gc.C) { if s.RootDir != "" { panic("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = osenv.Home() home := filepath.Join(s.RootDir, "/home/ubuntu") err := os.MkdirAll(home, 0777) c.Assert(err, gc.IsNil) osenv.SetHome(home) s.oldJujuHome = osenv.SetJujuHome(filepath.Join(home, ".juju")) err = os.Mkdir(osenv.JujuHome(), 0777) c.Assert(err, gc.IsNil) err = os.MkdirAll(s.DataDir(), 0777) c.Assert(err, gc.IsNil) s.PatchEnvironment(osenv.JujuEnvEnvKey, "") // TODO(rog) remove these files and add them only when // the tests specifically need them (in cmd/juju for example) s.writeSampleConfig(c, osenv.JujuHomePath("environments.yaml")) err = ioutil.WriteFile(osenv.JujuHomePath("dummyenv-cert.pem"), []byte(testing.CACert), 0666) c.Assert(err, gc.IsNil) err = ioutil.WriteFile(osenv.JujuHomePath("dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) c.Assert(err, gc.IsNil) store, err := configstore.Default() c.Assert(err, gc.IsNil) s.ConfigStore = store ctx := testing.Context(c) environ, err := environs.PrepareFromName("dummyenv", ctx, s.ConfigStore) c.Assert(err, gc.IsNil) // sanity check we've got the correct environment. c.Assert(environ.Name(), gc.Equals, "dummyenv") s.PatchValue(&dummy.DataDir, s.DataDir()) s.LogDir = c.MkDir() s.PatchValue(&dummy.LogDir, s.LogDir) versions := PreferredDefaultVersions(environ.Config(), version.Binary{Number: version.Current.Number, Series: "precise", Arch: "amd64"}) versions = append(versions, version.Current) // Upload tools for both preferred and fake default series envtesting.MustUploadFakeToolsVersions(environ.Storage(), versions...) c.Assert(bootstrap.Bootstrap(ctx, environ, environs.BootstrapParams{}), gc.IsNil) s.BackingState = environ.(GetStater).GetStateInAPIServer() conn, err := juju.NewConn(environ) c.Assert(err, gc.IsNil) s.Conn = conn s.State = conn.State apiConn, err := juju.NewAPIConn(environ, api.DialOpts{}) c.Assert(err, gc.IsNil) s.APIConn = apiConn s.APIState = apiConn.State s.environ = environ }
// breakJuju writes a dummy environment with incomplete configuration. // environMethod is called. func breakJuju(c *gc.C, environMethod string) (msg string) { path := osenv.JujuHomePath("environments.yaml") err := ioutil.WriteFile(path, []byte(brokenConfig), 0666) c.Assert(err, gc.IsNil) return `cannot parse "[^"]*": YAML error.*` }
// Validate implements environs.EnvironProvider.Validate. func (provider environProvider) Validate(cfg, old *config.Config) (valid *config.Config, err error) { // Check for valid changes for the base config values. if err := config.Validate(cfg, old); err != nil { return nil, err } validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) if err != nil { return nil, fmt.Errorf("failed to validate unknown attrs: %v", err) } localConfig := newEnvironConfig(cfg, validated) // Before potentially creating directories, make sure that the // root directory has not changed. containerType := localConfig.container() if old != nil { oldLocalConfig, err := provider.newConfig(old) if err != nil { return nil, fmt.Errorf("old config is not a valid local config: %v", old) } if containerType != oldLocalConfig.container() { return nil, fmt.Errorf("cannot change container from %q to %q", oldLocalConfig.container(), containerType) } if localConfig.rootDir() != oldLocalConfig.rootDir() { return nil, fmt.Errorf("cannot change root-dir from %q to %q", oldLocalConfig.rootDir(), localConfig.rootDir()) } if localConfig.networkBridge() != oldLocalConfig.networkBridge() { return nil, fmt.Errorf("cannot change network-bridge from %q to %q", oldLocalConfig.rootDir(), localConfig.rootDir()) } if localConfig.storagePort() != oldLocalConfig.storagePort() { return nil, fmt.Errorf("cannot change storage-port from %v to %v", oldLocalConfig.storagePort(), localConfig.storagePort()) } } // Currently only supported containers are "lxc" and "kvm". if containerType != instance.LXC && containerType != instance.KVM { return nil, fmt.Errorf("unsupported container type: %q", containerType) } dir, err := utils.NormalizePath(localConfig.rootDir()) if err != nil { return nil, err } if dir == "." { dir = osenv.JujuHomePath(cfg.Name()) } // Always assign the normalized path. localConfig.attrs["root-dir"] = dir if containerType != instance.KVM { fastOptionAvailable := useFastLXC(containerType) if _, found := localConfig.attrs["lxc-clone"]; !found { localConfig.attrs["lxc-clone"] = fastOptionAvailable } } // Apply the coerced unknown values back into the config. return cfg.Apply(localConfig.attrs) }
func environsPath(path string) string { if path == "" { path = osenv.JujuHomePath("environments.yaml") } return path }