55
59
return resource.ServiceResources{}, errors.Annotate(err, "got bad data from server")
61
resNames := map[string]bool{}
57
62
unitResources := resource.UnitResources{Tag: tag}
58
63
for _, apiRes := range unitRes.Resources {
59
64
res, err := API2Resource(apiRes)
61
66
return resource.ServiceResources{}, errors.Annotate(err, "got bad data from server")
68
resNames[res.Name] = true
63
69
unitResources.Resources = append(unitResources.Resources, res)
71
if len(unitRes.DownloadProgress) > 0 {
72
unitResources.DownloadProgress = make(map[string]int64)
73
for resName, progress := range unitRes.DownloadProgress {
74
if _, ok := resNames[resName]; !ok {
75
err := errors.Errorf("got progress from unrecognized resource %q", resName)
76
return resource.ServiceResources{}, errors.Annotate(err, "got bad data from server")
78
unitResources.DownloadProgress[resName] = progress
65
81
result.UnitResources = append(result.UnitResources, unitResources)
79
func ServiceResources2APIResult(svcRes resource.ServiceResources, units []names.UnitTag) ResourcesResult {
95
func ServiceResources2APIResult(svcRes resource.ServiceResources) ResourcesResult {
80
96
var result ResourcesResult
81
97
for _, res := range svcRes.Resources {
82
98
result.Resources = append(result.Resources, Resource2API(res))
84
unitResources := make(map[names.UnitTag]resource.UnitResources, len(svcRes.UnitResources))
85
for _, unitRes := range svcRes.UnitResources {
86
unitResources[unitRes.Tag] = unitRes
89
result.UnitResources = make([]UnitResources, len(units))
90
for i, tag := range units {
101
for _, unitResources := range svcRes.UnitResources {
102
tag := unitResources.Tag
91
103
apiRes := UnitResources{
92
104
Entity: params.Entity{Tag: tag.String()},
94
for _, res := range unitResources[tag].Resources {
95
apiRes.Resources = append(apiRes.Resources, Resource2API(res))
97
result.UnitResources[i] = apiRes
106
for _, unitRes := range unitResources.Resources {
107
apiRes.Resources = append(apiRes.Resources, Resource2API(unitRes))
109
if len(unitResources.DownloadProgress) > 0 {
110
apiRes.DownloadProgress = make(map[string]int64)
111
for resName, progress := range unitResources.DownloadProgress {
112
apiRes.DownloadProgress[resName] = progress
115
result.UnitResources = append(result.UnitResources, apiRes)
100
118
result.CharmStoreResources = make([]CharmResource, len(svcRes.CharmStoreResources))
205
func singletonError(err error) (error, bool) {
206
sameErr := func(err2 error) (error, bool) {
207
return err2, err.Error() == err2.Error()
209
switch params.ErrCode(err) {
210
case params.CodeCannotEnterScopeYet:
211
return sameErr(state.ErrCannotEnterScopeYet)
212
case params.CodeCannotEnterScope:
213
return sameErr(state.ErrCannotEnterScope)
214
case params.CodeUnitHasSubordinates:
215
return sameErr(state.ErrUnitHasSubordinates)
216
case params.CodeDead:
217
return sameErr(state.ErrDead)
218
case params.CodeExcessiveContention:
219
return sameErr(txn.ErrExcessiveContention)
220
case params.CodeLeadershipClaimDenied:
221
return sameErr(leadership.ErrClaimDenied)
222
case params.CodeLeaseClaimDenied:
223
return sameErr(lease.ErrClaimDenied)
224
case params.CodeNotFound:
225
if err, ok := sameErr(common.ErrBadId); ok {
228
return sameErr(common.ErrUnknownWatcher)
229
case params.CodeUnauthorized:
230
if err, ok := sameErr(common.ErrBadCreds); ok {
233
if err, ok := sameErr(common.ErrPerm); ok {
236
return sameErr(common.ErrNotLoggedIn)
237
case params.CodeStopped:
238
return sameErr(common.ErrStoppedWatcher)
239
case params.CodeTryAgain:
240
return sameErr(common.ErrTryAgain)
241
case params.CodeActionNotAvailable:
242
return sameErr(common.ErrActionNotAvailable)
248
// RestoreError makes a best effort at converting the given error
249
// back into an error originally converted by ServerError().
250
func RestoreError(err error) error {
251
err = errors.Cause(err)
253
if apiErr, ok := err.(*params.Error); !ok {
255
} else if apiErr == nil {
258
if params.ErrCode(err) == "" {
263
if singleton, ok := singletonError(err); ok {
267
// TODO(ericsnow) Support the other error types handled by ServerError().
269
case params.IsCodeUnauthorized(err):
270
return errors.NewUnauthorized(nil, msg)
271
case params.IsCodeNotFound(err):
272
// TODO(ericsnow) UnknownModelError should be handled here too.
273
// ...by parsing msg?
274
return errors.NewNotFound(nil, msg)
275
case params.IsCodeAlreadyExists(err):
276
return errors.NewAlreadyExists(nil, msg)
277
case params.IsCodeNotAssigned(err):
278
return errors.NewNotAssigned(nil, msg)
279
case params.IsCodeHasAssignedUnits(err):
280
// TODO(ericsnow) Handle state.HasAssignedUnitsError here.
281
// ...by parsing msg?
283
case params.IsCodeNoAddressSet(err):
284
// TODO(ericsnow) Handle isNoAddressSetError here.
285
// ...by parsing msg?
287
case params.IsCodeNotProvisioned(err):
288
return errors.NewNotProvisioned(nil, msg)
289
case params.IsCodeUpgradeInProgress(err):
290
// TODO(ericsnow) Handle state.UpgradeInProgressError here.
291
// ...by parsing msg?
293
case params.IsCodeMachineHasAttachedStorage(err):
294
// TODO(ericsnow) Handle state.HasAttachmentsError here.
295
// ...by parsing msg?
297
case params.IsCodeNotSupported(err):
298
return errors.NewNotSupported(nil, msg)
299
case params.IsBadRequest(err):
300
return errors.NewBadRequest(nil, msg)
301
case params.IsMethodNotAllowed(err):
302
return errors.NewMethodNotAllowed(nil, msg)
303
case params.ErrCode(err) == params.CodeDischargeRequired:
304
// TODO(ericsnow) Handle DischargeRequiredError here.