github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/environs/tools/storage.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package tools
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/juju/utils/arch"
    13  	"github.com/juju/version"
    14  
    15  	"github.com/juju/juju/environs/storage"
    16  	coretools "github.com/juju/juju/tools"
    17  )
    18  
    19  var ErrNoTools = errors.New("no tools available")
    20  
    21  const (
    22  	toolPrefix = "tools/%s/juju-"
    23  	toolSuffix = ".tgz"
    24  )
    25  
    26  // StorageName returns the name that is used to store and retrieve the
    27  // given version of the juju tools.
    28  func StorageName(vers version.Binary, stream string) string {
    29  	return storagePrefix(stream) + vers.String() + toolSuffix
    30  }
    31  
    32  func storagePrefix(stream string) string {
    33  	return fmt.Sprintf(toolPrefix, stream)
    34  }
    35  
    36  // ReadList returns a List of the tools in store with the given major.minor version.
    37  // If minorVersion = -1, then only majorVersion is considered.
    38  // If majorVersion is -1, then all tools tarballs are used.
    39  // If store contains no such tools, it returns ErrNoMatches.
    40  func ReadList(stor storage.StorageReader, toolsDir string, majorVersion, minorVersion int) (coretools.List, error) {
    41  	if minorVersion >= 0 {
    42  		logger.Debugf("reading v%d.%d tools", majorVersion, minorVersion)
    43  	} else {
    44  		logger.Debugf("reading v%d.* tools", majorVersion)
    45  	}
    46  	storagePrefix := storagePrefix(toolsDir)
    47  	names, err := storage.List(stor, storagePrefix)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	var list coretools.List
    52  	var foundAnyTools bool
    53  	for _, name := range names {
    54  		name = filepath.ToSlash(name)
    55  		if !strings.HasPrefix(name, storagePrefix) || !strings.HasSuffix(name, toolSuffix) {
    56  			continue
    57  		}
    58  		var t coretools.Tools
    59  		vers := name[len(storagePrefix) : len(name)-len(toolSuffix)]
    60  		if t.Version, err = version.ParseBinary(vers); err != nil {
    61  			logger.Debugf("failed to parse version %q: %v", vers, err)
    62  			continue
    63  		}
    64  		foundAnyTools = true
    65  		// If specified major version value supplied, major version must match.
    66  		if majorVersion >= 0 && t.Version.Major != majorVersion {
    67  			continue
    68  		}
    69  		// If specified minor version value supplied, minor version must match.
    70  		if minorVersion >= 0 && t.Version.Minor != minorVersion {
    71  			continue
    72  		}
    73  		logger.Debugf("found %s", vers)
    74  		if t.URL, err = stor.URL(name); err != nil {
    75  			return nil, err
    76  		}
    77  		list = append(list, &t)
    78  		// Older versions of Juju only know about ppc64, so add metadata for that arch.
    79  		if t.Version.Arch == arch.PPC64EL {
    80  			legacyPPC64Tools := t
    81  			legacyPPC64Tools.Version.Arch = arch.LEGACY_PPC64
    82  			list = append(list, &legacyPPC64Tools)
    83  		}
    84  	}
    85  	if len(list) == 0 {
    86  		if foundAnyTools {
    87  			return nil, coretools.ErrNoMatches
    88  		}
    89  		return nil, ErrNoTools
    90  	}
    91  	return list, nil
    92  }