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") }
func (s *JujuConnSuite) setUpConn(c *gc.C) { if s.RootDir != "" { panic("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = utils.Home() home := filepath.Join(s.RootDir, "/home/ubuntu") err := os.MkdirAll(home, 0777) c.Assert(err, gc.IsNil) utils.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.Config().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...) err = bootstrap.Bootstrap(ctx, environ, bootstrap.BootstrapParams{}) c.Assert(err, gc.IsNil) s.BackingState = environ.(GetStater).GetStateInAPIServer() s.State, err = newState(environ, s.BackingState.MongoConnectionInfo()) c.Assert(err, gc.IsNil) s.APIState, err = juju.NewAPIState(environ, api.DialOpts{}) c.Assert(err, gc.IsNil) s.Environ = environ }
func (s *fakeHomeSuite) TearDownTest(c *gc.C) { s.FakeJujuHomeSuite.TearDownTest(c) // Test that the environment is restored. c.Assert(utils.Home(), gc.Equals, jujuHome) c.Assert(os.Getenv("JUJU_HOME"), gc.Equals, jujuHome) c.Assert(osenv.JujuHome(), gc.Equals, jujuHome) }
func badrun(c *gc.C, exit int, args ...string) string { localArgs := append([]string{"-test.run", "TestRunMain", "-run-main", "--", "juju"}, args...) ps := exec.Command(os.Args[0], localArgs...) ps.Env = append(os.Environ(), osenv.JujuHomeEnvKey+"="+osenv.JujuHome()) output, err := ps.CombinedOutput() c.Logf("command output: %q", output) if exit != 0 { c.Assert(err, gc.ErrorMatches, fmt.Sprintf("exit status %d", exit)) } return string(output) }
func acquireEnvironmentLock(operation string) (*fslock.Lock, error) { // NOTE: any reading or writing from the directory should be done with a // fslock to make sure we have a consistent read or write. Also worth // noting, we should use a very short timeout. lock, err := fslock.NewLock(osenv.JujuHome(), lockName) if err != nil { return nil, errors.Trace(err) } err = lock.LockWithTimeout(lockTimeout, operation) if err != nil { return nil, errors.Trace(err) } return lock, nil }
func (c *toolsMetadataCommand) Run(context *cmd.Context) error { loggo.RegisterWriter("toolsmetadata", cmd.NewCommandLogWriter("juju.environs.tools", context.Stdout, context.Stderr), loggo.INFO) defer loggo.RemoveWriter("toolsmetadata") if c.metadataDir == "" { c.metadataDir = osenv.JujuHome() } else { c.metadataDir = context.AbsPath(c.metadataDir) } sourceStorage, err := filestorage.NewFileStorageReader(c.metadataDir) if err != nil { return err } // We now store the tools in a directory named after their stream, but the // legacy behaviour is to store all tools in a single "releases" directory. toolsDir := c.stream if c.stream == "" { fmt.Fprintf(context.Stdout, "No stream specified, defaulting to released tools in the releases directory.\n") c.stream = envtools.ReleasedStream toolsDir = envtools.LegacyReleaseDirectory } fmt.Fprintf(context.Stdout, "Finding tools in %s for stream %s.\n", c.metadataDir, c.stream) const minorVersion = -1 toolsList, err := envtools.ReadList(sourceStorage, toolsDir, version.Current.Major, minorVersion) if err == envtools.ErrNoTools { var source string source, err = envtools.ToolsURL(envtools.DefaultBaseURL) if err != nil { return err } sourceDataSource := simplestreams.NewURLDataSource("local source", source, utils.VerifySSLHostnames) toolsList, err = envtools.FindToolsForCloud( []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{}, c.stream, version.Current.Major, minorVersion, coretools.Filter{}) } if err != nil { return err } targetStorage, err := filestorage.NewFileStorageWriter(c.metadataDir) if err != nil { return err } writeMirrors := envtools.DoNotWriteMirrors if c.public { writeMirrors = envtools.WriteMirrors } return mergeAndWriteMetadata(targetStorage, toolsDir, c.stream, c.clean, toolsList, writeMirrors) }
func (s *ToolsMetadataSuite) TestPatchLevels(c *gc.C) { currentVersion := version.Current.Number currentVersion.Build = 0 versionStrings := []string{ currentVersion.String() + "-precise-amd64", currentVersion.String() + ".1-precise-amd64", } metadataDir := osenv.JujuHome() // default metadata dir toolstesting.MakeTools(c, metadataDir, "released", versionStrings) ctx := coretesting.Context(c) code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"--stream", "released"}) c.Assert(code, gc.Equals, 0) output := ctx.Stdout.(*bytes.Buffer).String() expectedOutput := fmt.Sprintf(` Finding tools in .* .*Fetching tools from dir "released" to generate hash: %s .*Fetching tools from dir "released" to generate hash: %s .*Writing tools/streams/v1/index2\.json .*Writing tools/streams/v1/index\.json .*Writing tools/streams/v1/com\.ubuntu\.juju-released-tools\.json `[1:], regexp.QuoteMeta(versionStrings[0]), regexp.QuoteMeta(versionStrings[1])) c.Assert(output, gc.Matches, expectedOutput) metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false) c.Assert(metadata, gc.HasLen, 2) filename := fmt.Sprintf("juju-%s-precise-amd64.tgz", currentVersion) size, sha256 := toolstesting.SHA256sum(c, filepath.Join(metadataDir, "tools", "released", filename)) c.Assert(metadata[0], gc.DeepEquals, &tools.ToolsMetadata{ Release: "precise", Version: currentVersion.String(), Arch: "amd64", Size: size, Path: "released/" + filename, FileType: "tar.gz", SHA256: sha256, }) filename = fmt.Sprintf("juju-%s.1-precise-amd64.tgz", currentVersion) size, sha256 = toolstesting.SHA256sum(c, filepath.Join(metadataDir, "tools", "released", filename)) c.Assert(metadata[1], gc.DeepEquals, &tools.ToolsMetadata{ Release: "precise", Version: currentVersion.String() + ".1", Arch: "amd64", Size: size, Path: "released/" + filename, FileType: "tar.gz", SHA256: sha256, }) }
func (s *ToolsMetadataSuite) TestGenerateLegacyRelease(c *gc.C) { metadataDir := osenv.JujuHome() // default metadata dir toolstesting.MakeTools(c, metadataDir, "releases", versionStrings) ctx := coretesting.Context(c) code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, nil) c.Assert(code, gc.Equals, 0) output := ctx.Stdout.(*bytes.Buffer).String() c.Assert(output, gc.Matches, expectedOutputDirectoryLegacyReleased) metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false) c.Assert(metadata, gc.HasLen, len(versionStrings)) obtainedVersionStrings := make([]string, len(versionStrings)) for i, metadata := range metadata { s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch) obtainedVersionStrings[i] = s } c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings) }
func (s *localJujuTestSuite) TestDestroyCallSudo(c *gc.C) { env := s.testBootstrap(c, minimalConfig(c)) s.makeAgentsDir(c, env) err := env.Destroy() c.Assert(err, jc.ErrorIsNil) data, err := ioutil.ReadFile(s.fakesudo + ".args") c.Assert(err, jc.ErrorIsNil) expected := []string{ s.fakesudo, "env", "JUJU_HOME=" + osenv.JujuHome(), os.Args[0], "kill-controller", "-y", env.Config().Name(), } c.Assert(string(data), gc.Equals, strings.Join(expected, " ")+"\n") }
func (c *ToolsMetadataCommand) Run(context *cmd.Context) error { loggo.RegisterWriter("toolsmetadata", cmd.NewCommandLogWriter("juju.environs.tools", context.Stdout, context.Stderr), loggo.INFO) defer loggo.RemoveWriter("toolsmetadata") if c.metadataDir == "" { c.metadataDir = osenv.JujuHome() } else { c.metadataDir = context.AbsPath(c.metadataDir) } sourceStorage, err := filestorage.NewFileStorageReader(c.metadataDir) if err != nil { return err } fmt.Fprintf(context.Stdout, "Finding tools in %s\n", c.metadataDir) const minorVersion = -1 toolsList, err := envtools.ReadList(sourceStorage, version.Current.Major, minorVersion) if err == envtools.ErrNoTools { var source string source, err = envtools.ToolsURL(envtools.DefaultBaseURL) if err != nil { return err } sourceDataSource := simplestreams.NewURLDataSource("local source", source, utils.VerifySSLHostnames) toolsList, err = envtools.FindToolsForCloud( []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{}, version.Current.Major, minorVersion, coretools.Filter{}) } if err != nil { return err } targetStorage, err := filestorage.NewFileStorageWriter(c.metadataDir) if err != nil { return err } writeMirrors := envtools.DoNotWriteMirrors if c.public { writeMirrors = envtools.WriteMirrors } return mergeAndWriteMetadata(targetStorage, toolsList, writeMirrors) }
func (c *PluginCommand) Run(ctx *cmd.Context) error { command := exec.Command(c.name, c.args...) command.Env = append(os.Environ(), []string{ osenv.JujuHomeEnvKey + "=" + osenv.JujuHome(), osenv.JujuEnvEnvKey + "=" + c.ConnectionName()}..., ) // Now hook up stdin, stdout, stderr command.Stdin = ctx.Stdin command.Stdout = ctx.Stdout command.Stderr = ctx.Stderr // And run it! err := command.Run() if exitError, ok := err.(*exec.ExitError); ok && exitError != nil { status := exitError.ProcessState.Sys().(syscall.WaitStatus) if status.Exited() { return cmd.NewRcPassthroughError(status.ExitStatus()) } } return err }
// Destroy is specified in the Environ interface. func (env *localEnviron) Destroy() error { // If bootstrap failed, for example because the user // lacks sudo rights, then the agents won't have been // installed. If that's the case, we can just remove // the data-dir and exit. agentsDir := filepath.Join(env.config.rootDir(), "agents") if _, err := os.Stat(agentsDir); os.IsNotExist(err) { // If we can't remove the root dir, then continue // and attempt as root anyway. if os.RemoveAll(env.config.rootDir()) == nil { return nil } } if !checkIfRoot() { juju, err := exec.LookPath(os.Args[0]) if err != nil { return err } args := []string{ "env", osenv.JujuHomeEnvKey + "=" + osenv.JujuHome(), juju, "kill-controller", "-y", env.Config().Name(), } cmd := exec.Command("sudo", args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } // Kill all running instances. This must be done as // root, or listing/stopping containers will fail. containers, err := env.containerManager.ListContainers() if err != nil { return err } for _, inst := range containers { if err := env.containerManager.DestroyContainer(inst.Id()); err != nil { return err } } uninstallFile := filepath.Join(env.config.rootDir(), agent.UninstallAgentFile) if err := ioutil.WriteFile(uninstallFile, nil, 0644); err != nil { logger.Debugf("could not write uninstall file: %s", err) } cmd := exec.Command( "pkill", fmt.Sprintf("-%d", terminationworker.TerminationSignal), "-f", filepath.Join(regexp.QuoteMeta(env.config.rootDir()), ".*", "jujud"), ) if err := cmd.Run(); err != nil { if err, ok := err.(*exec.ExitError); ok { // Exit status 1 means no processes were matched: // we don't consider this an error here. if err.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() != 1 { return errors.Annotate(err, "failed to kill jujud") } } } // Stop the mongo database and machine agent. We log any errors but // do not fail, so that remaining "destroy" steps will still happen. // // We run through twice, since this races with the agent's teardown. // We only log errors on the second time through, since if an error // occurred, we sould expect it to be due to the service no longer // existing. for i := 0; i < 2; i++ { err = mongoRemoveService(env.config.namespace()) if err != nil && !errors.IsNotFound(err) && i > 0 { logger.Errorf("while stopping mongod: %v", err) } svc, err := discoverService(env.machineAgentServiceName()) if err == nil { if err := svc.Stop(); err != nil && i > 0 { logger.Errorf("while stopping machine agent: %v", err) } if err := svc.Remove(); err != nil && i > 0 { logger.Errorf("while disabling machine agent: %v", err) } } } // Finally, remove the data-dir. if err := os.RemoveAll(env.config.rootDir()); err != nil && !os.IsNotExist(err) { // Before we return the error, just check to see if the directory is // there. There is a race condition with the agent with the removing // of the directory, and due to a bug // (https://code.google.com/p/go/issues/detail?id=7776) the // os.IsNotExist error isn't always returned. if _, statErr := os.Stat(env.config.rootDir()); os.IsNotExist(statErr) { return nil } return err } return nil }
func (s *fakeHomeSuite) TestFakeHomeSetsConfigJujuHome(c *gc.C) { expected := filepath.Join(utils.Home(), ".juju") c.Assert(osenv.JujuHome(), gc.Equals, expected) }
func getCurrentControllerFilePath() string { return filepath.Join(osenv.JujuHome(), CurrentControllerFilename) }
goyaml "gopkg.in/yaml.v1" "github.com/juju/juju/juju/osenv" ) var logger = loggo.GetLogger("juju.environs.configstore") const lockName = "env.lock" // A second should be way more than enough to write or read any files. var lockTimeout = time.Second // Default returns disk-based environment config storage // rooted at JujuHome. var Default = func() (Storage, error) { return NewDisk(osenv.JujuHome()) } type diskStore struct { dir string } // EnvironInfoData is the serialisation structure for the original JENV file. type EnvironInfoData struct { User string Password string EnvironUUID string `json:"environ-uuid,omitempty" yaml:"environ-uuid,omitempty"` StateServers []string `json:"state-servers" yaml:"state-servers"` CACert string `json:"ca-cert" yaml:"ca-cert"` Config map[string]interface{} `json:"bootstrap-config,omitempty" yaml:"bootstrap-config,omitempty"` }
func (m *ovaImportManager) importOva(ecfg *environConfig, instSpec *instanceSpec) (*object.VirtualMachine, error) { folders, err := m.client.datacenter.Folders(context.TODO()) if err != nil { return nil, errors.Trace(err) } basePath, err := ioutil.TempDir(osenv.JujuHome(), "") if err != nil { return nil, errors.Trace(err) } defer func() { if err := os.RemoveAll(basePath); err != nil { logger.Errorf("can't remove temp directory, error: %s", err.Error()) } }() ovf, err := m.downloadOva(basePath, instSpec.img.Url) if err != nil { return nil, errors.Trace(err) } cisp := types.OvfCreateImportSpecParams{ EntityName: instSpec.machineID, PropertyMapping: []types.KeyValue{ types.KeyValue{Key: "public-keys", Value: instSpec.sshKey}, types.KeyValue{Key: "user-data", Value: base64.StdEncoding.EncodeToString(instSpec.userData)}, }, } ovfManager := object.NewOvfManager(m.client.connection.Client) resourcePool := object.NewReference(m.client.connection.Client, *instSpec.zone.r.ResourcePool) datastore := object.NewReference(m.client.connection.Client, instSpec.zone.r.Datastore[0]) spec, err := ovfManager.CreateImportSpec(context.TODO(), string(ovf), resourcePool, datastore, cisp) if err != nil { return nil, errors.Trace(err) } if spec.Error != nil { return nil, errors.New(spec.Error[0].LocalizedMessage) } s := &spec.ImportSpec.(*types.VirtualMachineImportSpec).ConfigSpec s.NumCPUs = int(*instSpec.hwc.CpuCores) s.MemoryMB = int64(*instSpec.hwc.Mem) s.CpuAllocation = &types.ResourceAllocationInfo{ Limit: int64(*instSpec.hwc.CpuPower), Reservation: int64(*instSpec.hwc.CpuPower), } if instSpec.isState { s.ExtraConfig = append(s.ExtraConfig, &types.OptionValue{Key: metadataKeyIsState, Value: metadataValueIsState}) } for _, d := range s.DeviceChange { if disk, ok := d.GetVirtualDeviceConfigSpec().Device.(*types.VirtualDisk); ok { if disk.CapacityInKB < int64(*instSpec.hwc.RootDisk*1024) { disk.CapacityInKB = int64(*instSpec.hwc.RootDisk * 1024) } //Set UnitNumber to -1 if it is unset in ovf file template (in this case it is parces as 0) //but 0 causes an error for disk devices if disk.UnitNumber == 0 { disk.UnitNumber = -1 } } } if ecfg.externalNetwork() != "" { s.DeviceChange = append(s.DeviceChange, &types.VirtualDeviceConfigSpec{ Operation: types.VirtualDeviceConfigSpecOperationAdd, Device: &types.VirtualE1000{ VirtualEthernetCard: types.VirtualEthernetCard{ VirtualDevice: types.VirtualDevice{ Backing: &types.VirtualEthernetCardNetworkBackingInfo{ VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{ DeviceName: ecfg.externalNetwork(), }, }, Connectable: &types.VirtualDeviceConnectInfo{ StartConnected: true, AllowGuestControl: true, }, }, }, }, }) } rp := object.NewResourcePool(m.client.connection.Client, *instSpec.zone.r.ResourcePool) lease, err := rp.ImportVApp(context.TODO(), spec.ImportSpec, folders.VmFolder, nil) if err != nil { return nil, errors.Annotatef(err, "failed to import vapp") } info, err := lease.Wait(context.TODO()) if err != nil { return nil, errors.Trace(err) } items := []ovaFileItem{} for _, device := range info.DeviceUrl { for _, item := range spec.FileItem { if device.ImportKey != item.DeviceId { continue } u, err := m.client.connection.Client.ParseURL(device.Url) if err != nil { return nil, errors.Trace(err) } i := ovaFileItem{ url: u, item: item, ch: make(chan progress.Report), } items = append(items, i) } } for _, i := range items { err = m.uploadImage(i, basePath) if err != nil { return nil, errors.Trace(err) } } lease.HttpNfcLeaseComplete(context.TODO()) return object.NewVirtualMachine(m.client.connection.Client, info.Entity), nil }
func (s *JujuConnSuite) setUpConn(c *gc.C) { if s.RootDir != "" { panic("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = utils.Home() home := filepath.Join(s.RootDir, "/home/ubuntu") err := os.MkdirAll(home, 0777) c.Assert(err, jc.ErrorIsNil) utils.SetHome(home) s.oldJujuHome = osenv.SetJujuHome(filepath.Join(home, ".juju")) err = os.Mkdir(osenv.JujuHome(), 0777) c.Assert(err, jc.ErrorIsNil) err = os.MkdirAll(s.DataDir(), 0777) c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) err = ioutil.WriteFile(osenv.JujuHomePath("dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) c.Assert(err, jc.ErrorIsNil) store, err := configstore.Default() c.Assert(err, jc.ErrorIsNil) s.ConfigStore = store ctx := testing.Context(c) environ, err := environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(ctx), s.ConfigStore) c.Assert(err, jc.ErrorIsNil) // sanity check we've got the correct environment. c.Assert(environ.Config().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 s.DefaultToolsStorageDir = c.MkDir() s.PatchValue(&tools.DefaultBaseURL, s.DefaultToolsStorageDir) stor, err := filestorage.NewFileStorageWriter(s.DefaultToolsStorageDir) c.Assert(err, jc.ErrorIsNil) // Upload tools to both release and devel streams since config will dictate that we // end up looking in both places. envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", versions...) envtesting.AssertUploadFakeToolsVersions(c, stor, "devel", "devel", versions...) s.DefaultToolsStorage = stor err = bootstrap.Bootstrap(envcmd.BootstrapContext(ctx), environ, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) s.BackingState = environ.(GetStater).GetStateInAPIServer() s.State, err = newState(environ, s.BackingState.MongoConnectionInfo()) c.Assert(err, jc.ErrorIsNil) s.APIState, err = juju.NewAPIState(s.AdminUserTag(c), environ, api.DialOpts{}) c.Assert(err, jc.ErrorIsNil) err = s.State.SetAPIHostPorts(s.APIState.APIHostPorts()) c.Assert(err, jc.ErrorIsNil) // Make sure the config store has the api endpoint address set info, err := s.ConfigStore.ReadInfo("dummyenv") c.Assert(err, jc.ErrorIsNil) endpoint := info.APIEndpoint() endpoint.Addresses = []string{s.APIState.APIHostPorts()[0][0].String()} info.SetAPIEndpoint(endpoint) err = info.Write() c.Assert(err, jc.ErrorIsNil) // Make sure the jenv file has the local host ports. c.Logf("jenv host ports: %#v", s.APIState.APIHostPorts()) s.Environ = environ // Insert expected values... servingInfo := state.StateServingInfo{ PrivateKey: testing.ServerKey, Cert: testing.ServerCert, CAPrivateKey: testing.CAKey, SharedSecret: "really, really secret", APIPort: 4321, StatePort: 1234, } s.State.SetStateServingInfo(servingInfo) }
func getCurrentSystemFilePath() string { return filepath.Join(osenv.JujuHome(), CurrentSystemFilename) }
func getCurrentEnvironmentFilePath() string { return filepath.Join(osenv.JujuHome(), CurrentEnvironmentFilename) }
// Default returns disk-based environment config storage // rooted at JujuHome. func Default() (Storage, error) { return NewDisk(osenv.JujuHome()) }
func (s *JujuHomeSuite) TestStandardHome(c *gc.C) { testJujuHome := c.MkDir() defer osenv.SetJujuHome(osenv.SetJujuHome(testJujuHome)) c.Assert(osenv.JujuHome(), gc.Equals, testJujuHome) }