github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/annotations/client.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package annotations 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/state" 13 ) 14 15 func init() { 16 common.RegisterStandardFacade("Annotations", 2, NewAPI) 17 } 18 19 var getState = func(st *state.State) annotationAccess { 20 return stateShim{st} 21 } 22 23 // Annotations defines the methods on the service API end point. 24 type Annotations interface { 25 Get(args params.Entities) params.AnnotationsGetResults 26 Set(args params.AnnotationsSet) params.ErrorResults 27 } 28 29 // API implements the service interface and is the concrete 30 // implementation of the api end point. 31 type API struct { 32 access annotationAccess 33 authorizer common.Authorizer 34 } 35 36 // NewAPI returns a new charm annotator API facade. 37 func NewAPI( 38 st *state.State, 39 resources *common.Resources, 40 authorizer common.Authorizer, 41 ) (*API, error) { 42 if !authorizer.AuthClient() { 43 return nil, common.ErrPerm 44 } 45 46 return &API{ 47 access: getState(st), 48 authorizer: authorizer, 49 }, nil 50 } 51 52 // Get returns annotations for given entities. 53 // If annotations cannot be retrieved for a given entity, an error is returned. 54 // Each entity is treated independently and, hence, will fail or succeed independently. 55 func (api *API) Get(args params.Entities) params.AnnotationsGetResults { 56 entityResults := []params.AnnotationsGetResult{} 57 for _, entity := range args.Entities { 58 anEntityResult := params.AnnotationsGetResult{EntityTag: entity.Tag} 59 if annts, err := api.getEntityAnnotations(entity.Tag); err != nil { 60 anEntityResult.Error = params.ErrorResult{annotateError(err, entity.Tag, "getting")} 61 } else { 62 anEntityResult.Annotations = annts 63 } 64 entityResults = append(entityResults, anEntityResult) 65 } 66 return params.AnnotationsGetResults{Results: entityResults} 67 } 68 69 // Set stores annotations for given entities 70 func (api *API) Set(args params.AnnotationsSet) params.ErrorResults { 71 setErrors := []params.ErrorResult{} 72 for _, entityAnnotation := range args.Annotations { 73 err := api.setEntityAnnotations(entityAnnotation.EntityTag, entityAnnotation.Annotations) 74 if err != nil { 75 setErrors = append(setErrors, 76 params.ErrorResult{Error: annotateError(err, entityAnnotation.EntityTag, "setting")}) 77 } 78 } 79 return params.ErrorResults{Results: setErrors} 80 } 81 82 func annotateError(err error, tag, op string) *params.Error { 83 return common.ServerError( 84 errors.Trace( 85 errors.Annotatef( 86 err, "while %v annotations to %q", op, tag))) 87 } 88 89 func (api *API) getEntityAnnotations(entityTag string) (map[string]string, error) { 90 tag, err := names.ParseTag(entityTag) 91 if err != nil { 92 return nil, errors.Trace(err) 93 } 94 entity, err := api.findEntity(tag) 95 if err != nil { 96 return nil, errors.Trace(err) 97 } 98 annotations, err := api.access.GetAnnotations(entity) 99 if err != nil { 100 return nil, errors.Trace(err) 101 } 102 return annotations, nil 103 } 104 105 func (api *API) findEntity(tag names.Tag) (state.GlobalEntity, error) { 106 entity0, err := api.access.FindEntity(tag) 107 if err != nil { 108 if errors.IsNotFound(err) { 109 return nil, common.ErrPerm 110 } 111 return nil, err 112 } 113 entity, ok := entity0.(state.GlobalEntity) 114 if !ok { 115 return nil, common.NotSupportedError(tag, "annotations") 116 } 117 return entity, nil 118 } 119 120 func (api *API) setEntityAnnotations(entityTag string, annotations map[string]string) error { 121 tag, err := names.ParseTag(entityTag) 122 if err != nil { 123 return errors.Trace(err) 124 } 125 entity, err := api.findEntity(tag) 126 if err != nil { 127 return errors.Trace(err) 128 } 129 return api.access.SetAnnotations(entity, annotations) 130 }