~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/resource/api/helpers.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
import (
9
9
        "github.com/juju/errors"
10
10
        "github.com/juju/names"
 
11
        "github.com/juju/txn"
11
12
        charmresource "gopkg.in/juju/charm.v6-unstable/resource"
12
13
 
13
14
        "github.com/juju/juju/apiserver/common"
14
15
        "github.com/juju/juju/apiserver/params"
 
16
        "github.com/juju/juju/core/leadership"
 
17
        "github.com/juju/juju/core/lease"
15
18
        "github.com/juju/juju/resource"
 
19
        "github.com/juju/juju/state"
16
20
)
17
21
 
18
22
// Resource2API converts a resource.Resource into
34
38
 
35
39
        if apiResult.Error != nil {
36
40
                // TODO(ericsnow) Return the resources too?
37
 
                err := common.RestoreError(apiResult.Error)
 
41
                err := RestoreError(apiResult.Error)
38
42
                return resource.ServiceResources{}, errors.Trace(err)
39
43
        }
40
44
 
54
58
                if err != nil {
55
59
                        return resource.ServiceResources{}, errors.Annotate(err, "got bad data from server")
56
60
                }
 
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)
60
65
                        if err != nil {
61
66
                                return resource.ServiceResources{}, errors.Annotate(err, "got bad data from server")
62
67
                        }
 
68
                        resNames[res.Name] = true
63
69
                        unitResources.Resources = append(unitResources.Resources, res)
64
70
                }
 
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")
 
77
                                }
 
78
                                unitResources.DownloadProgress[resName] = progress
 
79
                        }
 
80
                }
65
81
                result.UnitResources = append(result.UnitResources, unitResources)
66
82
        }
67
83
 
76
92
        return result, nil
77
93
}
78
94
 
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))
83
99
        }
84
 
        unitResources := make(map[names.UnitTag]resource.UnitResources, len(svcRes.UnitResources))
85
 
        for _, unitRes := range svcRes.UnitResources {
86
 
                unitResources[unitRes.Tag] = unitRes
87
 
        }
88
100
 
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()},
93
105
                }
94
 
                for _, res := range unitResources[tag].Resources {
95
 
                        apiRes.Resources = append(apiRes.Resources, Resource2API(res))
96
 
                }
97
 
                result.UnitResources[i] = apiRes
 
106
                for _, unitRes := range unitResources.Resources {
 
107
                        apiRes.Resources = append(apiRes.Resources, Resource2API(unitRes))
 
108
                }
 
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
 
113
                        }
 
114
                }
 
115
                result.UnitResources = append(result.UnitResources, apiRes)
98
116
        }
99
117
 
100
118
        result.CharmStoreResources = make([]CharmResource, len(svcRes.CharmStoreResources))
183
201
        }
184
202
        return res, nil
185
203
}
 
204
 
 
205
func singletonError(err error) (error, bool) {
 
206
        sameErr := func(err2 error) (error, bool) {
 
207
                return err2, err.Error() == err2.Error()
 
208
        }
 
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 {
 
226
                        return err, ok
 
227
                }
 
228
                return sameErr(common.ErrUnknownWatcher)
 
229
        case params.CodeUnauthorized:
 
230
                if err, ok := sameErr(common.ErrBadCreds); ok {
 
231
                        return err, ok
 
232
                }
 
233
                if err, ok := sameErr(common.ErrPerm); ok {
 
234
                        return err, ok
 
235
                }
 
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)
 
243
        default:
 
244
                return nil, false
 
245
        }
 
246
}
 
247
 
 
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)
 
252
 
 
253
        if apiErr, ok := err.(*params.Error); !ok {
 
254
                return err
 
255
        } else if apiErr == nil {
 
256
                return nil
 
257
        }
 
258
        if params.ErrCode(err) == "" {
 
259
                return err
 
260
        }
 
261
        msg := err.Error()
 
262
 
 
263
        if singleton, ok := singletonError(err); ok {
 
264
                return singleton
 
265
        }
 
266
 
 
267
        // TODO(ericsnow) Support the other error types handled by ServerError().
 
268
        switch {
 
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?
 
282
                return err
 
283
        case params.IsCodeNoAddressSet(err):
 
284
                // TODO(ericsnow) Handle isNoAddressSetError here.
 
285
                // ...by parsing msg?
 
286
                return err
 
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?
 
292
                return err
 
293
        case params.IsCodeMachineHasAttachedStorage(err):
 
294
                // TODO(ericsnow) Handle state.HasAttachmentsError here.
 
295
                // ...by parsing msg?
 
296
                return err
 
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.
 
305
                return err
 
306
        default:
 
307
                return err
 
308
        }
 
309
}