import (
"bytes"
+ _ "embed"
"encoding/json"
"errors"
"flag"
"io/ioutil"
"os"
"regexp"
+ "strconv"
"strings"
"git.arvados.org/arvados.git/sdk/go/arvados"
"github.com/sirupsen/logrus"
)
+//go:embed config.default.yml
+var DefaultYAML []byte
+
var ErrNoClustersDefined = errors.New("config does not define any clusters")
type Loader struct {
}
ldr.logExtraKeys(merged, src, "")
removeSampleKeys(merged)
+ // We merge the loaded config into the default, overriding any existing keys.
+ // Make sure we do not override a default with a key that has a 'null' value.
+ removeNullKeys(src)
err = mergo.Merge(&merged, src, mergo.WithOverride)
if err != nil {
return nil, fmt.Errorf("merging config data: %s", err)
ldr.checkEmptyKeepstores(cc),
ldr.checkUnlistedKeepstores(cc),
ldr.checkStorageClasses(cc),
+ ldr.checkCUDAVersions(cc),
// TODO: check non-empty Rendezvous on
// services other than Keepstore
} {
return nil
}
+func (ldr *Loader) checkCUDAVersions(cc arvados.Cluster) error {
+ for _, it := range cc.InstanceTypes {
+ if it.CUDA.DeviceCount == 0 {
+ continue
+ }
+
+ _, err := strconv.ParseFloat(it.CUDA.DriverVersion, 64)
+ if err != nil {
+ return fmt.Errorf("InstanceType %q has invalid CUDA.DriverVersion %q, expected format X.Y (%v)", it.Name, it.CUDA.DriverVersion, err)
+ }
+ _, err = strconv.ParseFloat(it.CUDA.HardwareCapability, 64)
+ if err != nil {
+ return fmt.Errorf("InstanceType %q has invalid CUDA.HardwareCapability %q, expected format X.Y (%v)", it.Name, it.CUDA.HardwareCapability, err)
+ }
+ }
+ return nil
+}
+
func checkKeyConflict(label string, m map[string]string) error {
saw := map[string]bool{}
for k := range m {
return nil
}
+func removeNullKeys(m map[string]interface{}) {
+ for k, v := range m {
+ if v == nil {
+ delete(m, k)
+ }
+ if v, _ := v.(map[string]interface{}); v != nil {
+ removeNullKeys(v)
+ }
+ }
+}
+
func removeSampleKeys(m map[string]interface{}) {
delete(m, "SAMPLE")
for _, v := range m {