github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/uniter/payload.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 10 "github.com/juju/juju/api/base" 11 api "github.com/juju/juju/api/client/payloads" 12 apiservererrors "github.com/juju/juju/apiserver/errors" 13 "github.com/juju/juju/core/payloads" 14 "github.com/juju/juju/rpc/params" 15 ) 16 17 // PayloadFacadeClient provides methods for interacting with Juju's internal 18 // RPC API, relative to payloads. 19 type PayloadFacadeClient struct { 20 FacadeCaller 21 } 22 23 // NewPayloadFacadeClient builds a new payload API client. 24 func NewPayloadFacadeClient(caller base.APICaller) *PayloadFacadeClient { 25 facadeCaller := base.NewFacadeCaller(caller, "PayloadsHookContext") 26 return &PayloadFacadeClient{FacadeCaller: facadeCaller} 27 } 28 29 // Track calls the Track API server method. 30 func (c PayloadFacadeClient) Track(payloads ...payloads.Payload) ([]payloads.Result, error) { 31 args := payloads2TrackArgs(payloads) 32 33 var rs params.PayloadResults 34 if err := c.FacadeCall("Track", &args, &rs); err != nil { 35 return nil, errors.Trace(err) 36 } 37 38 return api2results(rs) 39 } 40 41 // List calls the List API server method. 42 func (c PayloadFacadeClient) List(fullIDs ...string) ([]payloads.Result, error) { 43 var ids []string 44 if len(fullIDs) > 0 { 45 actual, err := c.lookUp(fullIDs) 46 if err != nil { 47 return nil, errors.Trace(err) 48 } 49 ids = actual 50 } 51 args := ids2Args(ids) 52 53 var rs params.PayloadResults 54 if err := c.FacadeCall("List", &args, &rs); err != nil { 55 return nil, errors.Trace(err) 56 } 57 58 return api2results(rs) 59 } 60 61 // LookUp calls the LookUp API server method. 62 func (c PayloadFacadeClient) LookUp(fullIDs ...string) ([]payloads.Result, error) { 63 if len(fullIDs) == 0 { 64 // Unlike List(), LookUp doesn't fall back to looking up all IDs. 65 return nil, nil 66 } 67 args := fullIDs2LookUpArgs(fullIDs) 68 69 var rs params.PayloadResults 70 if err := c.FacadeCall("LookUp", &args, &rs); err != nil { 71 return nil, err 72 } 73 74 return api2results(rs) 75 } 76 77 // SetStatus calls the SetStatus API server method. 78 func (c PayloadFacadeClient) SetStatus(status string, fullIDs ...string) ([]payloads.Result, error) { 79 ids, err := c.lookUp(fullIDs) 80 if err != nil { 81 return nil, errors.Trace(err) 82 } 83 args := ids2SetStatusArgs(ids, status) 84 85 var rs params.PayloadResults 86 if err := c.FacadeCall("SetStatus", &args, &rs); err != nil { 87 return nil, err 88 } 89 90 return api2results(rs) 91 } 92 93 // Untrack calls the Untrack API server method. 94 func (c PayloadFacadeClient) Untrack(fullIDs ...string) ([]payloads.Result, error) { 95 ids, err := c.lookUp(fullIDs) 96 if err != nil { 97 return nil, errors.Trace(err) 98 } 99 args := ids2Args(ids) 100 101 var rs params.PayloadResults 102 if err := c.FacadeCall("Untrack", &args, &rs); err != nil { 103 return nil, err 104 } 105 106 return api2results(rs) 107 } 108 109 func (c PayloadFacadeClient) lookUp(fullIDs []string) ([]string, error) { 110 results, err := c.LookUp(fullIDs...) 111 if err != nil { 112 return nil, errors.Annotate(err, "while looking up IDs") 113 } 114 115 var ids []string 116 for _, result := range results { 117 if result.Error != nil { 118 // TODO(ericsnow) Do not short-circuit? 119 return nil, errors.Annotate(result.Error, "while looking up IDs") 120 } 121 ids = append(ids, result.ID) 122 } 123 return ids, nil 124 } 125 126 func api2results(rs params.PayloadResults) ([]payloads.Result, error) { 127 var results []payloads.Result 128 for _, r := range rs.Results { 129 result, err := api2Result(r) 130 if err != nil { 131 // This should not happen; we safely control the result. 132 return nil, errors.Trace(err) 133 } 134 results = append(results, result) 135 } 136 return results, nil 137 } 138 139 // api2Result converts the API result to a payloads.Result. 140 func api2Result(r params.PayloadResult) (payloads.Result, error) { 141 result := payloads.Result{ 142 NotFound: r.NotFound, 143 } 144 145 id, err := api.API2ID(r.Tag) 146 if err != nil { 147 return result, errors.Trace(err) 148 } 149 result.ID = id 150 151 if r.Payload != nil { 152 pl, err := api.API2Payload(*r.Payload) 153 if err != nil { 154 return result, errors.Trace(err) 155 } 156 result.Payload = &pl 157 } 158 159 if r.Error != nil { 160 result.Error = apiservererrors.RestoreError(r.Error) 161 } 162 163 return result, nil 164 } 165 166 // payloads2TrackArgs converts the provided payload info into arguments 167 // for the Track API endpoint. 168 func payloads2TrackArgs(payloadInfo []payloads.Payload) params.TrackPayloadArgs { 169 var args params.TrackPayloadArgs 170 for _, pl := range payloadInfo { 171 fullPayload := payloads.FullPayloadInfo{Payload: pl} 172 arg := api.Payload2api(fullPayload) 173 args.Payloads = append(args.Payloads, arg) 174 } 175 return args 176 } 177 178 // fullIDs2LookUpArgs converts the provided payload "full" IDs into arguments 179 // for the LookUp API endpoint. 180 func fullIDs2LookUpArgs(fullIDs []string) params.LookUpPayloadArgs { 181 var args params.LookUpPayloadArgs 182 for _, fullID := range fullIDs { 183 name, rawID := payloads.ParseID(fullID) 184 args.Args = append(args.Args, params.LookUpPayloadArg{ 185 Name: name, 186 ID: rawID, 187 }) 188 } 189 return args 190 } 191 192 // ids2SetStatusArgs converts the provided payload IDs into arguments 193 // for the SetStatus API endpoint. 194 func ids2SetStatusArgs(ids []string, status string) params.SetPayloadStatusArgs { 195 var args params.SetPayloadStatusArgs 196 for _, id := range ids { 197 arg := params.SetPayloadStatusArg{ 198 Status: status, 199 } 200 arg.Tag = names.NewPayloadTag(id).String() 201 args.Args = append(args.Args, arg) 202 } 203 return args 204 } 205 206 func ids2Args(ids []string) params.Entities { 207 var args params.Entities 208 for _, id := range ids { 209 tag := names.NewPayloadTag(id).String() 210 args.Entities = append(args.Entities, params.Entity{ 211 Tag: tag, 212 }) 213 } 214 return args 215 }