| // Copyright 2020 The LUCI Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package cfgclient |
| |
| import ( |
| "context" |
| "sort" |
| |
| "github.com/golang/protobuf/jsonpb" |
| "github.com/golang/protobuf/proto" |
| |
| luciProto "go.chromium.org/luci/common/proto" |
| "go.chromium.org/luci/config" |
| ) |
| |
| // Destination receives a raw config file body, deserializes and stores it. |
| // |
| // See Get(...). |
| type Destination func(string) error |
| |
| // Bytes can be used to put the received config body into a byte slice. |
| func Bytes(out *[]byte) Destination { |
| return func(body string) error { |
| *out = []byte(body) |
| return nil |
| } |
| } |
| |
| // String can be used to put the received config body into a string. |
| func String(out *string) Destination { |
| return func(body string) error { |
| *out = body |
| return nil |
| } |
| } |
| |
| // ProtoText can be used to deserialize the received config body as a text proto |
| // message. |
| func ProtoText(msg proto.Message) Destination { |
| return func(body string) error { |
| return luciProto.UnmarshalTextML(body, msg) |
| } |
| } |
| |
| // ProtoJSON can be used to deserialize the received config body as a JSONPB |
| // message. |
| func ProtoJSON(msg proto.Message) Destination { |
| return func(body string) error { |
| return jsonpb.UnmarshalString(body, msg) |
| } |
| } |
| |
| // Get fetches and optionally deserializes a single config file. |
| // |
| // It is a convenience wrapper over Client(ctx).GetConfig(...). If you need |
| // something more advanced, use the client directly. |
| // |
| // If `dest` is given, it is used to deserialize and store the fetched config. |
| // If it is nil, the config body is ignored (but its metadata is still fetched). |
| // |
| // If `meta` is given, it receives the metadata about the config. |
| // |
| // Returns an error if the config can't be fetched or deserialized. |
| func Get(ctx context.Context, cs config.Set, path string, dest Destination, meta *config.Meta) error { |
| cfg, err := Client(ctx).GetConfig(ctx, cs, path, dest == nil) |
| if err != nil { |
| return err |
| } |
| if dest != nil { |
| if err := dest(cfg.Content); err != nil { |
| return err |
| } |
| } |
| if meta != nil { |
| *meta = cfg.Meta |
| } |
| return nil |
| } |
| |
| // ProjectsWithConfig returns a list of LUCI projects that have the given |
| // configuration file. |
| // |
| // It is a convenience wrapper over Client(ctx).GetProjectConfigs(...). If you |
| // need something more advanced, use the client directly. |
| func ProjectsWithConfig(ctx context.Context, path string) ([]string, error) { |
| cfgs, err := Client(ctx).GetProjectConfigs(ctx, path, true) |
| if err != nil { |
| return nil, err |
| } |
| projects := make([]string, 0, len(cfgs)) |
| for _, cfg := range cfgs { |
| if proj := cfg.ConfigSet.Project(); proj != "" { |
| projects = append(projects, proj) |
| } |
| } |
| sort.Strings(projects) |
| return projects, nil |
| } |