github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/vsphere/image_metadata.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package vsphere
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	"github.com/juju/juju/core/base"
    10  	"github.com/juju/juju/environs"
    11  	"github.com/juju/juju/environs/imagemetadata"
    12  	"github.com/juju/juju/environs/simplestreams"
    13  )
    14  
    15  /*
    16  Vmware provider use "image-download" data type for simplestream. That's why we use custom implementation of imagemetadata.Fetch function.
    17  We also use custom struct OvfFileMetadata that corresponds to the format used in "image-downloads" simplestream datatype.
    18  Also we use custom append function to filter content of the stream and keep only items, that have ova FileType
    19  */
    20  
    21  type OvaFileMetadata struct {
    22  	URL      string
    23  	Arch     string `json:"arch"`
    24  	Size     int    `json:"size"`
    25  	Path     string `json:"path"`
    26  	FileType string `json:"ftype"`
    27  	Sha256   string `json:"sha256"`
    28  	Md5      string `json:"md5"`
    29  }
    30  
    31  func init() {
    32  	simplestreams.RegisterStructTags(OvaFileMetadata{})
    33  }
    34  
    35  func findImageMetadata(env environs.Environ, arch string, b base.Base) (*OvaFileMetadata, error) {
    36  	vers, err := imagemetadata.ImageRelease(b)
    37  	if err != nil {
    38  		return nil, errors.Trace(err)
    39  	}
    40  	ic := &imagemetadata.ImageConstraint{
    41  		LookupParams: simplestreams.LookupParams{
    42  			Releases: []string{vers},
    43  			Arches:   []string{arch},
    44  			Stream:   env.Config().ImageStream(),
    45  		},
    46  	}
    47  	ss := simplestreams.NewSimpleStreams(simplestreams.DefaultDataSourceFactory())
    48  	sources, err := environs.ImageMetadataSources(env, ss)
    49  	if err != nil {
    50  		return nil, errors.Trace(err)
    51  	}
    52  
    53  	matchingImages, err := imageMetadataFetch(sources, ic)
    54  	if err != nil {
    55  		return nil, errors.Trace(err)
    56  	}
    57  	if len(matchingImages) == 0 {
    58  		return nil, errors.Errorf("no matching images found for given constraints: %v", ic)
    59  	}
    60  
    61  	return matchingImages[0], nil
    62  }
    63  
    64  func imageMetadataFetch(sources []simplestreams.DataSource, cons *imagemetadata.ImageConstraint) ([]*OvaFileMetadata, error) {
    65  	params := simplestreams.GetMetadataParams{
    66  		StreamsVersion:   imagemetadata.StreamsVersionV1,
    67  		LookupConstraint: cons,
    68  		ValueParams: simplestreams.ValueParams{
    69  			DataType:      "image-downloads",
    70  			FilterFunc:    appendMatchingFunc,
    71  			ValueTemplate: OvaFileMetadata{},
    72  		},
    73  	}
    74  	ss := simplestreams.NewSimpleStreams(simplestreams.DefaultDataSourceFactory())
    75  	items, _, err := ss.GetMetadata(sources, params)
    76  	if err != nil {
    77  		return nil, errors.Trace(err)
    78  	}
    79  	metadata := make([]*OvaFileMetadata, len(items))
    80  	for i, md := range items {
    81  		metadata[i] = md.(*OvaFileMetadata)
    82  	}
    83  	return metadata, nil
    84  }
    85  
    86  func appendMatchingFunc(source simplestreams.DataSource, matchingImages []interface{},
    87  	images map[string]interface{}, cons simplestreams.LookupConstraint) ([]interface{}, error) {
    88  
    89  	for _, val := range images {
    90  		file := val.(*OvaFileMetadata)
    91  		if file.FileType == "ova" {
    92  			//ignore error for url data source
    93  			url, _ := source.URL(file.Path)
    94  			file.URL = url
    95  			matchingImages = append(matchingImages, file)
    96  		}
    97  	}
    98  	return matchingImages, nil
    99  }