|
| 1 | +/* |
| 2 | +Copyright 2020 The Kubernetes Authors. |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +*/ |
| 16 | + |
| 17 | +package opentelemetry |
| 18 | + |
| 19 | +import ( |
| 20 | + "fmt" |
| 21 | + "io/ioutil" |
| 22 | + "net/url" |
| 23 | + |
| 24 | + "k8s.io/apimachinery/pkg/runtime" |
| 25 | + "k8s.io/apimachinery/pkg/util/validation/field" |
| 26 | + "k8s.io/apiserver/pkg/apis/apiserver" |
| 27 | + "k8s.io/apiserver/pkg/apis/apiserver/install" |
| 28 | + "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1" |
| 29 | + "sigs.k8s.io/yaml" |
| 30 | +) |
| 31 | + |
| 32 | +var cfgScheme = runtime.NewScheme() |
| 33 | + |
| 34 | +func init() { |
| 35 | + install.Install(cfgScheme) |
| 36 | +} |
| 37 | + |
| 38 | +// ReadOpenTelemetryConfiguration reads the opentelemetry configuration from a file |
| 39 | +func ReadOpenTelemetryConfiguration(configFilePath string) (*apiserver.OpenTelemetryClientConfiguration, error) { |
| 40 | + if configFilePath == "" { |
| 41 | + return nil, nil |
| 42 | + } |
| 43 | + data, err := ioutil.ReadFile(configFilePath) |
| 44 | + if err != nil { |
| 45 | + return nil, fmt.Errorf("unable to read opentelemetry configuration from %q [%v]", configFilePath, err) |
| 46 | + } |
| 47 | + var decodedConfig v1alpha1.OpenTelemetryClientConfiguration |
| 48 | + err = yaml.Unmarshal(data, &decodedConfig) |
| 49 | + if err != nil { |
| 50 | + // we got an error where the decode wasn't related to a missing type |
| 51 | + return nil, err |
| 52 | + } |
| 53 | + if decodedConfig.Kind != "OpenTelemetryClientConfiguration" { |
| 54 | + return nil, fmt.Errorf("invalid service configuration object %q", decodedConfig.Kind) |
| 55 | + } |
| 56 | + internalConfig := &apiserver.OpenTelemetryClientConfiguration{} |
| 57 | + if err := cfgScheme.Convert(&decodedConfig, internalConfig, nil); err != nil { |
| 58 | + // we got an error where the decode wasn't related to a missing type |
| 59 | + return nil, err |
| 60 | + } |
| 61 | + return internalConfig, nil |
| 62 | +} |
| 63 | + |
| 64 | +// ValidateOpenTelemetryConfiguration validates the opentelemetry configuration |
| 65 | +func ValidateOpenTelemetryConfiguration(config *apiserver.OpenTelemetryClientConfiguration) field.ErrorList { |
| 66 | + allErrs := field.ErrorList{} |
| 67 | + if config == nil { |
| 68 | + // OpenTelemetry is disabled |
| 69 | + return allErrs |
| 70 | + } |
| 71 | + if config.Service != nil && config.URL != nil { |
| 72 | + allErrs = append(allErrs, field.Invalid( |
| 73 | + field.NewPath("service"), |
| 74 | + config.Service, |
| 75 | + "Service and URL cannot both be set")) |
| 76 | + } |
| 77 | + if config.Service != nil { |
| 78 | + allErrs = append(allErrs, validateService(config.Service, field.NewPath("service"))...) |
| 79 | + } |
| 80 | + if config.URL != nil { |
| 81 | + allErrs = append(allErrs, validateURL(*config.URL, field.NewPath("url"))...) |
| 82 | + } |
| 83 | + return allErrs |
| 84 | +} |
| 85 | + |
| 86 | +func validateService(service *apiserver.ServiceReference, fldPath *field.Path) field.ErrorList { |
| 87 | + allErrors := field.ErrorList{} |
| 88 | + |
| 89 | + if len(service.Name) == 0 { |
| 90 | + allErrors = append(allErrors, field.Required(fldPath.Child("name"), "service name is required")) |
| 91 | + } |
| 92 | + |
| 93 | + if len(service.Namespace) == 0 { |
| 94 | + allErrors = append(allErrors, field.Required(fldPath.Child("namespace"), "service namespace is required")) |
| 95 | + } |
| 96 | + return allErrors |
| 97 | +} |
| 98 | + |
| 99 | +func validateURL(u string, fldPath *field.Path) field.ErrorList { |
| 100 | + errs := field.ErrorList{} |
| 101 | + _, err := url.Parse(u) |
| 102 | + if err != nil { |
| 103 | + return append(errs, field.Invalid( |
| 104 | + fldPath, u, |
| 105 | + fmt.Sprintf("Unable to parse URL: %v", err))) |
| 106 | + } |
| 107 | + return errs |
| 108 | +} |
0 commit comments