Chromium Code Reviews| 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 service | 5 package service |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "errors" | |
| 9 "flag" | 8 "flag" |
| 10 "fmt" | 9 "fmt" |
| 11 "net/http" | 10 "net/http" |
| 11 "net/url" | |
| 12 "os" | 12 "os" |
| 13 "os/signal" | 13 "os/signal" |
| 14 "path/filepath" | 14 "path/filepath" |
| 15 "runtime/pprof" | 15 "runtime/pprof" |
| 16 "sync/atomic" | 16 "sync/atomic" |
| 17 "time" | 17 "time" |
| 18 | 18 |
| 19 "github.com/luci/luci-go/client/authcli" | 19 "github.com/luci/luci-go/client/authcli" |
| 20 "github.com/luci/luci-go/common/auth" | 20 "github.com/luci/luci-go/common/auth" |
| 21 "github.com/luci/luci-go/common/clock/clockflag" | |
| 22 "github.com/luci/luci-go/common/config/impl/filesystem" | |
| 21 "github.com/luci/luci-go/common/data/caching/proccache" | 23 "github.com/luci/luci-go/common/data/caching/proccache" |
| 24 "github.com/luci/luci-go/common/errors" | |
| 22 "github.com/luci/luci-go/common/gcloud/gs" | 25 "github.com/luci/luci-go/common/gcloud/gs" |
| 23 log "github.com/luci/luci-go/common/logging" | 26 log "github.com/luci/luci-go/common/logging" |
| 24 "github.com/luci/luci-go/common/logging/gologger" | 27 "github.com/luci/luci-go/common/logging/gologger" |
| 28 "github.com/luci/luci-go/common/proto/google" | |
| 25 "github.com/luci/luci-go/common/tsmon" | 29 "github.com/luci/luci-go/common/tsmon" |
| 26 "github.com/luci/luci-go/common/tsmon/target" | 30 "github.com/luci/luci-go/common/tsmon/target" |
| 27 "github.com/luci/luci-go/grpc/prpc" | 31 "github.com/luci/luci-go/grpc/prpc" |
| 28 "github.com/luci/luci-go/logdog/api/config/svcconfig" | 32 "github.com/luci/luci-go/logdog/api/config/svcconfig" |
| 29 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/services/v1" | 33 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/services/v1" |
| 30 "github.com/luci/luci-go/logdog/common/storage" | 34 "github.com/luci/luci-go/logdog/common/storage" |
| 31 "github.com/luci/luci-go/logdog/common/storage/bigtable" | 35 "github.com/luci/luci-go/logdog/common/storage/bigtable" |
| 32 "github.com/luci/luci-go/logdog/server/retryServicesClient" | 36 "github.com/luci/luci-go/logdog/server/retryServicesClient" |
| 33 "github.com/luci/luci-go/logdog/server/service/config" | 37 "github.com/luci/luci-go/logdog/server/service/config" |
| 34 "github.com/luci/luci-go/luci_config/common/cfgtypes" | 38 "github.com/luci/luci-go/luci_config/common/cfgtypes" |
| 39 "github.com/luci/luci-go/luci_config/server/cfgclient" | |
| 40 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client" | |
| 41 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig " | |
| 42 "github.com/luci/luci-go/luci_config/server/cfgclient/textproto" | |
| 35 | 43 |
| 36 "cloud.google.com/go/compute/metadata" | 44 "cloud.google.com/go/compute/metadata" |
| 37 "golang.org/x/net/context" | 45 "golang.org/x/net/context" |
| 38 "golang.org/x/oauth2" | 46 "golang.org/x/oauth2" |
| 39 "google.golang.org/api/option" | 47 "google.golang.org/api/option" |
| 40 ) | 48 ) |
| 41 | 49 |
| 42 var ( | 50 var ( |
| 43 // ErrInvalidConfig is an error that is returned when the supplied | 51 // ErrInvalidConfig is an error that is returned when the supplied |
| 44 // configuration is invalid. | 52 // configuration is invalid. |
| 45 ErrInvalidConfig = errors.New("invalid configuration") | 53 ErrInvalidConfig = errors.New("invalid configuration") |
| 46 | 54 |
| 47 // CoordinatorScopes is the set of OAuth2 scopes to use for the Coordina tor | 55 // CoordinatorScopes is the set of OAuth2 scopes to use for the Coordina tor |
| 48 // client. | 56 // client. |
| 49 CoordinatorScopes = []string{ | 57 CoordinatorScopes = []string{ |
| 50 auth.OAuthScopeEmail, | 58 auth.OAuthScopeEmail, |
| 51 } | 59 } |
| 52 ) | 60 ) |
| 53 | 61 |
| 54 // projectConfigCacheDuration is the amount of time to cache a project's | 62 // projectConfigCacheDuration is the amount of time to cache a project's |
| 55 // configuration before reloading. | 63 // configuration before reloading. |
| 56 const projectConfigCacheDuration = 30 * time.Minute | 64 const ( |
| 65 » projectConfigCacheDuration = 30 * time.Minute | |
| 66 | |
| 67 » // minAuthTokenLifetime is the amount of time that an access token has b efore | |
| 68 » // expiring. | |
| 69 » minAuthTokenLifetime = 2 * time.Minute | |
| 70 ) | |
| 57 | 71 |
| 58 // Service is a base class full of common LogDog service application parameters. | 72 // Service is a base class full of common LogDog service application parameters. |
| 59 type Service struct { | 73 type Service struct { |
| 60 // Name is the name of this service. It is used for logging, metrics, an d | 74 // Name is the name of this service. It is used for logging, metrics, an d |
| 61 // user agent string generation. | 75 // user agent string generation. |
| 62 // | 76 // |
| 63 // If empty, a service name will be inferred from the command-line argum ents. | 77 // If empty, a service name will be inferred from the command-line argum ents. |
| 64 Name string | 78 Name string |
| 65 // Flags is the set of flags that will be used by the Service. | 79 // Flags is the set of flags that will be used by the Service. |
| 66 Flags flag.FlagSet | 80 Flags flag.FlagSet |
| 67 | 81 |
| 68 shutdownFunc atomic.Value | 82 shutdownFunc atomic.Value |
| 69 | 83 |
| 70 loggingFlags log.Config | 84 loggingFlags log.Config |
| 71 authFlags authcli.Flags | 85 authFlags authcli.Flags |
| 72 configFlags config.Flags | |
| 73 tsMonFlags tsmon.Flags | 86 tsMonFlags tsmon.Flags |
| 74 | 87 |
| 75 coordinatorHost string | 88 coordinatorHost string |
| 76 coordinatorInsecure bool | 89 coordinatorInsecure bool |
| 77 serviceID string | |
| 78 storageCredentialJSONPath string | 90 storageCredentialJSONPath string |
| 79 cpuProfilePath string | 91 cpuProfilePath string |
| 80 heapProfilePath string | 92 heapProfilePath string |
| 81 | 93 |
| 82 » coord logdog.ServicesClient | 94 » // onGCE is true if we're on GCE. We probe this exactly once. |
|
iannucci
2017/01/21 00:23:14
probe it... lazily? on init? from environ?
dnj
2017/01/21 01:37:31
Once during "Run". updated.
| |
| 83 » config *config.Manager | 95 » onGCE bool |
| 84 | 96 |
| 85 » onGCE bool | 97 » killCheckInterval clockflag.Duration |
| 98 » configFilePath string | |
| 99 » serviceConfig svcconfig.Config | |
| 100 | |
| 101 » // serviceID is the cloud project ID, which is also this service's uniqu e | |
| 102 » // ID. This can be specified by flag or, if on GCE, will automatically b e | |
| 103 » // probed from metadata. | |
| 104 » serviceID string | |
| 105 | |
| 106 » coord logdog.ServicesClient | |
| 86 } | 107 } |
| 87 | 108 |
| 88 // Run performs service-wide initialization and invokes the specified run | 109 // Run performs service-wide initialization and invokes the specified run |
| 89 // function. | 110 // function. |
| 90 func (s *Service) Run(c context.Context, f func(context.Context) error) { | 111 func (s *Service) Run(c context.Context, f func(context.Context) error) { |
| 91 c = gologger.StdConfig.Use(c) | 112 c = gologger.StdConfig.Use(c) |
| 92 | 113 |
| 93 // If a service name isn't specified, default to the base of the current | 114 // If a service name isn't specified, default to the base of the current |
| 94 // executable. | 115 // executable. |
| 95 if s.Name == "" { | 116 if s.Name == "" { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 | 164 |
| 144 if err := pprof.WriteHeapProfile(fd); err != nil { | 165 if err := pprof.WriteHeapProfile(fd); err != nil { |
| 145 log.Fields{ | 166 log.Fields{ |
| 146 log.ErrorKey: err, | 167 log.ErrorKey: err, |
| 147 "path": p, | 168 "path": p, |
| 148 }.Warningf(c, "Failed to write heap profile.") | 169 }.Warningf(c, "Failed to write heap profile.") |
| 149 } | 170 } |
| 150 }() | 171 }() |
| 151 } | 172 } |
| 152 | 173 |
| 153 // Are we running on a GCE intance? | |
| 154 if err := s.probeGCEEnvironment(c); err != nil { | |
| 155 log.WithError(err).Errorf(c, "Failed to probe GCE environment.") | |
| 156 return err | |
| 157 } | |
| 158 | |
| 159 // Validate the runtime environment. | 174 // Validate the runtime environment. |
| 160 if s.serviceID == "" { | 175 if s.serviceID == "" { |
| 161 » » return errors.New("no service ID was configured") | 176 » » return errors.New("no service ID was configured (-service-id)") |
| 162 } | 177 } |
| 163 | 178 |
| 179 // Install a process-wide cache. | |
| 180 c = proccache.Use(c, &proccache.Cache{}) | |
| 181 | |
| 164 // Configure our signal handler. It will listen for terminating signals and | 182 // Configure our signal handler. It will listen for terminating signals and |
| 165 // issue a shutdown signal if one is received. | 183 // issue a shutdown signal if one is received. |
| 166 signalC := make(chan os.Signal) | 184 signalC := make(chan os.Signal) |
| 167 go func(c context.Context) { | 185 go func(c context.Context) { |
| 168 hasShutdownAlready := false | 186 hasShutdownAlready := false |
| 169 for sig := range signalC { | 187 for sig := range signalC { |
| 170 if !hasShutdownAlready { | 188 if !hasShutdownAlready { |
| 171 hasShutdownAlready = true | 189 hasShutdownAlready = true |
| 172 | 190 |
| 173 log.Warningf(log.SetField(c, "signal", sig), "Re ceived close signal. Send again to terminate immediately.") | 191 log.Warningf(log.SetField(c, "signal", sig), "Re ceived close signal. Send again to terminate immediately.") |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 189 // Initialize our tsmon library. | 207 // Initialize our tsmon library. |
| 190 c = tsmon.WithState(c, tsmon.NewState()) | 208 c = tsmon.WithState(c, tsmon.NewState()) |
| 191 | 209 |
| 192 if err := tsmon.InitializeFromFlags(c, &s.tsMonFlags); err != nil { | 210 if err := tsmon.InitializeFromFlags(c, &s.tsMonFlags); err != nil { |
| 193 log.WithError(err).Warningf(c, "Failed to initialize monitoring; will continue without metrics.") | 211 log.WithError(err).Warningf(c, "Failed to initialize monitoring; will continue without metrics.") |
| 194 } | 212 } |
| 195 defer tsmon.Shutdown(c) | 213 defer tsmon.Shutdown(c) |
| 196 | 214 |
| 197 // Initialize our Client instantiations. | 215 // Initialize our Client instantiations. |
| 198 var err error | 216 var err error |
| 199 » s.coord, err = s.initCoordinatorClient(c) | 217 » if s.coord, err = s.initCoordinatorClient(c); err != nil { |
| 200 » if err != nil { | |
| 201 log.WithError(err).Errorf(c, "Failed to setup Coordinator client .") | 218 log.WithError(err).Errorf(c, "Failed to setup Coordinator client .") |
| 202 return err | 219 return err |
| 203 } | 220 } |
| 204 | 221 |
| 205 » s.config, err = s.initConfig(c) | 222 » // Initialize and install our config service and caching layers, and loa d our |
| 206 » if err != nil { | 223 » // initial service config. |
| 224 » if err := s.initConfig(&c); err != nil { | |
| 207 log.WithError(err).Errorf(c, "Failed to setup configuration.") | 225 log.WithError(err).Errorf(c, "Failed to setup configuration.") |
| 208 return err | 226 return err |
| 209 } | 227 } |
| 210 defer s.config.Close() | |
| 211 | 228 |
| 229 // Clear our shutdown function on termination. | |
| 212 defer s.SetShutdownFunc(nil) | 230 defer s.SetShutdownFunc(nil) |
| 213 | 231 |
| 214 // Install a process-wide cache. | |
| 215 c = proccache.Use(c, &proccache.Cache{}) | |
| 216 | |
| 217 // Run main service function. | 232 // Run main service function. |
| 218 return f(c) | 233 return f(c) |
| 219 } | 234 } |
| 220 | 235 |
| 221 func (s *Service) addFlags(c context.Context, fs *flag.FlagSet) { | 236 func (s *Service) addFlags(c context.Context, fs *flag.FlagSet) { |
| 222 // Initialize logging flags. | 237 // Initialize logging flags. |
| 223 s.loggingFlags.Level = log.Warning | 238 s.loggingFlags.Level = log.Warning |
| 224 s.loggingFlags.AddFlags(fs) | 239 s.loggingFlags.AddFlags(fs) |
| 225 | 240 |
| 226 // Initialize tsmon flags. | 241 // Initialize tsmon flags. |
| 227 s.tsMonFlags = tsmon.NewFlags() | 242 s.tsMonFlags = tsmon.NewFlags() |
| 228 s.tsMonFlags.Flush = tsmon.FlushAuto | 243 s.tsMonFlags.Flush = tsmon.FlushAuto |
| 229 s.tsMonFlags.Target.TargetType = target.TaskType | 244 s.tsMonFlags.Target.TargetType = target.TaskType |
| 230 s.tsMonFlags.Target.TaskJobName = s.Name | 245 s.tsMonFlags.Target.TaskJobName = s.Name |
| 231 s.tsMonFlags.Register(fs) | 246 s.tsMonFlags.Register(fs) |
| 232 | 247 |
| 233 s.authFlags.Register(fs, auth.Options{}) | 248 s.authFlags.Register(fs, auth.Options{}) |
| 234 s.configFlags.AddToFlagSet(fs) | |
| 235 | 249 |
| 236 fs.StringVar(&s.serviceID, "service-id", "", | 250 fs.StringVar(&s.serviceID, "service-id", "", |
| 237 "Specify the service ID that this instance is supporting. If emp ty, the service ID "+ | 251 "Specify the service ID that this instance is supporting. If emp ty, the service ID "+ |
| 238 "will attempt to be resolved by probing the local enviro nment. This probably will match the "+ | 252 "will attempt to be resolved by probing the local enviro nment. This probably will match the "+ |
| 239 "App ID of the Coordinator.") | 253 "App ID of the Coordinator.") |
| 240 fs.StringVar(&s.coordinatorHost, "coordinator", "", | 254 fs.StringVar(&s.coordinatorHost, "coordinator", "", |
| 241 "The Coordinator service's [host][:port].") | 255 "The Coordinator service's [host][:port].") |
| 242 fs.BoolVar(&s.coordinatorInsecure, "coordinator-insecure", false, | 256 fs.BoolVar(&s.coordinatorInsecure, "coordinator-insecure", false, |
| 243 "Connect to Coordinator over HTTP (instead of HTTPS).") | 257 "Connect to Coordinator over HTTP (instead of HTTPS).") |
| 244 fs.StringVar(&s.storageCredentialJSONPath, "storage-credential-json-path ", "", | 258 fs.StringVar(&s.storageCredentialJSONPath, "storage-credential-json-path ", "", |
| 245 "If supplied, the path of a JSON credential file to load and use for storage operations.") | 259 "If supplied, the path of a JSON credential file to load and use for storage operations.") |
| 246 fs.StringVar(&s.cpuProfilePath, "cpu-profile-path", "", | 260 fs.StringVar(&s.cpuProfilePath, "cpu-profile-path", "", |
| 247 "If supplied, enable CPU profiling and write the profile here.") | 261 "If supplied, enable CPU profiling and write the profile here.") |
| 248 fs.StringVar(&s.heapProfilePath, "heap-profile-path", "", | 262 fs.StringVar(&s.heapProfilePath, "heap-profile-path", "", |
| 249 "If supplied, enable CPU profiling and write the profile here.") | 263 "If supplied, enable CPU profiling and write the profile here.") |
| 264 fs.Var(&s.killCheckInterval, "config-kill-interval", | |
| 265 "If non-zero, poll for configuration changes and kill the applic ation if one is detected.") | |
|
iannucci
2017/01/21 00:23:14
ah, got it... that's why it was killfunc before. C
dnj
2017/01/21 01:37:31
Done.
| |
| 266 fs.StringVar(&s.configFilePath, "config-file-path", "", | |
| 267 "If set, load configuration from a local filesystem rooted here. ") | |
|
iannucci
2017/01/21 00:23:13
for testing? or will this be used in production?
dnj
2017/01/21 01:37:31
test
| |
| 250 } | 268 } |
| 251 | 269 |
| 252 // probeGCEEnvironment fills in any parameters that can be probed from Google | 270 // probeGCEEnvironment fills in any parameters that can be probed from Google |
| 253 // Compute Engine metadata. | 271 // Compute Engine metadata. |
| 254 // | 272 // |
| 255 // If we're not running on GCE, this will return nil. An error will only be | 273 // If we're not running on GCE, this will return nil. An error will only be |
| 256 // returned if an operation that is expected to work fails. | 274 // returned if an operation that is expected to work fails. |
| 257 func (s *Service) probeGCEEnvironment(c context.Context) error { | 275 func (s *Service) probeGCEEnvironment(c context.Context) error { |
| 258 s.onGCE = metadata.OnGCE() | 276 s.onGCE = metadata.OnGCE() |
| 259 if !s.onGCE { | 277 if !s.onGCE { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 prpcClient.Options.UserAgent = fmt.Sprintf("%s/%s", s.Name, prpc.Default UserAgent) | 312 prpcClient.Options.UserAgent = fmt.Sprintf("%s/%s", s.Name, prpc.Default UserAgent) |
| 295 if s.coordinatorInsecure { | 313 if s.coordinatorInsecure { |
| 296 prpcClient.Options.Insecure = true | 314 prpcClient.Options.Insecure = true |
| 297 } | 315 } |
| 298 sc := logdog.NewServicesPRPCClient(&prpcClient) | 316 sc := logdog.NewServicesPRPCClient(&prpcClient) |
| 299 | 317 |
| 300 // Wrap the resulting client in a retry harness. | 318 // Wrap the resulting client in a retry harness. |
| 301 return retryServicesClient.New(sc, nil), nil | 319 return retryServicesClient.New(sc, nil), nil |
| 302 } | 320 } |
| 303 | 321 |
| 304 func (s *Service) initConfig(c context.Context) (*config.Manager, error) { | 322 func (s *Service) initConfig(c *context.Context) error { |
| 305 » rt, err := s.AuthenticatedTransport(c, nil) | 323 » opts := config.CacheOptions{ |
| 306 » if err != nil { | 324 » » CacheExpiration: projectConfigCacheDuration, |
| 307 » » log.WithError(err).Errorf(c, "Failed to create config client.") | |
| 308 » » return nil, err | |
| 309 } | 325 } |
| 310 | 326 |
| 311 » s.configFlags.RoundTripper = rt | 327 » // If a configFilePath was specified, use a mock configuration service t hat |
| 312 » o, err := s.configFlags.CoordinatorOptions(c, s.coord) | 328 » // loads from a local file. |
| 313 » if err != nil { | 329 » var p client.Provider |
| 314 » » log.WithError(err).Errorf(c, "Failed to load configuration param eters.") | 330 » if s.configFilePath == "" { |
| 315 » » return nil, err | 331 » » ccfg, err := s.coord.GetConfig(*c, &google.Empty{}) |
| 332 » » if err != nil { | |
| 333 » » » return err | |
| 334 » » } | |
| 335 | |
| 336 » » // Determine our config service host. | |
| 337 » » // | |
| 338 » » // Older Coordinator instances may provide the full URL instead of the host, | |
| 339 » » // in which case we will extract the host from the URL. | |
| 340 » » host := ccfg.ConfigServiceHost | |
| 341 » » if host == "" { | |
| 342 » » » if ccfg.ConfigServiceUrl == "" { | |
| 343 » » » » return errors.New("coordinator does not specify a config service") | |
| 344 » » » } | |
| 345 » » » u, err := url.Parse(ccfg.ConfigServiceUrl) | |
| 346 » » » if err != nil { | |
| 347 » » » » return errors.Annotate(err).Reason("failed to pa rse config service URL").Err() | |
| 348 » » » } | |
| 349 » » » host = u.Host | |
| 350 » » } | |
| 351 | |
| 352 » » if ccfg.ConfigSet == "" { | |
| 353 » » » return errors.New("coordinator does not specify a config set") | |
| 354 » » } | |
| 355 | |
| 356 » » log.Fields{ | |
| 357 » » » "host": host, | |
| 358 » » }.Debugf(*c, "Using remote configuration service client.") | |
| 359 » » p = &client.RemoteProvider{ | |
| 360 » » » Host: host, | |
| 361 » » } | |
| 362 » } else { | |
| 363 » » // Test / Local: use filesystem config path. | |
| 364 » » ci, err := filesystem.New(s.configFilePath) | |
| 365 » » if err != nil { | |
| 366 » » » return err | |
| 367 » » } | |
| 368 » » p = &testconfig.Provider{Base: ci} | |
| 316 } | 369 } |
| 317 o.ServiceID = s.serviceID | |
| 318 o.ProjectConfigCacheDuration = projectConfigCacheDuration | |
| 319 o.KillFunc = s.shutdown | |
| 320 | 370 |
| 321 » return config.NewManager(c, *o) | 371 » // Add config caching layers. |
| 372 » *c = opts.WrapBackend(*c, &client.Backend{ | |
| 373 » » Provider: p, | |
| 374 » }) | |
| 375 | |
| 376 » // Load our service configuration. | |
| 377 » var meta cfgclient.Meta | |
| 378 » cset, path := s.ServiceConfigPath() | |
| 379 » if err := cfgclient.Get(*c, cfgclient.AsService, cset, path, textproto.M essage(&s.serviceConfig), &meta); err != nil { | |
| 380 » » return errors.Annotate(err).Reason("failed to load service confi g").Err() | |
| 381 » } | |
| 382 | |
| 383 » // Create a poller for our service config. | |
| 384 » if s.killCheckInterval > 0 { | |
| 385 » » poller := config.ChangePoller{ | |
| 386 » » » ConfigSet: cset, | |
| 387 » » » Path: path, | |
| 388 » » » CheckInterval: time.Duration(s.killCheckInterval), | |
| 389 » » » OnChange: s.shutdown, | |
|
iannucci
2017/01/21 00:23:14
os.Exit :p
*chants*
crash! crash! crash! crash! c
dnj
2017/01/21 01:37:31
I want to flush :(
| |
| 390 » » » ContentHash: meta.ContentHash, | |
| 391 » » } | |
| 392 » » go poller.Run(*c) | |
| 393 » } | |
| 394 » return nil | |
| 395 } | |
| 396 | |
| 397 // ServiceConfigPath returns the ConfigSet and path to the current service's | |
| 398 // configuration. | |
| 399 func (s *Service) ServiceConfigPath() (cfgtypes.ConfigSet, string) { | |
| 400 » return cfgtypes.ServiceConfigSet(s.serviceID), svcconfig.ServiceConfigPa th | |
| 401 } | |
| 402 | |
| 403 // ServiceConfig returns the configuration data for the current service. | |
| 404 func (s *Service) ServiceConfig() *svcconfig.Config { return &s.serviceConfig } | |
| 405 | |
| 406 // ProjectConfigPath returns the ConfigSet and path to the current service's | |
| 407 // project configuration for proj. | |
| 408 func (s *Service) ProjectConfigPath(proj cfgtypes.ProjectName) (cfgtypes.ConfigS et, string) { | |
| 409 » return cfgtypes.ProjectConfigSet(proj), svcconfig.ProjectConfigPath(s.se rviceID) | |
| 410 } | |
| 411 | |
| 412 // ProjectConfig returns the current service's project configuration for proj. | |
| 413 func (s *Service) ProjectConfig(c context.Context, proj cfgtypes.ProjectName) (* svcconfig.ProjectConfig, error) { | |
| 414 » cset, path := s.ProjectConfigPath(proj) | |
| 415 | |
| 416 » var pcfg svcconfig.ProjectConfig | |
| 417 » if err := cfgclient.Get(c, cfgclient.AsService, cset, path, textproto.Me ssage(&pcfg), nil); err != nil { | |
| 418 » » return nil, errors.Annotate(err).Reason("failed to load project config from %(cset)s.%(path)s"). | |
| 419 » » » D("cset", cset).D("path", path).Err() | |
| 420 » } | |
| 421 » return &pcfg, nil | |
| 322 } | 422 } |
| 323 | 423 |
| 324 // SetShutdownFunc sets the service shutdown function. | 424 // SetShutdownFunc sets the service shutdown function. |
| 325 func (s *Service) SetShutdownFunc(f func()) { | 425 func (s *Service) SetShutdownFunc(f func()) { |
| 326 s.shutdownFunc.Store(f) | 426 s.shutdownFunc.Store(f) |
| 327 } | 427 } |
| 328 | 428 |
| 329 func (s *Service) shutdown() { | 429 func (s *Service) shutdown() { |
| 330 v := s.shutdownFunc.Load() | 430 v := s.shutdownFunc.Load() |
| 331 if f, ok := v.(func()); ok { | 431 if f, ok := v.(func()); ok { |
| 332 f() | 432 f() |
| 333 } else { | 433 } else { |
| 334 s.shutdownImmediately() | 434 s.shutdownImmediately() |
| 335 } | 435 } |
| 336 } | 436 } |
| 337 | 437 |
| 338 func (s *Service) shutdownImmediately() { | 438 func (s *Service) shutdownImmediately() { |
| 339 os.Exit(1) | 439 os.Exit(1) |
| 340 } | 440 } |
| 341 | 441 |
| 342 // Config returns the cached service configuration. | |
| 343 func (s *Service) Config() *svcconfig.Config { | |
| 344 return s.config.Config() | |
| 345 } | |
| 346 | |
| 347 // ProjectConfig returns the cached project configuration. | |
| 348 // | |
| 349 // If the project configuration is not available, nil will be returned. | |
| 350 func (s *Service) ProjectConfig(c context.Context, proj cfgtypes.ProjectName) (* svcconfig.ProjectConfig, error) { | |
| 351 return s.config.ProjectConfig(c, proj) | |
| 352 } | |
| 353 | |
| 354 // Coordinator returns the cached Coordinator client. | 442 // Coordinator returns the cached Coordinator client. |
| 355 func (s *Service) Coordinator() logdog.ServicesClient { | 443 func (s *Service) Coordinator() logdog.ServicesClient { |
| 356 return s.coord | 444 return s.coord |
| 357 } | 445 } |
| 358 | 446 |
| 359 // ServiceID returns the service ID. | 447 // ServiceID returns the service ID. |
| 360 // | 448 // |
| 361 // This is synonymous with the cloud "project ID" and the AppEngine "app ID". | 449 // This is synonymous with the cloud "project ID" and the AppEngine "app ID". |
| 362 func (s *Service) ServiceID() string { | 450 func (s *Service) ServiceID() string { |
| 363 return s.serviceID | 451 return s.serviceID |
| 364 } | 452 } |
| 365 | 453 |
| 366 // IntermediateStorage instantiates the configured intermediate Storage | 454 // IntermediateStorage instantiates the configured intermediate Storage |
| 367 // instance. | 455 // instance. |
| 368 func (s *Service) IntermediateStorage(c context.Context) (storage.Storage, error ) { | 456 func (s *Service) IntermediateStorage(c context.Context) (storage.Storage, error ) { |
| 369 » cfg := s.config.Config() | 457 » cfg := s.ServiceConfig() |
| 370 if cfg.GetStorage() == nil { | 458 if cfg.GetStorage() == nil { |
| 371 log.Errorf(c, "Missing storage configuration.") | 459 log.Errorf(c, "Missing storage configuration.") |
| 372 return nil, ErrInvalidConfig | 460 return nil, ErrInvalidConfig |
| 373 } | 461 } |
| 374 | 462 |
| 375 btcfg := cfg.GetStorage().GetBigtable() | 463 btcfg := cfg.GetStorage().GetBigtable() |
| 376 if btcfg == nil { | 464 if btcfg == nil { |
| 377 log.Errorf(c, "Missing BigTable storage configuration") | 465 log.Errorf(c, "Missing BigTable storage configuration") |
| 378 return nil, ErrInvalidConfig | 466 return nil, ErrInvalidConfig |
| 379 } | 467 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 // | 557 // |
| 470 // An optional permutation function can be provided to modify those Options | 558 // An optional permutation function can be provided to modify those Options |
| 471 // before the Authenticator is created. | 559 // before the Authenticator is created. |
| 472 func (s *Service) TokenSource(c context.Context, f func(o *auth.Options)) (oauth 2.TokenSource, error) { | 560 func (s *Service) TokenSource(c context.Context, f func(o *auth.Options)) (oauth 2.TokenSource, error) { |
| 473 a, err := s.Authenticator(c, f) | 561 a, err := s.Authenticator(c, f) |
| 474 if err != nil { | 562 if err != nil { |
| 475 return nil, err | 563 return nil, err |
| 476 } | 564 } |
| 477 return a.TokenSource() | 565 return a.TokenSource() |
| 478 } | 566 } |
| OLD | NEW |