github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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  	"github.com/juju/utils/set"
    11  
    12  	"github.com/juju/juju/environs/simplestreams"
    13  )
    14  
    15  const (
    16  	ProductMetadataPath = "streams/v1/com.ubuntu.cloud-released-imagemetadata.json"
    17  	ImageContentId      = "com.ubuntu.cloud:custom"
    18  )
    19  
    20  // MarshalImageMetadataJSON marshals image metadata to index and products JSON.
    21  //
    22  // updated is the time at which the JSON file was updated.
    23  func MarshalImageMetadataJSON(metadata []*ImageMetadata, cloudSpec []simplestreams.CloudSpec,
    24  	updated time.Time) (index, products []byte, err error) {
    25  
    26  	if index, err = MarshalImageMetadataIndexJSON(metadata, cloudSpec, updated); err != nil {
    27  		return nil, nil, err
    28  	}
    29  	if products, err = MarshalImageMetadataProductsJSON(metadata, updated); err != nil {
    30  		return nil, nil, err
    31  	}
    32  	return index, products, err
    33  }
    34  
    35  // MarshalImageMetadataIndexJSON marshals image metadata to index JSON.
    36  //
    37  // updated is the time at which the JSON file was updated.
    38  func MarshalImageMetadataIndexJSON(metadata []*ImageMetadata, cloudSpec []simplestreams.CloudSpec,
    39  	updated time.Time) (out []byte, err error) {
    40  
    41  	productIds := make([]string, len(metadata))
    42  	for i, t := range metadata {
    43  		productIds[i] = t.productId()
    44  	}
    45  	var indices simplestreams.Indices
    46  	indices.Updated = updated.Format(time.RFC1123Z)
    47  	indices.Format = simplestreams.IndexFormat
    48  	indices.Indexes = map[string]*simplestreams.IndexMetadata{
    49  		ImageContentId: {
    50  			CloudName:        "custom",
    51  			Updated:          indices.Updated,
    52  			Format:           simplestreams.ProductFormat,
    53  			DataType:         "image-ids",
    54  			ProductsFilePath: ProductMetadataPath,
    55  			ProductIds:       set.NewStrings(productIds...).SortedValues(),
    56  			Clouds:           cloudSpec,
    57  		},
    58  	}
    59  	return json.MarshalIndent(&indices, "", "    ")
    60  }
    61  
    62  // MarshalImageMetadataProductsJSON marshals image metadata to products JSON.
    63  //
    64  // updated is the time at which the JSON file was updated.
    65  func MarshalImageMetadataProductsJSON(metadata []*ImageMetadata, updated time.Time) (out []byte, err error) {
    66  	var cloud simplestreams.CloudMetadata
    67  	cloud.Updated = updated.Format(time.RFC1123Z)
    68  	cloud.Format = simplestreams.ProductFormat
    69  	cloud.ContentId = ImageContentId
    70  	cloud.Products = make(map[string]simplestreams.MetadataCatalog)
    71  	itemsversion := updated.Format("20060102") // YYYYMMDD
    72  	for _, t := range metadata {
    73  		toWrite := *t
    74  		// These fields are not required in the individual
    75  		// record values - they are recorded at the top level.
    76  		toWrite.RegionAlias = ""
    77  		toWrite.Version = ""
    78  		toWrite.Arch = ""
    79  		if catalog, ok := cloud.Products[t.productId()]; ok {
    80  			catalog.Items[itemsversion].Items[t.Id] = toWrite
    81  		} else {
    82  			catalog = simplestreams.MetadataCatalog{
    83  				Arch:    t.Arch,
    84  				Version: t.Version,
    85  				Items: map[string]*simplestreams.ItemCollection{
    86  					itemsversion: {
    87  						Items: map[string]interface{}{t.Id: toWrite},
    88  					},
    89  				},
    90  			}
    91  			cloud.Products[t.productId()] = catalog
    92  		}
    93  	}
    94  	return json.MarshalIndent(&cloud, "", "    ")
    95  }