launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 "net/url" 9 "path" 10 "strings" 11 12 "github.com/loggo/loggo" 13 "launchpad.net/gnuflag" 14 15 "launchpad.net/juju-core/cmd" 16 "launchpad.net/juju-core/environs/filestorage" 17 "launchpad.net/juju-core/environs/simplestreams" 18 "launchpad.net/juju-core/environs/storage" 19 envtools "launchpad.net/juju-core/environs/tools" 20 "launchpad.net/juju-core/juju/osenv" 21 coretools "launchpad.net/juju-core/tools" 22 "launchpad.net/juju-core/version" 23 ) 24 25 // ToolsMetadataCommand is used to generate simplestreams metadata for juju tools. 26 type ToolsMetadataCommand struct { 27 cmd.EnvCommandBase 28 fetch bool 29 metadataDir string 30 public bool 31 } 32 33 func (c *ToolsMetadataCommand) Info() *cmd.Info { 34 return &cmd.Info{ 35 Name: "generate-tools", 36 Purpose: "generate simplestreams tools metadata", 37 } 38 } 39 40 func (c *ToolsMetadataCommand) SetFlags(f *gnuflag.FlagSet) { 41 c.EnvCommandBase.SetFlags(f) 42 f.StringVar(&c.metadataDir, "d", "", "local directory in which to store metadata") 43 f.BoolVar(&c.public, "public", false, "tools are for a public cloud, so generate mirrors information") 44 } 45 46 func (c *ToolsMetadataCommand) Run(context *cmd.Context) error { 47 loggo.RegisterWriter("toolsmetadata", cmd.NewCommandLogWriter("juju.environs.tools", context.Stdout, context.Stderr), loggo.INFO) 48 defer loggo.RemoveWriter("toolsmetadata") 49 if c.metadataDir == "" { 50 c.metadataDir = osenv.JujuHome() 51 } else { 52 c.metadataDir = context.AbsPath(c.metadataDir) 53 } 54 55 sourceStorage, err := filestorage.NewFileStorageReader(c.metadataDir) 56 if err != nil { 57 return err 58 } 59 fmt.Fprintf(context.Stdout, "Finding tools in %s\n", c.metadataDir) 60 const minorVersion = -1 61 toolsList, err := envtools.ReadList(sourceStorage, version.Current.Major, minorVersion) 62 if err == envtools.ErrNoTools { 63 source := envtools.DefaultBaseURL 64 var u *url.URL 65 u, err = url.Parse(source) 66 if err != nil { 67 return fmt.Errorf("invalid tools source %s: %v", source, err) 68 } 69 if u.Scheme == "" { 70 source = "file://" + source 71 if !strings.HasSuffix(source, "/"+storage.BaseToolsPath) { 72 source = path.Join(source, storage.BaseToolsPath) 73 } 74 } 75 sourceDataSource := simplestreams.NewURLDataSource(source, simplestreams.VerifySSLHostnames) 76 toolsList, err = envtools.FindToolsForCloud( 77 []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{}, 78 version.Current.Major, minorVersion, coretools.Filter{}) 79 } 80 if err != nil { 81 return err 82 } 83 84 targetStorage, err := filestorage.NewFileStorageWriter(c.metadataDir, filestorage.UseDefaultTmpDir) 85 if err != nil { 86 return err 87 } 88 writeMirrors := envtools.DoNotWriteMirrors 89 if c.public { 90 writeMirrors = envtools.WriteMirrors 91 } 92 return mergeAndWriteMetadata(targetStorage, toolsList, writeMirrors) 93 } 94 95 // This is essentially the same as tools.MergeAndWriteMetadata, but also 96 // resolves metadata for existing tools by fetching them and computing 97 // size/sha256 locally. 98 func mergeAndWriteMetadata(stor storage.Storage, toolsList coretools.List, writeMirrors envtools.ShouldWriteMirrors) error { 99 existing, err := envtools.ReadMetadata(stor) 100 if err != nil { 101 return err 102 } 103 metadata := envtools.MetadataFromTools(toolsList) 104 if metadata, err = envtools.MergeMetadata(metadata, existing); err != nil { 105 return err 106 } 107 if err = envtools.ResolveMetadata(stor, metadata); err != nil { 108 return err 109 } 110 return envtools.WriteMetadata(stor, metadata, writeMirrors) 111 }