Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(251)

Delta Between Two Patch Sets: environs/tools/simplestreams.go

Issue 14527043: Fix tools metadata generation for null provider
Left Patch Set: Created 11 years, 6 months ago
Right Patch Set: Fix tools metadata generation for null provider Created 11 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « environs/testing/tools.go ('k') | environs/tools/simplestreams_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 Canonical Ltd. 1 // Copyright 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 // The tools package supports locating, parsing, and filtering Ubuntu tools meta data in simplestreams format. 4 // The tools package supports locating, parsing, and filtering Ubuntu tools meta data in simplestreams format.
5 // See http://launchpad.net/simplestreams and in particular the doc/README file in that project for more information 5 // See http://launchpad.net/simplestreams and in particular the doc/README file in that project for more information
6 // about the file formats. 6 // about the file formats.
7 package tools 7 package tools
8 8
9 import ( 9 import (
10 "bytes" 10 "bytes"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 FileType: "tar.gz", 207 FileType: "tar.gz",
208 Size: t.Size, 208 Size: t.Size,
209 SHA256: t.SHA256, 209 SHA256: t.SHA256,
210 } 210 }
211 } 211 }
212 return metadata 212 return metadata
213 } 213 }
214 214
215 // ResolveMetadata resolves incomplete metadata 215 // ResolveMetadata resolves incomplete metadata
216 // by fetching the tools from storage and computing 216 // by fetching the tools from storage and computing
217 // the metadata locally. 217 // the size and hash locally.
218 func ResolveMetadata(stor storage.StorageReader, metadata []*ToolsMetadata) erro r { 218 func ResolveMetadata(stor storage.StorageReader, metadata []*ToolsMetadata) erro r {
219 for _, md := range metadata { 219 for _, md := range metadata {
220 » » if md.Size == 0 { 220 » » if md.Size != 0 {
221 » » » binary := md.binary() 221 » » » continue
222 » » » logger.Infof("Fetching tools to generate hash: %v", bina ry) 222 » » }
223 » » » var sha256hash hash.Hash 223 » » binary := md.binary()
224 » » » size, sha256hash, err := fetchToolsHash(stor, binary) 224 » » logger.Infof("Fetching tools to generate hash: %v", binary)
225 » » » if err != nil { 225 » » var sha256hash hash.Hash
226 » » » » return err 226 » » size, sha256hash, err := fetchToolsHash(stor, binary)
227 » » » } 227 » » if err != nil {
228 » » » md.Size = size 228 » » » return err
229 » » » md.SHA256 = fmt.Sprintf("%x", sha256hash.Sum(nil)) 229 » » }
230 » » } 230 » » md.Size = size
231 » » md.SHA256 = fmt.Sprintf("%x", sha256hash.Sum(nil))
231 } 232 }
232 return nil 233 return nil
233 } 234 }
234 235
235 // MergeMetadata merges the given tools metadata. 236 // MergeMetadata merges the given tools metadata.
236 // If metadata for the same tools version exists in both lists, 237 // If metadata for the same tools version exists in both lists,
237 // an entry with non-empty size/SHA256 takes precedence. If 238 // an entry with non-empty size/SHA256 takes precedence; if
238 // both entries have information, prefer the entry from 239 // the two entries have different sizes/hashes, then an error is
239 // "newMetadata". 240 // returned.
240 func MergeMetadata(newMetadata, oldMetadata []*ToolsMetadata) []*ToolsMetadata { 241 func MergeMetadata(tmlist1, tmlist2 []*ToolsMetadata) ([]*ToolsMetadata, error) {
241 merged := make(map[version.Binary]*ToolsMetadata) 242 merged := make(map[version.Binary]*ToolsMetadata)
242 » for _, tm := range newMetadata { 243 » for _, tm := range tmlist1 {
243 merged[tm.binary()] = tm 244 merged[tm.binary()] = tm
244 } 245 }
245 » for _, tm := range oldMetadata { 246 » for _, tm := range tmlist2 {
246 binary := tm.binary() 247 binary := tm.binary()
247 » » if existing, ok := merged[binary]; !ok || existing.Size == 0 { 248 » » if existing, ok := merged[binary]; ok {
249 » » » if tm.Size != 0 {
250 » » » » if existing.Size == 0 {
251 » » » » » merged[binary] = tm
252 » » » » } else if existing.Size != tm.Size || existing.S HA256 != tm.SHA256 {
253 » » » » » return nil, fmt.Errorf(
254 » » » » » » "metadata mismatch for %s: sizes =(%v,%v) sha256=(%v,%v)",
255 » » » » » » binary.String(),
256 » » » » » » existing.Size, tm.Size,
257 » » » » » » existing.SHA256, tm.SHA256,
258 » » » » » )
259 » » » » }
260 » » » }
261 » » } else {
248 merged[binary] = tm 262 merged[binary] = tm
249 } 263 }
250 } 264 }
251 list := make([]*ToolsMetadata, 0, len(merged)) 265 list := make([]*ToolsMetadata, 0, len(merged))
252 for _, metadata := range merged { 266 for _, metadata := range merged {
253 list = append(list, metadata) 267 list = append(list, metadata)
254 } 268 }
255 » return list 269 » return list, nil
256 } 270 }
257 271
258 // ReadMetadata returns the tools metadata from the given storage. 272 // ReadMetadata returns the tools metadata from the given storage.
259 func ReadMetadata(store storage.StorageReader) ([]*ToolsMetadata, error) { 273 func ReadMetadata(store storage.StorageReader) ([]*ToolsMetadata, error) {
260 dataSource := storage.NewStorageSimpleStreamsDataSource(store, "tools") 274 dataSource := storage.NewStorageSimpleStreamsDataSource(store, "tools")
261 toolsConstraint, err := makeToolsConstraint(simplestreams.CloudSpec{}, - 1, -1, coretools.Filter{}) 275 toolsConstraint, err := makeToolsConstraint(simplestreams.CloudSpec{}, - 1, -1, coretools.Filter{})
262 if err != nil { 276 if err != nil {
263 return nil, err 277 return nil, err
264 } 278 }
265 metadata, err := Fetch([]simplestreams.DataSource{dataSource}, simplestr eams.DefaultIndexPath, toolsConstraint, false) 279 metadata, err := Fetch([]simplestreams.DataSource{dataSource}, simplestr eams.DefaultIndexPath, toolsConstraint, false)
(...skipping 16 matching lines...) Expand all
282 for _, md := range metadataInfo { 296 for _, md := range metadataInfo {
283 logger.Infof("Writing %s", "tools/"+md.Path) 297 logger.Infof("Writing %s", "tools/"+md.Path)
284 err = stor.Put("tools/"+md.Path, bytes.NewReader(md.Data), int64 (len(md.Data))) 298 err = stor.Put("tools/"+md.Path, bytes.NewReader(md.Data), int64 (len(md.Data)))
285 if err != nil { 299 if err != nil {
286 return err 300 return err
287 } 301 }
288 } 302 }
289 return nil 303 return nil
290 } 304 }
291 305
292 type ResolveFlag bool
293
294 const (
295 DontResolve ResolveFlag = false
296 Resolve ResolveFlag = true
297 )
298
299 // MergeAndWriteMetadata reads the existing metadata from storage (if any), 306 // MergeAndWriteMetadata reads the existing metadata from storage (if any),
300 // and merges it with metadata generated from the given tools list. 307 // and merges it with metadata generated from the given tools list. The
301 // If resolve is true, incomplete metadata is resolved by fetching the tools 308 // resulting metadata is written to storage.
302 // from the target storage. Finally, the resulting metadata is written to 309 func MergeAndWriteMetadata(stor storage.Storage, tools coretools.List) error {
303 // storage.
304 func MergeAndWriteMetadata(stor storage.Storage, targetTools coretools.List, res olve ResolveFlag) error {
305 existing, err := ReadMetadata(stor) 310 existing, err := ReadMetadata(stor)
306 if err != nil { 311 if err != nil {
307 return err 312 return err
308 } 313 }
309 » metadata := MetadataFromTools(targetTools) 314 » metadata := MetadataFromTools(tools)
310 » metadata = MergeMetadata(metadata, existing) 315 » if metadata, err = MergeMetadata(metadata, existing); err != nil {
311 » if resolve { 316 » » return err
312 » » if err = ResolveMetadata(stor, metadata); err != nil {
313 » » » return err
314 » » }
315 } 317 }
316 return WriteMetadata(stor, metadata) 318 return WriteMetadata(stor, metadata)
317 } 319 }
318 320
319 // fetchToolsHash fetches the tools from storage and calculates 321 // fetchToolsHash fetches the tools from storage and calculates
320 // its size in bytes and computes a SHA256 hash of its contents. 322 // its size in bytes and computes a SHA256 hash of its contents.
321 func fetchToolsHash(stor storage.StorageReader, ver version.Binary) (size int64, sha256hash hash.Hash, err error) { 323 func fetchToolsHash(stor storage.StorageReader, ver version.Binary) (size int64, sha256hash hash.Hash, err error) {
322 r, err := storage.Get(stor, StorageName(ver)) 324 r, err := storage.Get(stor, StorageName(ver))
323 if err != nil { 325 if err != nil {
324 return 0, nil, err 326 return 0, nil, err
325 } 327 }
326 defer r.Close() 328 defer r.Close()
327 sha256hash = sha256.New() 329 sha256hash = sha256.New()
328 size, err = io.Copy(sha256hash, r) 330 size, err = io.Copy(sha256hash, r)
329 return size, sha256hash, err 331 return size, sha256hash, err
330 } 332 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b