github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/imagemetadata/metadata.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package imagemetadata 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/state" 13 "github.com/juju/juju/state/cloudimagemetadata" 14 ) 15 16 func init() { 17 common.RegisterStandardFacade("ImageMetadata", 1, NewAPI) 18 } 19 20 // API is the concrete implementation of the api end point 21 // for loud image metadata manipulations. 22 type API struct { 23 metadata metadataAcess 24 authorizer common.Authorizer 25 } 26 27 // createAPI returns a new image metadata API facade. 28 func createAPI( 29 st metadataAcess, 30 resources *common.Resources, 31 authorizer common.Authorizer, 32 ) (*API, error) { 33 if !authorizer.AuthClient() && !authorizer.AuthEnvironManager() { 34 return nil, common.ErrPerm 35 } 36 37 return &API{ 38 metadata: st, 39 authorizer: authorizer, 40 }, nil 41 } 42 43 // NewAPI returns a new cloud image metadata API facade. 44 func NewAPI( 45 st *state.State, 46 resources *common.Resources, 47 authorizer common.Authorizer, 48 ) (*API, error) { 49 return createAPI(getState(st), resources, authorizer) 50 } 51 52 // List returns all found cloud image metadata that satisfy 53 // given filter. 54 // Returned list contains metadata for custom images first, then public. 55 func (api *API) List(filter params.ImageMetadataFilter) (params.ListCloudImageMetadataResult, error) { 56 found, err := api.metadata.FindMetadata(cloudimagemetadata.MetadataFilter{ 57 Region: filter.Region, 58 Series: filter.Series, 59 Arches: filter.Arches, 60 Stream: filter.Stream, 61 VirtualType: filter.VirtualType, 62 RootStorageType: filter.RootStorageType, 63 }) 64 if err != nil { 65 return params.ListCloudImageMetadataResult{}, common.ServerError(err) 66 } 67 68 var all []params.CloudImageMetadata 69 addAll := func(ms []cloudimagemetadata.Metadata) { 70 for _, m := range ms { 71 all = append(all, parseMetadataToParams(m)) 72 } 73 } 74 75 // First return metadata for custom images, then public. 76 // No other source for cloud images should exist at the moment. 77 // Once new source is identified, the order of returned metadata 78 // may need to be changed. 79 addAll(found[cloudimagemetadata.Custom]) 80 addAll(found[cloudimagemetadata.Public]) 81 82 return params.ListCloudImageMetadataResult{Result: all}, nil 83 } 84 85 // Save stores given cloud image metadata. 86 // It supports bulk calls. 87 func (api *API) Save(metadata params.MetadataSaveParams) (params.ErrorResults, error) { 88 all := make([]params.ErrorResult, len(metadata.Metadata)) 89 for i, one := range metadata.Metadata { 90 err := api.metadata.SaveMetadata(parseMetadataFromParams(one)) 91 all[i] = params.ErrorResult{Error: common.ServerError(err)} 92 } 93 return params.ErrorResults{Results: all}, nil 94 } 95 96 func parseMetadataToParams(p cloudimagemetadata.Metadata) params.CloudImageMetadata { 97 result := params.CloudImageMetadata{ 98 ImageId: p.ImageId, 99 Stream: p.Stream, 100 Region: p.Region, 101 Series: p.Series, 102 Arch: p.Arch, 103 VirtualType: p.VirtualType, 104 RootStorageType: p.RootStorageType, 105 RootStorageSize: p.RootStorageSize, 106 Source: string(p.Source), 107 } 108 return result 109 } 110 111 func parseMetadataFromParams(p params.CloudImageMetadata) cloudimagemetadata.Metadata { 112 113 parseSource := func(s string) cloudimagemetadata.SourceType { 114 switch cloudimagemetadata.SourceType(strings.ToLower(s)) { 115 case cloudimagemetadata.Public: 116 return cloudimagemetadata.Public 117 case cloudimagemetadata.Custom: 118 return cloudimagemetadata.Custom 119 default: 120 panic(fmt.Sprintf("unknown cloud image metadata source %q", s)) 121 } 122 } 123 124 result := cloudimagemetadata.Metadata{ 125 cloudimagemetadata.MetadataAttributes{ 126 Stream: p.Stream, 127 Region: p.Region, 128 Series: p.Series, 129 Arch: p.Arch, 130 VirtualType: p.VirtualType, 131 RootStorageType: p.RootStorageType, 132 RootStorageSize: p.RootStorageSize, 133 Source: parseSource(p.Source), 134 }, 135 p.ImageId, 136 } 137 if p.Stream == "" { 138 result.Stream = "released" 139 } 140 return result 141 }