| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You 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 bufpluginconfig |
| |
| import ( |
| "context" |
| "fmt" |
| "io" |
| ) |
| |
| import ( |
| "go.opentelemetry.io/otel" |
| "go.opentelemetry.io/otel/codes" |
| |
| "go.uber.org/multierr" |
| ) |
| |
| import ( |
| "github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/encoding" |
| "github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage" |
| "github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/stringutil" |
| ) |
| |
| func getConfigForBucket(ctx context.Context, readBucket storage.ReadBucket, options []ConfigOption) (_ *Config, retErr error) { |
| ctx, span := otel.GetTracerProvider().Tracer("bufbuild/buf").Start(ctx, "get_plugin_config") |
| defer span.End() |
| defer func() { |
| if retErr != nil { |
| span.RecordError(retErr) |
| span.SetStatus(codes.Error, retErr.Error()) |
| } |
| }() |
| // This will be in the order of precedence. |
| var foundConfigFilePaths []string |
| // Go through all valid config file paths and see which ones are present. |
| // If none are present, return the default config. |
| // If multiple are present, error. |
| for _, configFilePath := range AllConfigFilePaths { |
| exists, err := storage.Exists(ctx, readBucket, configFilePath) |
| if err != nil { |
| return nil, err |
| } |
| if exists { |
| foundConfigFilePaths = append(foundConfigFilePaths, configFilePath) |
| } |
| } |
| switch len(foundConfigFilePaths) { |
| case 0: |
| // Did not find anything, return the default. |
| return newConfig(ExternalConfig{}, options) |
| case 1: |
| readObjectCloser, err := readBucket.Get(ctx, foundConfigFilePaths[0]) |
| if err != nil { |
| return nil, err |
| } |
| defer func() { |
| retErr = multierr.Append(retErr, readObjectCloser.Close()) |
| }() |
| data, err := io.ReadAll(readObjectCloser) |
| if err != nil { |
| return nil, err |
| } |
| return getConfigForDataInternal( |
| ctx, |
| encoding.UnmarshalYAMLNonStrict, |
| encoding.UnmarshalYAMLStrict, |
| data, |
| readObjectCloser.ExternalPath(), |
| options, |
| ) |
| default: |
| return nil, fmt.Errorf("only one plugin file can exist but found multiple plugin files: %s", stringutil.SliceToString(foundConfigFilePaths)) |
| } |
| } |
| |
| func getConfigForData(ctx context.Context, data []byte, options []ConfigOption) (*Config, error) { |
| _, span := otel.GetTracerProvider().Tracer("bufbuild/buf").Start(ctx, "get_plugin_config_for_data") |
| defer span.End() |
| config, err := getConfigForDataInternal( |
| ctx, |
| encoding.UnmarshalJSONOrYAMLNonStrict, |
| encoding.UnmarshalJSONOrYAMLStrict, |
| data, |
| "Plugin configuration data", |
| options, |
| ) |
| if err != nil { |
| span.RecordError(err) |
| span.SetStatus(codes.Error, err.Error()) |
| } |
| return config, err |
| } |
| |
| func getConfigForDataInternal( |
| ctx context.Context, |
| unmarshalNonStrict func([]byte, interface{}) error, |
| unmarshalStrict func([]byte, interface{}) error, |
| data []byte, |
| id string, |
| options []ConfigOption, |
| ) (*Config, error) { |
| var externalConfigVersion externalConfigVersion |
| if err := unmarshalNonStrict(data, &externalConfigVersion); err != nil { |
| return nil, err |
| } |
| if err := validateExternalConfigVersion(externalConfigVersion, id); err != nil { |
| return nil, err |
| } |
| var externalConfig ExternalConfig |
| if err := unmarshalStrict(data, &externalConfig); err != nil { |
| return nil, err |
| } |
| return newConfig(externalConfig, options) |
| } |
| |
| func validateExternalConfigVersion(externalConfigVersion externalConfigVersion, id string) error { |
| switch externalConfigVersion.Version { |
| case "": |
| return fmt.Errorf( |
| `%s has no version set. Please add "version: %s"`, |
| id, |
| V1Version, |
| ) |
| case V1Version: |
| return nil |
| default: |
| return fmt.Errorf( |
| `%s has an invalid "version: %s" set. Please add "version: %s"`, |
| id, |
| externalConfigVersion.Version, |
| V1Version, |
| ) |
| } |
| } |