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 }