github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/plugins/juju-metadata/toolsmetadata_test.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  	"bytes"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"regexp"
    12  	"strings"
    13  	"text/template"
    14  
    15  	"github.com/juju/cmd"
    16  	"github.com/juju/loggo"
    17  	jc "github.com/juju/testing/checkers"
    18  	gc "gopkg.in/check.v1"
    19  
    20  	"github.com/juju/juju/cmd/envcmd"
    21  	"github.com/juju/juju/environs"
    22  	"github.com/juju/juju/environs/configstore"
    23  	"github.com/juju/juju/environs/tools"
    24  	toolstesting "github.com/juju/juju/environs/tools/testing"
    25  	"github.com/juju/juju/juju/osenv"
    26  	"github.com/juju/juju/provider/dummy"
    27  	coretesting "github.com/juju/juju/testing"
    28  	"github.com/juju/juju/version"
    29  )
    30  
    31  type ToolsMetadataSuite struct {
    32  	coretesting.FakeJujuHomeSuite
    33  	env              environs.Environ
    34  	publicStorageDir string
    35  }
    36  
    37  var _ = gc.Suite(&ToolsMetadataSuite{})
    38  
    39  func (s *ToolsMetadataSuite) SetUpTest(c *gc.C) {
    40  	s.FakeJujuHomeSuite.SetUpTest(c)
    41  	s.AddCleanup(func(*gc.C) {
    42  		dummy.Reset()
    43  		loggo.ResetLoggers()
    44  	})
    45  	env, err := environs.PrepareFromName(
    46  		"erewhemos", envcmd.BootstrapContextNoVerify(coretesting.Context(c)), configstore.NewMem())
    47  	c.Assert(err, jc.ErrorIsNil)
    48  	s.env = env
    49  	loggo.GetLogger("").SetLogLevel(loggo.INFO)
    50  
    51  	// Switch the default tools location.
    52  	s.publicStorageDir = c.MkDir()
    53  	s.PatchValue(&tools.DefaultBaseURL, s.publicStorageDir)
    54  }
    55  
    56  var currentVersionStrings = []string{
    57  	// only these ones will make it into the JSON files.
    58  	version.Current.Number.String() + "-quantal-amd64",
    59  	version.Current.Number.String() + "-quantal-armhf",
    60  	version.Current.Number.String() + "-quantal-i386",
    61  }
    62  
    63  var versionStrings = append([]string{
    64  	"1.12.0-precise-amd64",
    65  	"1.12.0-precise-i386",
    66  	"1.12.0-raring-amd64",
    67  	"1.12.0-raring-i386",
    68  	"1.13.0-precise-amd64",
    69  }, currentVersionStrings...)
    70  
    71  var expectedOutputCommon = makeExpectedOutputCommon()
    72  
    73  func makeExpectedOutputCommon() string {
    74  	expected := `Finding tools in .*
    75  .*Fetching tools from dir "{{.ToolsDir}}" to generate hash: 1\.12\.0-precise-amd64
    76  .*Fetching tools from dir "{{.ToolsDir}}" to generate hash: 1\.12\.0-precise-i386
    77  .*Fetching tools from dir "{{.ToolsDir}}" to generate hash: 1\.12\.0-raring-amd64
    78  .*Fetching tools from dir "{{.ToolsDir}}" to generate hash: 1\.12\.0-raring-i386
    79  .*Fetching tools from dir "{{.ToolsDir}}" to generate hash: 1\.13\.0-precise-amd64
    80  `
    81  	f := `.*Fetching tools from dir "{{.ToolsDir}}" to generate hash: %s` + "\n"
    82  	for _, v := range currentVersionStrings {
    83  		expected += fmt.Sprintf(f, regexp.QuoteMeta(v))
    84  	}
    85  	return strings.TrimSpace(expected)
    86  }
    87  
    88  func makeExpectedOutput(templ, stream, toolsDir string) string {
    89  	t := template.Must(template.New("").Parse(templ))
    90  
    91  	var buf bytes.Buffer
    92  	err := t.Execute(&buf, map[string]interface{}{"Stream": stream, "ToolsDir": toolsDir})
    93  	if err != nil {
    94  		panic(err)
    95  	}
    96  	return buf.String()
    97  }
    98  
    99  var expectedOutputDirectoryReleasedTemplate = expectedOutputCommon + `
   100  .*Writing tools/streams/v1/index2\.json
   101  .*Writing tools/streams/v1/index\.json
   102  .*Writing tools/streams/v1/com\.ubuntu\.juju-{{.Stream}}-tools\.json
   103  `
   104  
   105  var expectedOutputDirectoryTemplate = expectedOutputCommon + `
   106  .*Writing tools/streams/v1/index2\.json
   107  .*Writing tools/streams/v1/com\.ubuntu\.juju-{{.Stream}}-tools\.json
   108  `
   109  
   110  var expectedOutputMirrorsTemplate = expectedOutputCommon + `
   111  .*Writing tools/streams/v1/index2\.json
   112  .*Writing tools/streams/v1/index\.json
   113  .*Writing tools/streams/v1/com\.ubuntu\.juju-{{.Stream}}-tools\.json
   114  .*Writing tools/streams/v1/mirrors\.json
   115  `
   116  
   117  var expectedOutputDirectoryLegacyReleased = "No stream specified, defaulting to released tools in the releases directory.\n" +
   118  	makeExpectedOutput(expectedOutputDirectoryReleasedTemplate, "released", "releases")
   119  
   120  var expectedOutputMirrorsReleased = makeExpectedOutput(expectedOutputMirrorsTemplate, "released", "released")
   121  
   122  func (s *ToolsMetadataSuite) TestGenerateLegacyRelease(c *gc.C) {
   123  	metadataDir := osenv.JujuHome() // default metadata dir
   124  	toolstesting.MakeTools(c, metadataDir, "releases", versionStrings)
   125  	ctx := coretesting.Context(c)
   126  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, nil)
   127  	c.Assert(code, gc.Equals, 0)
   128  	output := ctx.Stdout.(*bytes.Buffer).String()
   129  	c.Assert(output, gc.Matches, expectedOutputDirectoryLegacyReleased)
   130  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   131  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   132  	obtainedVersionStrings := make([]string, len(versionStrings))
   133  	for i, metadata := range metadata {
   134  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   135  		obtainedVersionStrings[i] = s
   136  	}
   137  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   138  }
   139  
   140  func (s *ToolsMetadataSuite) TestGenerateToDirectory(c *gc.C) {
   141  	metadataDir := c.MkDir()
   142  	toolstesting.MakeTools(c, metadataDir, "releases", versionStrings)
   143  	ctx := coretesting.Context(c)
   144  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir})
   145  	c.Assert(code, gc.Equals, 0)
   146  	output := ctx.Stdout.(*bytes.Buffer).String()
   147  	c.Assert(output, gc.Matches, expectedOutputDirectoryLegacyReleased)
   148  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   149  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   150  	obtainedVersionStrings := make([]string, len(versionStrings))
   151  	for i, metadata := range metadata {
   152  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   153  		obtainedVersionStrings[i] = s
   154  	}
   155  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   156  }
   157  
   158  func (s *ToolsMetadataSuite) TestGenerateStream(c *gc.C) {
   159  	metadataDir := c.MkDir()
   160  	toolstesting.MakeTools(c, metadataDir, "proposed", versionStrings)
   161  	ctx := coretesting.Context(c)
   162  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "proposed"})
   163  	c.Assert(code, gc.Equals, 0)
   164  	output := ctx.Stdout.(*bytes.Buffer).String()
   165  	c.Assert(output, gc.Matches, makeExpectedOutput(expectedOutputDirectoryTemplate, "proposed", "proposed"))
   166  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "proposed", false)
   167  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   168  	obtainedVersionStrings := make([]string, len(versionStrings))
   169  	for i, metadata := range metadata {
   170  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   171  		obtainedVersionStrings[i] = s
   172  	}
   173  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   174  }
   175  
   176  func (s *ToolsMetadataSuite) TestGenerateMultipleStreams(c *gc.C) {
   177  	metadataDir := c.MkDir()
   178  	toolstesting.MakeTools(c, metadataDir, "proposed", versionStrings)
   179  	toolstesting.MakeTools(c, metadataDir, "released", currentVersionStrings)
   180  
   181  	ctx := coretesting.Context(c)
   182  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "proposed"})
   183  	c.Assert(code, gc.Equals, 0)
   184  	code = cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "released"})
   185  	c.Assert(code, gc.Equals, 0)
   186  
   187  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "proposed", false)
   188  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   189  	obtainedVersionStrings := make([]string, len(versionStrings))
   190  	for i, metadata := range metadata {
   191  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   192  		obtainedVersionStrings[i] = s
   193  	}
   194  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   195  
   196  	metadata = toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   197  	c.Assert(metadata, gc.HasLen, len(currentVersionStrings))
   198  	obtainedVersionStrings = make([]string, len(currentVersionStrings))
   199  	for i, metadata := range metadata {
   200  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   201  		obtainedVersionStrings[i] = s
   202  	}
   203  	c.Assert(obtainedVersionStrings, gc.DeepEquals, currentVersionStrings)
   204  
   205  	toolstesting.MakeTools(c, metadataDir, "released", versionStrings)
   206  	metadata = toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   207  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   208  	obtainedVersionStrings = make([]string, len(versionStrings))
   209  	for i, metadata := range metadata {
   210  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   211  		obtainedVersionStrings[i] = s
   212  	}
   213  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   214  }
   215  
   216  func (s *ToolsMetadataSuite) TestGenerateDeleteExisting(c *gc.C) {
   217  	metadataDir := c.MkDir()
   218  	toolstesting.MakeTools(c, metadataDir, "proposed", versionStrings)
   219  	toolstesting.MakeTools(c, metadataDir, "released", currentVersionStrings)
   220  
   221  	ctx := coretesting.Context(c)
   222  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "proposed"})
   223  	c.Assert(code, gc.Equals, 0)
   224  	code = cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "released"})
   225  	c.Assert(code, gc.Equals, 0)
   226  
   227  	// Remove existing proposed tarballs, and create some different ones.
   228  	err := os.RemoveAll(filepath.Join(metadataDir, "tools", "proposed"))
   229  	c.Assert(err, jc.ErrorIsNil)
   230  	toolstesting.MakeTools(c, metadataDir, "proposed", currentVersionStrings)
   231  
   232  	// Generate proposed metadata again, using --clean.
   233  	code = cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "proposed", "--clean"})
   234  	c.Assert(code, gc.Equals, 0)
   235  
   236  	// Proposed metadata should just list the tarballs that were there, not the merged set.
   237  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "proposed", false)
   238  	c.Assert(metadata, gc.HasLen, len(currentVersionStrings))
   239  	obtainedVersionStrings := make([]string, len(currentVersionStrings))
   240  	for i, metadata := range metadata {
   241  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   242  		obtainedVersionStrings[i] = s
   243  	}
   244  	c.Assert(obtainedVersionStrings, gc.DeepEquals, currentVersionStrings)
   245  
   246  	// Released metadata should be untouched.
   247  	metadata = toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   248  	c.Assert(metadata, gc.HasLen, len(currentVersionStrings))
   249  	obtainedVersionStrings = make([]string, len(currentVersionStrings))
   250  	for i, metadata := range metadata {
   251  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   252  		obtainedVersionStrings[i] = s
   253  	}
   254  	c.Assert(obtainedVersionStrings, gc.DeepEquals, currentVersionStrings)
   255  }
   256  
   257  func (s *ToolsMetadataSuite) TestGenerateWithPublicFallback(c *gc.C) {
   258  	// Write tools and metadata to the public tools location.
   259  	toolstesting.MakeToolsWithCheckSum(c, s.publicStorageDir, "released", versionStrings)
   260  
   261  	// Run the command with no local metadata.
   262  	ctx := coretesting.Context(c)
   263  	metadataDir := c.MkDir()
   264  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"-d", metadataDir, "--stream", "released"})
   265  	c.Assert(code, gc.Equals, 0)
   266  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   267  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   268  	obtainedVersionStrings := make([]string, len(versionStrings))
   269  	for i, metadata := range metadata {
   270  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   271  		obtainedVersionStrings[i] = s
   272  	}
   273  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   274  }
   275  
   276  func (s *ToolsMetadataSuite) TestGenerateWithMirrors(c *gc.C) {
   277  	metadataDir := c.MkDir()
   278  	toolstesting.MakeTools(c, metadataDir, "released", versionStrings)
   279  	ctx := coretesting.Context(c)
   280  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"--public", "-d", metadataDir, "--stream", "released"})
   281  	c.Assert(code, gc.Equals, 0)
   282  	output := ctx.Stdout.(*bytes.Buffer).String()
   283  	c.Assert(output, gc.Matches, expectedOutputMirrorsReleased)
   284  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", true)
   285  	c.Assert(metadata, gc.HasLen, len(versionStrings))
   286  	obtainedVersionStrings := make([]string, len(versionStrings))
   287  	for i, metadata := range metadata {
   288  		s := fmt.Sprintf("%s-%s-%s", metadata.Version, metadata.Release, metadata.Arch)
   289  		obtainedVersionStrings[i] = s
   290  	}
   291  	c.Assert(obtainedVersionStrings, gc.DeepEquals, versionStrings)
   292  }
   293  
   294  func (s *ToolsMetadataSuite) TestNoTools(c *gc.C) {
   295  	ctx := coretesting.Context(c)
   296  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, nil)
   297  	c.Assert(code, gc.Equals, 1)
   298  	stdout := ctx.Stdout.(*bytes.Buffer).String()
   299  	c.Assert(stdout, gc.Matches, ".*\nFinding tools in .*\n")
   300  	stderr := ctx.Stderr.(*bytes.Buffer).String()
   301  	c.Assert(stderr, gc.Matches, "error: no tools available\n")
   302  }
   303  
   304  func (s *ToolsMetadataSuite) TestPatchLevels(c *gc.C) {
   305  	currentVersion := version.Current.Number
   306  	currentVersion.Build = 0
   307  	versionStrings := []string{
   308  		currentVersion.String() + "-precise-amd64",
   309  		currentVersion.String() + ".1-precise-amd64",
   310  	}
   311  	metadataDir := osenv.JujuHome() // default metadata dir
   312  	toolstesting.MakeTools(c, metadataDir, "released", versionStrings)
   313  	ctx := coretesting.Context(c)
   314  	code := cmd.Main(envcmd.Wrap(&ToolsMetadataCommand{}), ctx, []string{"--stream", "released"})
   315  	c.Assert(code, gc.Equals, 0)
   316  	output := ctx.Stdout.(*bytes.Buffer).String()
   317  	expectedOutput := fmt.Sprintf(`
   318  Finding tools in .*
   319  .*Fetching tools from dir "released" to generate hash: %s
   320  .*Fetching tools from dir "released" to generate hash: %s
   321  .*Writing tools/streams/v1/index2\.json
   322  .*Writing tools/streams/v1/index\.json
   323  .*Writing tools/streams/v1/com\.ubuntu\.juju-released-tools\.json
   324  `[1:], regexp.QuoteMeta(versionStrings[0]), regexp.QuoteMeta(versionStrings[1]))
   325  	c.Assert(output, gc.Matches, expectedOutput)
   326  	metadata := toolstesting.ParseMetadataFromDir(c, metadataDir, "released", false)
   327  	c.Assert(metadata, gc.HasLen, 2)
   328  
   329  	filename := fmt.Sprintf("juju-%s-precise-amd64.tgz", currentVersion)
   330  	size, sha256 := toolstesting.SHA256sum(c, filepath.Join(metadataDir, "tools", "released", filename))
   331  	c.Assert(metadata[0], gc.DeepEquals, &tools.ToolsMetadata{
   332  		Release:  "precise",
   333  		Version:  currentVersion.String(),
   334  		Arch:     "amd64",
   335  		Size:     size,
   336  		Path:     "released/" + filename,
   337  		FileType: "tar.gz",
   338  		SHA256:   sha256,
   339  	})
   340  
   341  	filename = fmt.Sprintf("juju-%s.1-precise-amd64.tgz", currentVersion)
   342  	size, sha256 = toolstesting.SHA256sum(c, filepath.Join(metadataDir, "tools", "released", filename))
   343  	c.Assert(metadata[1], gc.DeepEquals, &tools.ToolsMetadata{
   344  		Release:  "precise",
   345  		Version:  currentVersion.String() + ".1",
   346  		Arch:     "amd64",
   347  		Size:     size,
   348  		Path:     "released/" + filename,
   349  		FileType: "tar.gz",
   350  		SHA256:   sha256,
   351  	})
   352  }