launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/environs/imagemetadata/marshal.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package imagemetadata
     5  
     6  import (
     7  	"encoding/json"
     8  	"time"
     9  
    10  	"launchpad.net/juju-core/environs/simplestreams"
    11  	"launchpad.net/juju-core/utils/set"
    12  )
    13  
    14  const (
    15  	ProductMetadataPath = "streams/v1/com.ubuntu.cloud:released:imagemetadata.json"
    16  	ImageContentId      = "com.ubuntu.cloud:custom"
    17  )
    18  
    19  // MarshalImageMetadataJSON marshals image metadata to index and products JSON.
    20  //
    21  // updated is the time at which the JSON file was updated.
    22  func MarshalImageMetadataJSON(metadata []*ImageMetadata, cloudSpec []simplestreams.CloudSpec,
    23  	updated time.Time) (index, products []byte, err error) {
    24  
    25  	if index, err = MarshalImageMetadataIndexJSON(metadata, cloudSpec, updated); err != nil {
    26  		return nil, nil, err
    27  	}
    28  	if products, err = MarshalImageMetadataProductsJSON(metadata, updated); err != nil {
    29  		return nil, nil, err
    30  	}
    31  	return index, products, err
    32  }
    33  
    34  // MarshalImageMetadataIndexJSON marshals image metadata to index JSON.
    35  //
    36  // updated is the time at which the JSON file was updated.
    37  func MarshalImageMetadataIndexJSON(metadata []*ImageMetadata, cloudSpec []simplestreams.CloudSpec,
    38  	updated time.Time) (out []byte, err error) {
    39  
    40  	productIds := make([]string, len(metadata))
    41  	for i, t := range metadata {
    42  		productIds[i] = t.productId()
    43  	}
    44  	var indices simplestreams.Indices
    45  	indices.Updated = updated.Format(time.RFC1123Z)
    46  	indices.Format = "index:1.0"
    47  	indices.Indexes = map[string]*simplestreams.IndexMetadata{
    48  		ImageContentId: &simplestreams.IndexMetadata{
    49  			CloudName:        "custom",
    50  			Updated:          indices.Updated,
    51  			Format:           "products:1.0",
    52  			DataType:         "image-ids",
    53  			ProductsFilePath: ProductMetadataPath,
    54  			ProductIds:       set.NewStrings(productIds...).SortedValues(),
    55  			Clouds:           cloudSpec,
    56  		},
    57  	}
    58  	return json.MarshalIndent(&indices, "", "    ")
    59  }
    60  
    61  // MarshalImageMetadataProductsJSON marshals image metadata to products JSON.
    62  //
    63  // updated is the time at which the JSON file was updated.
    64  func MarshalImageMetadataProductsJSON(metadata []*ImageMetadata, updated time.Time) (out []byte, err error) {
    65  	var cloud simplestreams.CloudMetadata
    66  	cloud.Updated = updated.Format(time.RFC1123Z)
    67  	cloud.Format = "products:1.0"
    68  	cloud.ContentId = ImageContentId
    69  	cloud.Products = make(map[string]simplestreams.MetadataCatalog)
    70  	itemsversion := updated.Format("20060201") // YYYYMMDD
    71  	for _, t := range metadata {
    72  		toWrite := &ImageMetadata{
    73  			Id:         t.Id,
    74  			RegionName: t.RegionName,
    75  			Endpoint:   t.Endpoint,
    76  		}
    77  		if catalog, ok := cloud.Products[t.productId()]; ok {
    78  			catalog.Items[itemsversion].Items[t.Id] = toWrite
    79  		} else {
    80  			catalog = simplestreams.MetadataCatalog{
    81  				Arch:    t.Arch,
    82  				Version: t.Version,
    83  				Items: map[string]*simplestreams.ItemCollection{
    84  					itemsversion: &simplestreams.ItemCollection{
    85  						Items: map[string]interface{}{t.Id: toWrite},
    86  					},
    87  				},
    88  			}
    89  			cloud.Products[t.productId()] = catalog
    90  		}
    91  	}
    92  	return json.MarshalIndent(&cloud, "", "    ")
    93  }