Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1056)

Unified Diff: milo/appengine/common/config.go

Issue 2949783002: [milo] appengine/* -> * (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « milo/appengine/common/acl_test.go ('k') | milo/appengine/common/config_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: milo/appengine/common/config.go
diff --git a/milo/appengine/common/config.go b/milo/appengine/common/config.go
deleted file mode 100644
index 360df2da73c7df0872e4d50a7e79606172386fa5..0000000000000000000000000000000000000000
--- a/milo/appengine/common/config.go
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-package common
-
-import (
- "fmt"
- "time"
-
- "github.com/golang/protobuf/proto"
- "golang.org/x/net/context"
-
- "github.com/luci/gae/service/datastore"
- "github.com/luci/gae/service/info"
- "github.com/luci/luci-go/common/data/caching/proccache"
- "github.com/luci/luci-go/common/logging"
- "github.com/luci/luci-go/luci_config/server/cfgclient"
- "github.com/luci/luci-go/luci_config/server/cfgclient/backend"
- "github.com/luci/luci-go/luci_config/server/cfgclient/textproto"
-
- "github.com/luci/luci-go/milo/api/config"
-)
-
-// Project is a LUCI project.
-type Project struct {
- // The ID of the project, as per self defined. This is not the luci-config
- // name.
- ID string `gae:"$id"`
- // The luci-config name of the project.
- Name string
- // The Project data in protobuf binary format.
- Data []byte `gae:",noindex"`
-}
-
-// The key for the service config entity in datastore.
-const ServiceConfigID = "service_config"
-
-// ServiceConfig is a container for the instance's service config.
-type ServiceConfig struct {
- // ID is the datastore key. This should be static, as there should only be
- // one service config.
- ID string `gae:"$id"`
- // Revision is the revision of the config, taken from luci-config. This is used
- // to determine if the entry needs to be refreshed.
- Revision string
- // Data is the binary proto of the config.
- Data []byte `gae:",noindex"`
- // Text is the text format of the config. For human consumption only.
- Text string `gae:",noindex"`
- // LastUpdated is the time this config was last updated.
- LastUpdated time.Time
-}
-
-// GetServiceConfig returns the service (aka global) config for the current
-// instance of Milo from the datastore. Returns an empty config and warn heavily
-// if none is found.
-// TODO(hinoka): Use process cache to cache configs.
-func GetSettings(c context.Context) *config.Settings {
- settings := config.Settings{
- Buildbot: &config.Settings_Buildbot{},
- }
-
- msg, err := GetCurrentServiceConfig(c)
- if err != nil {
- // The service config does not exist, just return an empty config
- // and complain loudly in the logs.
- logging.WithError(err).Errorf(c,
- "Encountered error while loading service config, using empty config.")
- return &settings
- }
-
- err = proto.Unmarshal(msg.Data, &settings)
- if err != nil {
- // The service config is broken, just return an empty config
- // and complain loudly in the logs.
- logging.WithError(err).Errorf(c,
- "Encountered error while unmarshalling service config, using empty config.")
- // Zero out the message just incase something got written in.
- settings = config.Settings{Buildbot: &config.Settings_Buildbot{}}
- }
-
- return &settings
-}
-
-// GetCurrentServiceConfig gets the service config for the instance from either
-// process cache or datastore cache.
-func GetCurrentServiceConfig(c context.Context) (*ServiceConfig, error) {
- // This maker function is used to do the actual fetch of the ServiceConfig
- // from datastore. It is called if the ServiceConfig is not in proc cache.
- maker := func() (interface{}, time.Duration, error) {
- msg := ServiceConfig{ID: ServiceConfigID}
- err := datastore.Get(c, &msg)
- if err != nil {
- return nil, time.Minute, err
- }
- logging.Infof(c, "loaded service config from datastore")
- return msg, time.Minute, nil
- }
- item, err := proccache.GetOrMake(c, ServiceConfigID, maker)
- if err != nil {
- return nil, fmt.Errorf("failed to get service config: %s", err.Error())
- }
- if msg, ok := item.(ServiceConfig); ok {
- logging.Infof(c, "loaded config entry from %s", msg.LastUpdated.Format(time.RFC3339))
- return &msg, nil
- }
- return nil, fmt.Errorf("could not load service config %#v", item)
-}
-
-// UpdateServiceConfig fetches the service config from luci-config
-// and then stores a snapshot of the configuration in datastore.
-func UpdateServiceConfig(c context.Context) error {
- // Load the settings from luci-config.
- cs := string(cfgclient.CurrentServiceConfigSet(c))
- // Acquire the raw config client.
- lucicfg := backend.Get(c).GetConfigInterface(c, backend.AsService)
- // Our global config name is called settings.cfg.
- cfg, err := lucicfg.GetConfig(c, cs, "settings.cfg", false)
- if err != nil {
- return fmt.Errorf("could not load settings.cfg from luci-config: %s", err)
- }
- settings := &config.Settings{}
- err = proto.UnmarshalText(cfg.Content, settings)
- if err != nil {
- return fmt.Errorf("could not unmarshal proto from luci-config:\n%s", cfg.Content)
- }
- newConfig := ServiceConfig{
- ID: ServiceConfigID,
- Text: cfg.Content,
- Revision: cfg.Revision,
- LastUpdated: time.Now().UTC(),
- }
- newConfig.Data, err = proto.Marshal(settings)
- if err != nil {
- return fmt.Errorf("could not marshal proto into binary\n%s", newConfig.Text)
- }
-
- // Do the revision check & swap in a datastore transaction.
- err = datastore.RunInTransaction(c, func(c context.Context) error {
- oldConfig := ServiceConfig{ID: ServiceConfigID}
- err := datastore.Get(c, &oldConfig)
- switch err {
- case datastore.ErrNoSuchEntity:
- // Might be the first time this has run.
- logging.WithError(err).Warningf(c, "No existing service config.")
- case nil:
- // Continue
- default:
- return fmt.Errorf("could not load existing config: %s", err)
- }
- // Check to see if we need to update
- if oldConfig.Revision == newConfig.Revision {
- logging.Infof(c, "revisions matched (%s), no need to update", oldConfig.Revision)
- return nil
- }
- logging.Infof(c, "revisions differ (old %s, new %s), updating",
- oldConfig.Revision, newConfig.Revision)
- return datastore.Put(c, &newConfig)
- }, nil)
-
- if err != nil {
- return fmt.Errorf("failed to update config entry in transaction", err)
- }
- logging.Infof(c, "successfully updated to new config")
-
- return nil
-}
-
-// UpdateProjectConfigs internal project configuration based off luci-config.
-// update updates Milo's configuration based off luci config. This includes
-// scanning through all project and extract all console configs.
-func UpdateProjectConfigs(c context.Context) error {
- cfgName := info.AppID(c) + ".cfg"
-
- var (
- configs []*config.Project
- metas []*cfgclient.Meta
- )
- logging.Debugf(c, "fetching configs for %s", cfgName)
- if err := cfgclient.Projects(c, cfgclient.AsService, cfgName, textproto.Slice(&configs), &metas); err != nil {
- logging.WithError(err).Errorf(c, "Encountered error while getting project config for %s", cfgName)
- return err
- }
-
- // A map of project ID to project.
- projects := map[string]*Project{}
- for i, proj := range configs {
- projectName, _, _ := metas[i].ConfigSet.SplitProject()
-
- logging.Infof(c, "Prossing %s", projectName)
- if dup, ok := projects[proj.ID]; ok {
- return fmt.Errorf(
- "Duplicate project ID: %s. (%s and %s)", proj.ID, dup.Name, projectName)
- }
- p := &Project{
- ID: proj.ID,
- Name: string(projectName),
- }
- projects[proj.ID] = p
-
- var err error
- p.Data, err = proto.Marshal(proj)
- if err != nil {
- return err
- }
- }
-
- // Now load all the data into the datastore.
- projs := make([]*Project, 0, len(projects))
- for _, proj := range projects {
- projs = append(projs, proj)
- }
- if err := datastore.Put(c, projs); err != nil {
- return err
- }
-
- // Delete entries that no longer exist.
- q := datastore.NewQuery("Project").KeysOnly(true)
- allProjs := []Project{}
- datastore.GetAll(c, q, &allProjs)
- toDelete := []Project{}
- for _, proj := range allProjs {
- if _, ok := projects[proj.ID]; !ok {
- toDelete = append(toDelete, proj)
- }
- }
- datastore.Delete(c, toDelete)
-
- return nil
-}
-
-// GetAllProjects returns all registered projects.
-func GetAllProjects(c context.Context) ([]*config.Project, error) {
- q := datastore.NewQuery("Project")
- q.Order("ID")
-
- ps := []*Project{}
- err := datastore.GetAll(c, q, &ps)
- if err != nil {
- return nil, err
- }
- results := make([]*config.Project, len(ps))
- for i, p := range ps {
- results[i] = &config.Project{}
- if err := proto.Unmarshal(p.Data, results[i]); err != nil {
- return nil, err
- }
- }
- return results, nil
-}
-
-// GetProject returns the requested project.
-func GetProject(c context.Context, projName string) (*config.Project, error) {
- // Next, Try datastore
- p := Project{ID: projName}
- if err := datastore.Get(c, &p); err != nil {
- return nil, err
- }
- mp := config.Project{}
- if err := proto.Unmarshal(p.Data, &mp); err != nil {
- return nil, err
- }
-
- return &mp, nil
-}
-
-// GetConsole returns the requested console instance.
-func GetConsole(c context.Context, projName, consoleName string) (*config.Console, error) {
- p, err := GetProject(c, projName)
- if err != nil {
- return nil, err
- }
- for _, cs := range p.Consoles {
- if cs.Name == consoleName {
- return cs, nil
- }
- }
- return nil, fmt.Errorf("Console %s not found in project %s", consoleName, projName)
-}
« no previous file with comments | « milo/appengine/common/acl_test.go ('k') | milo/appengine/common/config_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698