// ToAggregate converts the ErrorList into an errors.Aggregate. func (list ErrorList) ToAggregate() utilerrors.Aggregate { errs := make([]error, len(list)) for i := range list { errs[i] = list[i] } return utilerrors.NewAggregate(errs) }
// RESTMapping provides the REST mapping for the resource based on the // kind and version. This implementation supports multiple REST schemas and // return the first match. func (m MultiRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) { allMappings := []*RESTMapping{} errors := []error{} for _, t := range m { currMapping, err := t.RESTMapping(gk, versions...) // ignore "no match" errors, but any other error percolates back up if IsNoMatchError(err) { continue } if err != nil { errors = append(errors, err) continue } allMappings = append(allMappings, currMapping) } // if we got exactly one mapping, then use it even if other requested failed if len(allMappings) == 1 { return allMappings[0], nil } if len(allMappings) > 1 { var kinds []unversioned.GroupVersionKind for _, m := range allMappings { kinds = append(kinds, m.GroupVersionKind) } return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds} } if len(errors) > 0 { return nil, utilerrors.NewAggregate(errors) } return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")} }
func (c configValidationTest) testAuthInfo(authInfoName string, t *testing.T) { errs := validateAuthInfo(authInfoName, *c.config.AuthInfos[authInfoName]) if len(c.expectedErrorSubstring) != 0 { if len(errs) == 0 { t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) } for _, curr := range c.expectedErrorSubstring { if len(errs) != 0 && !strings.Contains(utilerrors.NewAggregate(errs).Error(), curr) { t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, utilerrors.NewAggregate(errs)) } } } else { if len(errs) != 0 { t.Errorf("Unexpected error: %v", utilerrors.NewAggregate(errs)) } } }
// EncodeList ensures that each object in an array is converted to a Unknown{} in serialized form. // TODO: accept a content type. func EncodeList(e Encoder, objects []Object) error { var errs []error for i := range objects { data, err := Encode(e, objects[i]) if err != nil { errs = append(errs, err) continue } // TODO: Set ContentEncoding and ContentType. objects[i] = &Unknown{Raw: data} } return errors.NewAggregate(errs) }
// ToAggregate converts the ErrorList into an errors.Aggregate. func (list ErrorList) ToAggregate() utilerrors.Aggregate { errs := make([]error, 0, len(list)) errorMsgs := sets.NewString() for _, err := range list { msg := fmt.Sprintf("%v", err) if errorMsgs.Has(msg) { continue } errorMsgs.Insert(msg) errs = append(errs, err) } return utilerrors.NewAggregate(errs) }
// collapseAggregateErrors returns the minimal errors. it handles empty as nil, handles one item in a list // by returning the item, and collapses all NoMatchErrors to a single one (since they should all be the same) func collapseAggregateErrors(errors []error) error { if len(errors) == 0 { return nil } if len(errors) == 1 { return errors[0] } allNoMatchErrors := true for _, err := range errors { allNoMatchErrors = allNoMatchErrors && IsNoMatchError(err) } if allNoMatchErrors { return errors[0] } return utilerrors.NewAggregate(errors) }
// RESTMappings returns all possible RESTMappings for the provided group kind, or an error // if the type is not recognized. func (m MultiRESTMapper) RESTMappings(gk unversioned.GroupKind) ([]*RESTMapping, error) { var allMappings []*RESTMapping var errors []error for _, t := range m { currMappings, err := t.RESTMappings(gk) // ignore "no match" errors, but any other error percolates back up if IsNoMatchError(err) { continue } if err != nil { errors = append(errors, err) continue } allMappings = append(allMappings, currMappings...) } if len(errors) > 0 { return nil, utilerrors.NewAggregate(errors) } if len(allMappings) == 0 { return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")} } return allMappings, nil }
// Load starts by running the MigrationRules and then // takes the loading rules and returns a Config object based on following rules. // if the ExplicitPath, return the unmerged explicit file // Otherwise, return a merged config based on the Precedence slice // A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored. // Read errors or files with non-deserializable content produce errors. // The first file to set a particular map key wins and map key's value is never changed. // BUT, if you set a struct value that is NOT contained inside of map, the value WILL be changed. // This results in some odd looking logic to merge in one direction, merge in the other, and then merge the two. // It also means that if two files specify a "red-user", only values from the first file's red-user are used. Even // non-conflicting entries from the second file's "red-user" are discarded. // Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder // and only absolute file paths are returned. func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) { if err := rules.Migrate(); err != nil { return nil, err } errlist := []error{} kubeConfigFiles := []string{} // Make sure a file we were explicitly told to use exists if len(rules.ExplicitPath) > 0 { if _, err := os.Stat(rules.ExplicitPath); os.IsNotExist(err) { return nil, err } kubeConfigFiles = append(kubeConfigFiles, rules.ExplicitPath) } else { kubeConfigFiles = append(kubeConfigFiles, rules.Precedence...) } kubeconfigs := []*clientcmdapi.Config{} // read and cache the config files so that we only look at them once for _, filename := range kubeConfigFiles { if len(filename) == 0 { // no work to do continue } config, err := LoadFromFile(filename) if os.IsNotExist(err) { // skip missing files continue } if err != nil { errlist = append(errlist, fmt.Errorf("Error loading config file \"%s\": %v", filename, err)) continue } kubeconfigs = append(kubeconfigs, config) } // first merge all of our maps mapConfig := clientcmdapi.NewConfig() for _, kubeconfig := range kubeconfigs { mergo.Merge(mapConfig, kubeconfig) } // merge all of the struct values in the reverse order so that priority is given correctly // errors are not added to the list the second time nonMapConfig := clientcmdapi.NewConfig() for i := len(kubeconfigs) - 1; i >= 0; i-- { kubeconfig := kubeconfigs[i] mergo.Merge(nonMapConfig, kubeconfig) } // since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and // get the values we expect. config := clientcmdapi.NewConfig() mergo.Merge(config, mapConfig) mergo.Merge(config, nonMapConfig) if rules.ResolvePaths() { if err := ResolveLocalPaths(config); err != nil { errlist = append(errlist, err) } } return config, utilerrors.NewAggregate(errlist) }
// Error implements the error interface func (e errConfigurationInvalid) Error() string { return fmt.Sprintf("invalid configuration: %v", utilerrors.NewAggregate(e).Error()) }