blob: a77809da44dc3ea299729afffa09f127ad84c8e9 [file]
// 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 format implements a config client Backend that performs formatting
// on items.
//
// The available formats are registered during init() time via 'Register'.
package format
import (
"github.com/luci/luci-go/common/errors"
"github.com/luci/luci-go/luci_config/server/cfgclient/backend"
"golang.org/x/net/context"
)
// Backend is a backend.B implementation that applies Formatter
// transformations to the various Items that pass through it.
//
// Formatter transformations are registered explicitly to the Resolver
// descriptions of the types that they operate on. If an Item is already
// formatted, no further transformations will be applied.
type Backend struct {
// B is the underlying Backend that this Backend will pull data
// from.
backend.B
}
// Get implements backend.B.
func (b *Backend) Get(c context.Context, configSet, path string, p backend.Params) (*backend.Item, error) {
item, err := b.B.Get(c, configSet, path, p)
if err != nil {
return nil, err
}
if !p.FormatSpec.Unformatted() {
formatter, err := getFormatter(p.FormatSpec.Formatter)
if err != nil {
return nil, errors.Annotate(err).Reason("failed to get formatter for %(format)q").
D("format", p.FormatSpec).Err()
}
if err := b.formatItem(item, formatter, p.FormatSpec); err != nil {
return nil, errors.Annotate(err).Reason("failed to format item to %(format)q, data %(data)q").
D("format", p.FormatSpec.Formatter).
D("data", p.FormatSpec.Data).Err()
}
}
return item, nil
}
// GetAll implements backend.B.
func (b *Backend) GetAll(c context.Context, t backend.GetAllTarget, path string, p backend.Params) (
[]*backend.Item, error) {
items, err := b.B.GetAll(c, t, path, p)
if err != nil {
return nil, err
}
if !p.FormatSpec.Unformatted() {
formatter, err := getFormatter(p.FormatSpec.Formatter)
if err != nil {
return nil, errors.Annotate(err).Reason("failed to get formatter for %(format)q, data %(data)q").
D("format", p.FormatSpec.Formatter).
D("data", p.FormatSpec.Data).Err()
}
lme := errors.NewLazyMultiError(len(items))
for i, item := range items {
if err := b.formatItem(item, formatter, p.FormatSpec); err != nil {
lme.Assign(i, err)
}
}
if err := lme.Get(); err != nil {
return nil, errors.Annotate(err).Reason("failed to format items to %(format)q, data %(data)q").
D("format", p.FormatSpec.Formatter).
D("data", p.FormatSpec.Data).Err()
}
}
return items, nil
}
func (b *Backend) formatItem(it *backend.Item, formatter Formatter, fs backend.FormatSpec) error {
if !it.FormatSpec.Unformatted() {
// Item is already formatted.
return nil
}
// Item is not formatted, so format it.
content, err := formatter.FormatItem(it.Content, fs.Data)
if err != nil {
return errors.Annotate(err).Reason("failed to format item").Err()
}
it.Content = content
it.FormatSpec = fs
return nil
}