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  }