func ReadConfig()

in e2etest/newe2e_config.go [517:602]


func ReadConfig(config reflect.Value, fieldName string, tag EnvTag) *ConfigReaderError {
	if tag.EnvName != "" { // This needs to be fulfilled
		return SetValue(fieldName, config, tag)
	} else if config.Kind() == reflect.Struct {
		fieldCt := config.NumField()
		sType := config.Type()

		hasRequiredFlags := false
		successfulSetCount := uint(0)

		baseError := NewConfigReaderError(fieldName)
		for i := 0; i < fieldCt; i++ {
			envTag := ParseEnvTag(sType.Field(i).Tag.Get("env"))

			if tag.MutuallyExclusive { // all semantically get treated as required for consistency.
				envTag.Required = true
			}

			if envTag.Required {
				hasRequiredFlags = true
			}

			err := ReadConfig(config.Field(i), sType.Field(i).Name, envTag)

			if err != nil && envTag.Required {
				baseError.Combine(err)
			} else if err == nil && envTag.Required {
				successfulSetCount++
			}
		}

		// The definition of "Required" is simply that all underlying conditions must satisfy.
		// If this _is_ required, it is a structure error to have an issue.
		// If it is not required, but is mutually exclusive, it is still a structure error to fulfill more than one condition.
		if tag.Required {
			if tag.MutuallyExclusive {
				// When we're mutually exclusive, everything is required, but only one must satisfy.
				if successfulSetCount > 1 {
					baseError.CoreError = errors.New("mutually exclusive struct satisfies more than one field")
					return baseError.Finalize()
				} else if successfulSetCount == 0 {
					baseError.CoreError = errors.New("mutually exclusive struct does not satisfy at least one field")
					return baseError.Finalize()
				}

				baseError = NewConfigReaderError(fieldName) // No error if only one got set
			} else if tag.MinimumRequired != 0 {
				if successfulSetCount < tag.MinimumRequired {
					baseError.CoreError = fmt.Errorf("required struct fails to fulfill at least %d conditions", tag.MinimumRequired)
					return baseError.Finalize()
				}

				baseError = NewConfigReaderError(fieldName) // No error if the required amount got set
			} else if !baseError.Empty() {
				baseError.CoreError = errors.New("required struct fails to fulfill one or more conditions")
				return baseError.Finalize()
			}
		} else {
			// when we're not required, but we see required flags, and at least one is set, all required flags under us must succeed.
			if !tag.MutuallyExclusive && hasRequiredFlags && successfulSetCount >= 1 {
				if !baseError.Empty() {
					baseError.CoreError = errors.New("required struct fails to fulfill one or more conditions")
					return baseError.Finalize()
				}
			} else if tag.MutuallyExclusive {
				// When we're mutually exclusive, everything is required, but only one must satisfy.
				if successfulSetCount > 1 {
					baseError.CoreError = errors.New("mutually exclusive struct satisfies more than one field")
					return baseError.Finalize()
				} else if successfulSetCount == 0 {
					baseError.CoreError = errors.New("mutually exclusive struct does not satisfy at least one field")
					return baseError.Finalize()
				}

				baseError = NewConfigReaderError(fieldName) // No error if only one got set
			}
		}

		return baseError.Finalize() // Assuming we're not required or mutually exclusive, and everything under us satisfies,
	} else {
		return &ConfigReaderError{
			StructName: fieldName,
			CoreError:  errors.New("struct field was not assigned an environment variable and is not traversable"),
		}
	}
}