OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package model | 5 package model |
6 | 6 |
7 import ( | 7 import ( |
8 "crypto/sha256" | |
9 "encoding/base64" | |
10 "fmt" | |
11 "time" | 8 "time" |
12 | 9 |
13 "github.com/golang/protobuf/proto" | |
14 "golang.org/x/net/context" | 10 "golang.org/x/net/context" |
15 | 11 |
16 "github.com/luci/gae/service/datastore" | 12 "github.com/luci/gae/service/datastore" |
17 "github.com/luci/luci-go/common/clock" | 13 "github.com/luci/luci-go/common/clock" |
18 google_pb "github.com/luci/luci-go/common/proto/google" | 14 google_pb "github.com/luci/luci-go/common/proto/google" |
19 | 15 |
20 » "github.com/luci/luci-go/common/api/dm/service/v1" | 16 » dm "github.com/luci/luci-go/common/api/dm/service/v1" |
21 » "github.com/luci/luci-go/common/api/template" | |
22 ) | |
23 | |
24 var ( | |
25 » // QuestIDLength is the number of encoded bytes to use. It removes the | |
26 » // single padding character. | |
27 » QuestIDLength = base64.URLEncoding.EncodedLen(sha256.Size) - 1 | |
28 ) | |
29 | |
30 const ( | |
31 » // payloadMaxLength is the maximum size of the Quest Desc | |
32 » payloadMaxLength = 256 * 1024 | |
33 ) | 17 ) |
34 | 18 |
35 // NewQuest builds a new Quest object with a correct ID given the current | 19 // NewQuest builds a new Quest object with a correct ID given the current |
36 // contents of the Quest_Desc. It returns an error if the Desc is invalid. | 20 // contents of the Quest_Desc. It returns an error if the Desc is invalid. |
37 // | 21 // |
38 // This will also compactify the inner json Desc as a side effect. | 22 // Desc must already be Normalize()'d |
39 func NewQuest(c context.Context, desc *dm.Quest_Desc) (ret *Quest, err error) { | 23 func NewQuest(c context.Context, desc *dm.Quest_Desc) *Quest { |
40 » if len(desc.JsonPayload) > payloadMaxLength { | 24 » return &Quest{ID: desc.QuestID(), Desc: *desc, Created: clock.Now(c).UTC
()} |
41 » » return nil, fmt.Errorf("quest payload is too large: %d > %d", | |
42 » » » len(desc.JsonPayload), payloadMaxLength) | |
43 » } | |
44 » desc.JsonPayload, err = template.NormalizeJSON(desc.JsonPayload, true) | |
45 » if err != nil { | |
46 » » return | |
47 » } | |
48 | |
49 » data, err := proto.Marshal(desc) | |
50 » if err != nil { | |
51 » » panic(err) | |
52 » } | |
53 » h := sha256.Sum256(data) | |
54 | |
55 » ret = &Quest{ | |
56 » » ID: base64.URLEncoding.EncodeToString(h[:])[:QuestIDLength]
, | |
57 » » Desc: *desc, | |
58 » » Created: clock.Now(c).UTC(), | |
59 » } | |
60 » return | |
61 } | 25 } |
62 | 26 |
63 // Quest is the model for a job-to-run. Its questPayload should fully | 27 // Quest is the model for a job-to-run. Its questPayload should fully |
64 // describe the job to be done. | 28 // describe the job to be done. |
65 type Quest struct { | 29 type Quest struct { |
66 // ID is the base64 sha256 of questPayload | 30 // ID is the base64 sha256 of questPayload |
67 ID string `gae:"$id"` | 31 ID string `gae:"$id"` |
68 | 32 |
69 Desc dm.Quest_Desc `gae:",noindex"` | 33 Desc dm.Quest_Desc `gae:",noindex"` |
70 BuiltBy TemplateInfo `gae:",noindex"` | 34 BuiltBy TemplateInfo `gae:",noindex"` |
(...skipping 23 matching lines...) Expand all Loading... |
94 for i := range q.BuiltBy { | 58 for i := range q.BuiltBy { |
95 spec[i] = &q.BuiltBy[i] | 59 spec[i] = &q.BuiltBy[i] |
96 } | 60 } |
97 | 61 |
98 return &dm.Quest_Data{ | 62 return &dm.Quest_Data{ |
99 Created: google_pb.NewTimestamp(q.Created), | 63 Created: google_pb.NewTimestamp(q.Created), |
100 Desc: &q.Desc, | 64 Desc: &q.Desc, |
101 BuiltBy: spec, | 65 BuiltBy: spec, |
102 } | 66 } |
103 } | 67 } |
OLD | NEW |