Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package registration | 5 package registration |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 ds "github.com/luci/gae/service/datastore" | |
| 9 "github.com/luci/luci-go/appengine/logdog/coordinator" | |
| 10 "github.com/luci/luci-go/appengine/logdog/coordinator/hierarchy" | |
| 8 "github.com/luci/luci-go/common/api/logdog_coordinator/registration/v1" | 11 "github.com/luci/luci-go/common/api/logdog_coordinator/registration/v1" |
| 12 "github.com/luci/luci-go/common/clock" | |
| 13 "github.com/luci/luci-go/common/cryptorand" | |
| 14 "github.com/luci/luci-go/common/gcloud/pubsub" | |
| 9 "github.com/luci/luci-go/common/grpcutil" | 15 "github.com/luci/luci-go/common/grpcutil" |
| 16 "github.com/luci/luci-go/common/logdog/types" | |
| 17 log "github.com/luci/luci-go/common/logging" | |
| 18 | |
| 10 "golang.org/x/net/context" | 19 "golang.org/x/net/context" |
| 20 "google.golang.org/grpc/codes" | |
|
nodir
2016/05/17 02:45:59
this block should go before the luci one
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 11 ) | 21 ) |
| 12 | 22 |
| 13 func (s *server) RegisterPrefix(c context.Context, req *logdog.RegisterPrefixReq uest) (*logdog.RegisterPrefixResponse, error) { | 23 func (s *server) RegisterPrefix(c context.Context, req *logdog.RegisterPrefixReq uest) (*logdog.RegisterPrefixResponse, error) { |
| 14 » // TODO(dnj): Actually implement this endpoint. | 24 » log.Fields{ |
| 15 » return nil, grpcutil.Unimplemented | 25 » » "project": req.Project, |
| 26 » » "prefix": req.Prefix, | |
| 27 » » "source": req.SourceInfo, | |
| 28 » » "expiration": req.Expiration.Duration(), | |
| 29 » }.Debugf(c, "Registering log prefix.") | |
| 30 | |
| 31 » // Confirm that the Prefix is a valid stream name. | |
| 32 » prefix := types.StreamName(req.Prefix) | |
| 33 » if err := prefix.Validate(); err != nil { | |
| 34 » » log.WithError(err).Errorf(c, "Invalid prefix.") | |
|
nodir
2016/05/17 02:45:58
not sure about this. this is a user error, not a s
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 35 » » return nil, grpcutil.Errf(codes.InvalidArgument, "invalid prefix ") | |
| 36 » } | |
| 37 | |
| 38 » // Has the prefix already been registered? | |
| 39 » pfx := &coordinator.LogPrefix{ID: coordinator.LogPrefixID(prefix)} | |
| 40 | |
| 41 » // Check for existing prefix registration (non-transactional). | |
| 42 » di := ds.Get(c) | |
| 43 » switch exists, err := di.Exists(di.KeyForObj(pfx)); { | |
| 44 » case err != nil: | |
| 45 » » log.WithError(err).Errorf(c, "Failed to check for existing prefi x (non-transactional).") | |
| 46 » » return nil, grpcutil.Internal | |
| 47 | |
| 48 » case exists: | |
| 49 » » log.Errorf(c, "The prefix is already registered (non-transaction al).") | |
| 50 » » return nil, grpcutil.AlreadyExists | |
| 51 » } | |
| 52 | |
| 53 » // Load our service and project configurations. | |
| 54 » svcs := coordinator.GetServices(c) | |
| 55 » cfg, err := svcs.Config(c) | |
| 56 » if err != nil { | |
| 57 » » log.WithError(err).Errorf(c, "Failed to load service configurati on.") | |
| 58 » » return nil, grpcutil.Internal | |
| 59 » } | |
| 60 | |
| 61 » // Determine our Pub/Sub topic. | |
| 62 » var pubsubTopic pubsub.Topic | |
| 63 » switch t := cfg.Transport; t { | |
|
nodir
2016/05/17 02:45:58
switch is overkill here. Also you would have less
dnj (Google)
2016/05/17 14:44:33
Not sure that I agree here. Switch is a perfectly
| |
| 64 » case nil: | |
| 65 » » log.Errorf(c, "Missing transport configuration.") | |
| 66 » » return nil, grpcutil.Internal | |
| 67 | |
| 68 » default: | |
| 69 » » switch tps := t.GetPubsub(); tps { | |
|
nodir
2016/05/17 02:45:58
same here
| |
| 70 » » case nil: | |
| 71 » » » log.Errorf(c, "Missing transport Pub/Sub configuration." ) | |
| 72 » » » return nil, grpcutil.Internal | |
| 73 » » default: | |
| 74 » » » pubsubTopic = pubsub.NewTopic(tps.Project, tps.Topic) | |
| 75 » » } | |
| 76 » } | |
| 77 » if err := pubsubTopic.Validate(); err != nil { | |
| 78 » » log.Fields{ | |
| 79 » » » log.ErrorKey: err, | |
| 80 » » » "topic": pubsubTopic, | |
| 81 » » }.Errorf(c, "Invalid transport Pub/Sub topic.") | |
| 82 » » return nil, grpcutil.Internal | |
| 83 » } | |
| 84 | |
| 85 » // Best effort: register the stream prefix hierarchy components, includi ng the | |
| 86 » // separator. | |
| 87 » // | |
| 88 » // Determine which hierarchy components we need to add. | |
| 89 » comps := hierarchy.Components(prefix.AsPathPrefix("")) | |
| 90 » if comps, err = hierarchy.Missing(di, comps); err != nil { | |
| 91 » » log.WithError(err).Warningf(c, "Failed to probe for missing hier archy components.") | |
|
nodir
2016/05/17 02:45:58
now this is an error we want to notice as opposed
dnj (Google)
2016/05/17 14:44:33
This is actually not a big deal, since hierarchy c
| |
| 92 » } | |
| 93 | |
| 94 » // Before we go into transaction, try and put these entries. This should not | |
| 95 » // be contested, since components don't share an entity root. | |
| 96 » // | |
| 97 » // If this fails, that's okay; we'll handle this when the stream gets | |
| 98 » // registered. | |
| 99 » if err := hierarchy.PutMulti(di, comps); err != nil { | |
|
nodir
2016/05/17 02:45:59
in hierarchy.go you need to update comment
"This e
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 100 » » log.WithError(err).Infof(c, "Failed to add missing hierarchy com ponents.") | |
| 101 » } | |
| 102 | |
| 103 » // The prefix doesn't appear to be registered. Prepare to transactionall y | |
| 104 » // register it. | |
| 105 » now := clock.Now(c).UTC() | |
| 106 | |
| 107 » // Generate a prefix secret. | |
| 108 » secret := make(types.PrefixSecret, types.PrefixSecretLength) | |
| 109 » secretSize, err := cryptorand.Read(c, []byte(secret)) | |
|
nodir
2016/05/17 02:45:58
secretSize is unnecessary because according to htt
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 110 » if err != nil { | |
| 111 » » log.WithError(err).Errorf(c, "Failed to generate prefix secret." ) | |
| 112 » » return nil, grpcutil.Internal | |
| 113 » } | |
| 114 | |
| 115 » secret = secret[:secretSize] // Should be no-op. | |
|
nodir
2016/05/17 02:45:58
unnecessary
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 116 » if err := secret.Validate(); err != nil { | |
|
nodir
2016/05/17 02:45:59
will always return nil because it checks only leng
dnj (Google)
2016/05/17 14:44:32
Correct, but I am going to do it anyway, because i
| |
| 117 » » log.WithError(err).Errorf(c, "Generated invalid prefix secret.") | |
| 118 » » return nil, grpcutil.Internal | |
| 119 » } | |
| 120 | |
| 121 » // Transactionally register the prefix. | |
| 122 » err = di.RunInTransaction(func(c context.Context) error { | |
| 123 » » di := ds.Get(c) | |
| 124 | |
| 125 » » // Check if this Prefix exists (transactional). | |
| 126 » » switch exists, err := di.Exists(di.KeyForObj(pfx)); { | |
| 127 » » case err != nil: | |
| 128 » » » log.WithError(err).Errorf(c, "Failed to check for existi ng prefix (transactional).") | |
| 129 » » » return grpcutil.Internal | |
| 130 | |
| 131 » » case exists: | |
| 132 » » » log.Errorf(c, "The prefix is already registered (transac tional).") | |
| 133 » » » return grpcutil.AlreadyExists | |
| 134 » » } | |
| 135 | |
| 136 » » // The Prefix is not registered, so let's register it. | |
| 137 » » pfx.Created = now | |
| 138 » » pfx.Prefix = string(prefix) | |
| 139 » » pfx.Source = req.SourceInfo | |
| 140 » » pfx.Secret = []byte(secret) | |
| 141 | |
| 142 » » if err := di.Put(pfx); err != nil { | |
| 143 » » » log.WithError(err).Errorf(c, "Failed to register prefix. ") | |
| 144 » » » return grpcutil.Internal | |
| 145 » » } | |
| 146 | |
| 147 » » log.Infof(c, "The prefix was successfully registered.") | |
| 148 » » return nil | |
| 149 » }, nil) | |
| 150 » if err != nil { | |
| 151 » » log.WithError(err).Errorf(c, "Failed to register prefix (transac tional).") | |
|
nodir
2016/05/17 02:45:58
some cases of errors are already logged inside the
dnj (Google)
2016/05/17 14:44:33
Yes, but that's fine.
| |
| 152 » » return nil, err | |
| 153 » } | |
| 154 | |
| 155 » return &logdog.RegisterPrefixResponse{ | |
| 156 » » Secret: []byte(secret), | |
|
nodir
2016/05/17 02:45:58
types.PrefixSecret has a comment
"This is a Base6
dnj (Google)
2016/05/17 14:44:33
Done.
| |
| 157 » » LogBundleTopic: string(pubsubTopic), | |
| 158 » }, nil | |
| 16 } | 159 } |
| OLD | NEW |