github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/imagemetadatamanager/metadata.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package imagemetadatamanager 5 6 import ( 7 "sort" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 12 "github.com/juju/juju/apiserver/common" 13 "github.com/juju/juju/apiserver/common/imagecommon" 14 "github.com/juju/juju/apiserver/facade" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/permission" 18 "github.com/juju/juju/state" 19 "github.com/juju/juju/state/cloudimagemetadata" 20 "github.com/juju/juju/state/stateenvirons" 21 ) 22 23 var logger = loggo.GetLogger("juju.apiserver.imagemetadatamanager") 24 25 // API is the concrete implementation of the api end point 26 // for loud image metadata manipulations. 27 type API struct { 28 metadata metadataAccess 29 newEnviron func() (environs.Environ, error) 30 } 31 32 // createAPI returns a new image metadata API facade. 33 func createAPI( 34 st metadataAccess, 35 newEnviron func() (environs.Environ, error), 36 resources facade.Resources, 37 authorizer facade.Authorizer, 38 ) (*API, error) { 39 if !authorizer.AuthClient() { 40 return nil, common.ErrPerm 41 } 42 admin, err := authorizer.HasPermission(permission.SuperuserAccess, st.ControllerTag()) 43 if err != nil { 44 return nil, common.ErrPerm 45 } 46 if !admin { 47 return nil, common.ErrPerm 48 } 49 50 return &API{ 51 metadata: st, 52 newEnviron: newEnviron, 53 }, nil 54 } 55 56 // NewAPI returns a new cloud image metadata API facade. 57 func NewAPI( 58 st *state.State, 59 resources facade.Resources, 60 authorizer facade.Authorizer, 61 ) (*API, error) { 62 newEnviron := func() (environs.Environ, error) { 63 return stateenvirons.GetNewEnvironFunc(environs.New)(st) 64 } 65 return createAPI(getState(st), newEnviron, resources, authorizer) 66 } 67 68 // List returns all found cloud image metadata that satisfy 69 // given filter. 70 // Returned list contains metadata ordered by priority. 71 func (api *API) List(filter params.ImageMetadataFilter) (params.ListCloudImageMetadataResult, error) { 72 found, err := api.metadata.FindMetadata(cloudimagemetadata.MetadataFilter{ 73 Region: filter.Region, 74 Series: filter.Series, 75 Arches: filter.Arches, 76 Stream: filter.Stream, 77 VirtType: filter.VirtType, 78 RootStorageType: filter.RootStorageType, 79 }) 80 if err != nil { 81 return params.ListCloudImageMetadataResult{}, common.ServerError(err) 82 } 83 84 var all []params.CloudImageMetadata 85 addAll := func(ms []cloudimagemetadata.Metadata) { 86 for _, m := range ms { 87 all = append(all, parseMetadataToParams(m)) 88 } 89 } 90 91 for _, ms := range found { 92 addAll(ms) 93 } 94 sort.Sort(metadataList(all)) 95 96 return params.ListCloudImageMetadataResult{Result: all}, nil 97 } 98 99 // Save stores given cloud image metadata. 100 // It supports bulk calls. 101 func (api *API) Save(metadata params.MetadataSaveParams) (params.ErrorResults, error) { 102 all, err := imagecommon.Save(api.metadata, metadata) 103 if err != nil { 104 return params.ErrorResults{}, errors.Trace(err) 105 } 106 return params.ErrorResults{Results: all}, nil 107 } 108 109 // Delete deletes cloud image metadata for given image ids. 110 // It supports bulk calls. 111 func (api *API) Delete(images params.MetadataImageIds) (params.ErrorResults, error) { 112 all := make([]params.ErrorResult, len(images.Ids)) 113 for i, imageId := range images.Ids { 114 err := api.metadata.DeleteMetadata(imageId) 115 all[i] = params.ErrorResult{common.ServerError(err)} 116 } 117 return params.ErrorResults{Results: all}, nil 118 } 119 120 func parseMetadataToParams(p cloudimagemetadata.Metadata) params.CloudImageMetadata { 121 result := params.CloudImageMetadata{ 122 ImageId: p.ImageId, 123 Stream: p.Stream, 124 Region: p.Region, 125 Version: p.Version, 126 Series: p.Series, 127 Arch: p.Arch, 128 VirtType: p.VirtType, 129 RootStorageType: p.RootStorageType, 130 RootStorageSize: p.RootStorageSize, 131 Source: p.Source, 132 Priority: p.Priority, 133 } 134 return result 135 } 136 137 // metadataList is a convenience type enabling to sort 138 // a collection of Metadata in order of priority. 139 type metadataList []params.CloudImageMetadata 140 141 // Len implements sort.Interface 142 func (m metadataList) Len() int { 143 return len(m) 144 } 145 146 // Less implements sort.Interface and sorts image metadata by priority. 147 func (m metadataList) Less(i, j int) bool { 148 return m[i].Priority < m[j].Priority 149 } 150 151 // Swap implements sort.Interface 152 func (m metadataList) Swap(i, j int) { 153 m[i], m[j] = m[j], m[i] 154 }