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  }