runner/group/parse.go (69 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package group import ( "context" "fmt" "net/url" "os" "github.com/Azure/kperf/api/types" "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) // SpecURIType is the scheme of RunnerGroupSpec's URI. type SpecURIType string const ( // SpecURITypeFile is file scheme. SpecURITypeFile SpecURIType = "file" // SpecURITypeConfigMap is configmap scheme. SpecURITypeConfigMap SpecURIType = "configmap" ) // NewRunnerGroupSpecFromURI builds RunnerGroupSpec via URI. Current supported // schemes are: // // - file - The spec is stored in filesystem. // // - configmap - The spec is stored in kubernetes as configmap. // // For configmap, current supported query parameters: // // - namespace: The namespace scope for the configmap. Using `default` if not set or empty. // // - specName: The name of data which stores RunnerGroupSpec. Using `spec` if not set or empty. func NewRunnerGroupSpecFromURI(clientset kubernetes.Interface, specURI string) (*types.RunnerGroupSpec, error) { u, err := url.Parse(specURI) if err != nil { return nil, fmt.Errorf("invalid runner group uri %s: %w", specURI, err) } switch typ := SpecURIType(u.Scheme); typ { case SpecURITypeFile: return parseRunnerGroupSpecFromFile(u.Path) case SpecURITypeConfigMap: var ( namespace = "default" specName = "spec" ) if ns := u.Query().Get("namespace"); len(ns) > 0 { namespace = ns } if name := u.Query().Get("specName"); len(name) > 0 { specName = name } return parseRunnerGroupSpecFromConfigMap(clientset, namespace, u.Host, specName) default: return nil, fmt.Errorf("unsupported RunnerGroupSpec's URI scheme: %v", typ) } } func parseRunnerGroupSpecFromFile(specPath string) (*types.RunnerGroupSpec, error) { specInRaw, err := os.ReadFile(specPath) if err != nil { return nil, fmt.Errorf("failed to read runner group spec from %s: %w", specPath, err) } return parseRunnerGroupSpecFromBinary(specInRaw) } func parseRunnerGroupSpecFromConfigMap(clientset kubernetes.Interface, namespace, name, specName string) (*types.RunnerGroupSpec, error) { ctx := context.Background() cli := clientset.CoreV1().ConfigMaps(namespace) cm, err := cli.Get(ctx, name, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("failed to load configmap %s from namespace %s: %w", name, namespace, err) } specInStr, ok := cm.Data[specName] if !ok { return nil, fmt.Errorf("no such data (%s) in configmap %s from namespace %s", specName, name, namespace) } return parseRunnerGroupSpecFromBinary([]byte(specInStr)) } func parseRunnerGroupSpecFromBinary(data []byte) (*types.RunnerGroupSpec, error) { var spec types.RunnerGroupSpec if err := yaml.Unmarshal(data, &spec); err != nil { return nil, fmt.Errorf("failed to parse RunnerGroupSpec from YAML: %s\nerror: %w", string(data), err) } return &spec, nil }