github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/plugins/juju-metadata/toolsmetadata.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 9 "github.com/juju/loggo" 10 "github.com/juju/utils" 11 "launchpad.net/gnuflag" 12 13 "github.com/juju/juju/cmd" 14 "github.com/juju/juju/cmd/envcmd" 15 "github.com/juju/juju/environs/filestorage" 16 "github.com/juju/juju/environs/simplestreams" 17 "github.com/juju/juju/environs/storage" 18 envtools "github.com/juju/juju/environs/tools" 19 "github.com/juju/juju/juju/osenv" 20 coretools "github.com/juju/juju/tools" 21 "github.com/juju/juju/version" 22 ) 23 24 // ToolsMetadataCommand is used to generate simplestreams metadata for juju tools. 25 type ToolsMetadataCommand struct { 26 envcmd.EnvCommandBase 27 fetch bool 28 metadataDir string 29 public bool 30 } 31 32 func (c *ToolsMetadataCommand) Info() *cmd.Info { 33 return &cmd.Info{ 34 Name: "generate-tools", 35 Purpose: "generate simplestreams tools metadata", 36 } 37 } 38 39 func (c *ToolsMetadataCommand) SetFlags(f *gnuflag.FlagSet) { 40 f.StringVar(&c.metadataDir, "d", "", "local directory in which to store metadata") 41 f.BoolVar(&c.public, "public", false, "tools are for a public cloud, so generate mirrors information") 42 } 43 44 func (c *ToolsMetadataCommand) Run(context *cmd.Context) error { 45 loggo.RegisterWriter("toolsmetadata", cmd.NewCommandLogWriter("juju.environs.tools", context.Stdout, context.Stderr), loggo.INFO) 46 defer loggo.RemoveWriter("toolsmetadata") 47 if c.metadataDir == "" { 48 c.metadataDir = osenv.JujuHome() 49 } else { 50 c.metadataDir = context.AbsPath(c.metadataDir) 51 } 52 53 sourceStorage, err := filestorage.NewFileStorageReader(c.metadataDir) 54 if err != nil { 55 return err 56 } 57 fmt.Fprintf(context.Stdout, "Finding tools in %s\n", c.metadataDir) 58 const minorVersion = -1 59 toolsList, err := envtools.ReadList(sourceStorage, version.Current.Major, minorVersion) 60 if err == envtools.ErrNoTools { 61 var source string 62 source, err = envtools.ToolsURL(envtools.DefaultBaseURL) 63 if err != nil { 64 return err 65 } 66 sourceDataSource := simplestreams.NewURLDataSource("local source", source, utils.VerifySSLHostnames) 67 toolsList, err = envtools.FindToolsForCloud( 68 []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{}, 69 version.Current.Major, minorVersion, coretools.Filter{}) 70 } 71 if err != nil { 72 return err 73 } 74 75 targetStorage, err := filestorage.NewFileStorageWriter(c.metadataDir) 76 if err != nil { 77 return err 78 } 79 writeMirrors := envtools.DoNotWriteMirrors 80 if c.public { 81 writeMirrors = envtools.WriteMirrors 82 } 83 return mergeAndWriteMetadata(targetStorage, toolsList, writeMirrors) 84 } 85 86 // This is essentially the same as tools.MergeAndWriteMetadata, but also 87 // resolves metadata for existing tools by fetching them and computing 88 // size/sha256 locally. 89 func mergeAndWriteMetadata(stor storage.Storage, toolsList coretools.List, writeMirrors envtools.ShouldWriteMirrors) error { 90 existing, err := envtools.ReadMetadata(stor) 91 if err != nil { 92 return err 93 } 94 metadata := envtools.MetadataFromTools(toolsList) 95 if metadata, err = envtools.MergeMetadata(metadata, existing); err != nil { 96 return err 97 } 98 if err = envtools.ResolveMetadata(stor, metadata); err != nil { 99 return err 100 } 101 return envtools.WriteMetadata(stor, metadata, writeMirrors) 102 }