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) }
// SyncTools copies the Juju tools tarball from the official bucket // or a specified source directory into the user's environment. func SyncTools(syncContext *SyncContext) error { sourceDataSource, err := selectSourceDatasource(syncContext) if err != nil { return err } logger.Infof("listing available tools") if syncContext.MajorVersion == 0 && syncContext.MinorVersion == 0 { syncContext.MajorVersion = version.Current.Major syncContext.MinorVersion = -1 if !syncContext.AllVersions { syncContext.MinorVersion = version.Current.Minor } } else if !syncContext.Dev && syncContext.MinorVersion != -1 { // If a major.minor version is specified, we allow dev versions. // If Dev is already true, leave it alone. syncContext.Dev = true } released := !syncContext.Dev && !version.Current.IsDev() sourceTools, err := envtools.FindToolsForCloud( []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{}, syncContext.MajorVersion, syncContext.MinorVersion, coretools.Filter{Released: released}) if err != nil { return err } logger.Infof("found %d tools", len(sourceTools)) if !syncContext.AllVersions { var latest version.Number latest, sourceTools = sourceTools.Newest() logger.Infof("found %d recent tools (version %s)", len(sourceTools), latest) } for _, tool := range sourceTools { logger.Debugf("found source tool: %v", tool) } logger.Infof("listing target tools storage") targetStorage := syncContext.Target targetTools, err := envtools.ReadList(targetStorage, syncContext.MajorVersion, -1) switch err { case nil, coretools.ErrNoMatches, envtools.ErrNoTools: default: return err } for _, tool := range targetTools { logger.Debugf("found target tool: %v", tool) } missing := sourceTools.Exclude(targetTools) logger.Infof("found %d tools in target; %d tools to be copied", len(targetTools), len(missing)) err = copyTools(missing, syncContext, targetStorage) if err != nil { return err } logger.Infof("copied %d tools", len(missing)) logger.Infof("generating tools metadata") if !syncContext.DryRun { targetTools = append(targetTools, missing...) writeMirrors := envtools.DoNotWriteMirrors if syncContext.Public { writeMirrors = envtools.WriteMirrors } err = envtools.MergeAndWriteMetadata(targetStorage, targetTools, writeMirrors) if err != nil { return err } } logger.Infof("tools metadata written") return nil }