blob: 4d1dd809c319f052e185400b146f5a6e8d3dfe7f [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"sync"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/log"
)
// A global map of rarely-changing configuration values.
var config = struct {
sync.RWMutex
m map[string]string
}{
m: make(map[string]string),
}
// A list of config keys that should be created by initConfig.
// (Any configuration keys should be listed here.)
var configKeys = []string{
"GerritUsername",
"GerritPassword",
}
// configEntity is how config values are represented in the datastore.
type configEntity struct {
Value string
}
// Config returns the value for the given key
// or the empty string if no such key exists.
func Config(c context.Context, key string) string {
config.RLock()
v, ok := config.m[key]
config.RUnlock()
if ok {
return v
}
config.Lock()
defer config.Unlock()
// Lookup might have happened after RUnlock; check again.
if v, ok := config.m[key]; ok {
return v
}
// Lookup config value in datastore.
k := datastore.NewKey(c, "Config", key, 0, nil)
ent := configEntity{}
if err := datastore.Get(c, k, &ent); err != nil {
log.Errorf(c, "Get Config: %v", err)
return ""
}
// Don't return or cache the dummy value.
if ent.Value == configDummy {
return ""
}
config.m[key] = ent.Value
return ent.Value
}
// initConfig is invoked by the initHandler to create an entity for each key in
// configKeys. This makes it easy to edit the configuration values using the
// Datastore Viewer in the App Engine dashboard.
func initConfig(c context.Context) {
for _, key := range configKeys {
err := datastore.RunInTransaction(c, func(c context.Context) error {
k := datastore.NewKey(c, "Config", key, 0, nil)
ent := configEntity{}
if err := datastore.Get(c, k, &ent); err == nil {
log.Infof(c, "huh? %v", key)
return nil
} else if err != datastore.ErrNoSuchEntity {
return err
}
ent.Value = configDummy
_, err := datastore.Put(c, k, &ent)
log.Infof(c, "BLAH BLAH %v", key)
return err
}, nil)
if err != nil {
log.Errorf(c, "initConfig %v: %v", key, err)
}
}
}
const configDummy = "[config value unset]"