blob: c4d25267dfb378e3124a9769aa4c274e990d950d [file]
// Copyright 2018 The Chromium 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 config
import (
"context"
ds "go.chromium.org/luci/gae/service/datastore"
tricium "infra/tricium/api/v1"
)
// projectConfig contains a Tricium project config for one config.
type projectConfig struct {
Name string `gae:"$id"`
Parent *ds.Key `gae:"$parent"`
Revision string
ProjectConfig tricium.ProjectConfig
}
// serviceConfig is the single service config for this Tricium instance.
type serviceConfig struct {
ID int64 `gae:"$id"`
Parent *ds.Key `gae:"$parent"`
Revision string
ServiceConfig tricium.ServiceConfig
}
// By putting all config entities under one common parent, this makes it so
// that all configs are part of one entity group, so reads of all project
// configs in one query can be strongly consistent. See https://goo.gl/YgmiQF.
func rootKey(c context.Context) *ds.Key {
return ds.MakeKey(c, "configRoot", 1)
}
// getAllProjectConfigs retrieves stored project configs.
func getAllProjectConfigs(c context.Context) (map[string]*tricium.ProjectConfig, error) {
var storedConfigs []*projectConfig
q := ds.NewQuery("projectConfig").Ancestor(rootKey(c))
if err := ds.GetAll(c, q, &storedConfigs); err != nil {
return nil, err
}
configs := map[string]*tricium.ProjectConfig{}
for _, stored := range storedConfigs {
configs[stored.Name] = &stored.ProjectConfig
}
return configs, nil
}
// getStoredProjectConfigRevisions retrieves revisions of project configs.
//
// If there are no project configs stored yet, this will return an empty map.
func getStoredProjectConfigRevisions(c context.Context) (map[string]string, error) {
var storedConfigs []*projectConfig
q := ds.NewQuery("projectConfig").Ancestor(rootKey(c))
if err := ds.GetAll(c, q, &storedConfigs); err != nil {
return nil, err
}
revisions := map[string]string{}
for _, stored := range storedConfigs {
revisions[stored.Name] = stored.Revision
}
return revisions, nil
}
// getProjectConfig retrieves one project config by name.
func getProjectConfig(c context.Context, name string) (*tricium.ProjectConfig, error) {
stored := &projectConfig{Name: name, Parent: rootKey(c)}
if err := ds.Get(c, stored); err != nil {
return nil, err
}
return &stored.ProjectConfig, nil
}
// getServiceConfig retrieves the stored service config.
func getServiceConfig(c context.Context) (*tricium.ServiceConfig, error) {
stored := &serviceConfig{ID: 1, Parent: rootKey(c)}
if err := ds.Get(c, stored); err != nil {
return nil, err
}
return &stored.ServiceConfig, nil
}
// getStoredServiceConfigRevision retrieves the current service config revision.
//
// If there's no service config stored yet, empty string shall be returned.
func getStoredServiceConfigRevision(c context.Context) (string, error) {
stored := &serviceConfig{ID: 1, Parent: rootKey(c)}
err := ds.Get(c, stored)
if err == ds.ErrNoSuchEntity {
return "", nil
}
if err != nil {
return "", err
}
return stored.Revision, nil
}
// setProjectConfig stores a project config by name.
func setProjectConfig(c context.Context, name string, revision string, pc *tricium.ProjectConfig) error {
return ds.Put(c, &projectConfig{
Name: name,
Parent: rootKey(c),
Revision: revision,
ProjectConfig: *pc,
})
}
// setServiceConfig set the stored service config.
func setServiceConfig(c context.Context, revision string, sc *tricium.ServiceConfig) error {
return ds.Put(c, &serviceConfig{
ID: 1,
Parent: rootKey(c),
Revision: revision,
ServiceConfig: *sc,
})
}
// deleteProjectConfigs removes project configs with the given names.
func deleteProjectConfigs(c context.Context, names []string) error {
var keys []*ds.Key
for _, name := range names {
keys = append(keys, ds.NewKey(c, "projectConfig", name, 0, rootKey(c)))
}
return ds.Delete(c, keys)
}