sigs.k8s.io/kueue@v0.6.2/pkg/config/config.go (about)

     1  /*
     2  Copyright 2023 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 config
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"os"
    23  
    24  	"k8s.io/apimachinery/pkg/api/equality"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"k8s.io/apimachinery/pkg/runtime/serializer"
    28  	ctrl "sigs.k8s.io/controller-runtime"
    29  	"sigs.k8s.io/controller-runtime/pkg/webhook"
    30  
    31  	configapi "sigs.k8s.io/kueue/apis/config/v1beta1"
    32  )
    33  
    34  // fromFile provides an alternative to the deprecated ctrl.ConfigFile().AtPath(path).OfKind(&cfg)
    35  func fromFile(path string, scheme *runtime.Scheme, cfg *configapi.Configuration) error {
    36  	content, err := os.ReadFile(path)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	codecs := serializer.NewCodecFactory(scheme)
    42  
    43  	// Regardless of if the bytes are of any external version,
    44  	// it will be read successfully and converted into the internal version
    45  	return runtime.DecodeInto(codecs.UniversalDecoder(), content, cfg)
    46  }
    47  
    48  // addTo provides an alternative to the deprecated o.AndFrom(&cfg)
    49  func addTo(o *ctrl.Options, cfg *configapi.Configuration) {
    50  	addLeaderElectionTo(o, cfg)
    51  	if o.Metrics.BindAddress == "" && cfg.Metrics.BindAddress != "" {
    52  		o.Metrics.BindAddress = cfg.Metrics.BindAddress
    53  	}
    54  
    55  	if o.PprofBindAddress == "" && cfg.PprofBindAddress != "" {
    56  		o.PprofBindAddress = cfg.PprofBindAddress
    57  	}
    58  
    59  	if o.HealthProbeBindAddress == "" && cfg.Health.HealthProbeBindAddress != "" {
    60  		o.HealthProbeBindAddress = cfg.Health.HealthProbeBindAddress
    61  	}
    62  
    63  	if o.ReadinessEndpointName == "" && cfg.Health.ReadinessEndpointName != "" {
    64  		o.ReadinessEndpointName = cfg.Health.ReadinessEndpointName
    65  	}
    66  
    67  	if o.LivenessEndpointName == "" && cfg.Health.LivenessEndpointName != "" {
    68  		o.LivenessEndpointName = cfg.Health.LivenessEndpointName
    69  	}
    70  
    71  	if o.WebhookServer == nil && cfg.Webhook.Port != nil {
    72  		wo := webhook.Options{}
    73  		if cfg.Webhook.Port != nil {
    74  			wo.Port = *cfg.Webhook.Port
    75  		}
    76  		if cfg.Webhook.Host != "" {
    77  			wo.Host = cfg.Webhook.Host
    78  		}
    79  
    80  		if cfg.Webhook.CertDir != "" {
    81  			wo.CertDir = cfg.Webhook.CertDir
    82  		}
    83  		o.WebhookServer = webhook.NewServer(wo)
    84  	}
    85  
    86  	if cfg.Controller != nil {
    87  		if o.Controller.CacheSyncTimeout == 0 && cfg.Controller.CacheSyncTimeout != nil {
    88  			o.Controller.CacheSyncTimeout = *cfg.Controller.CacheSyncTimeout
    89  		}
    90  
    91  		if len(o.Controller.GroupKindConcurrency) == 0 && len(cfg.Controller.GroupKindConcurrency) > 0 {
    92  			o.Controller.GroupKindConcurrency = cfg.Controller.GroupKindConcurrency
    93  		}
    94  	}
    95  }
    96  
    97  func addLeaderElectionTo(o *ctrl.Options, cfg *configapi.Configuration) {
    98  	if cfg.LeaderElection == nil {
    99  		// The source does not have any configuration; noop
   100  		return
   101  	}
   102  
   103  	if !o.LeaderElection && cfg.LeaderElection.LeaderElect != nil {
   104  		o.LeaderElection = *cfg.LeaderElection.LeaderElect
   105  	}
   106  
   107  	if o.LeaderElectionResourceLock == "" && cfg.LeaderElection.ResourceLock != "" {
   108  		o.LeaderElectionResourceLock = cfg.LeaderElection.ResourceLock
   109  	}
   110  
   111  	if o.LeaderElectionNamespace == "" && cfg.LeaderElection.ResourceNamespace != "" {
   112  		o.LeaderElectionNamespace = cfg.LeaderElection.ResourceNamespace
   113  	}
   114  
   115  	if o.LeaderElectionID == "" && cfg.LeaderElection.ResourceName != "" {
   116  		o.LeaderElectionID = cfg.LeaderElection.ResourceName
   117  	}
   118  
   119  	if o.LeaseDuration == nil && !equality.Semantic.DeepEqual(cfg.LeaderElection.LeaseDuration, metav1.Duration{}) {
   120  		o.LeaseDuration = &cfg.LeaderElection.LeaseDuration.Duration
   121  	}
   122  
   123  	if o.RenewDeadline == nil && !equality.Semantic.DeepEqual(cfg.LeaderElection.RenewDeadline, metav1.Duration{}) {
   124  		o.RenewDeadline = &cfg.LeaderElection.RenewDeadline.Duration
   125  	}
   126  
   127  	if o.RetryPeriod == nil && !equality.Semantic.DeepEqual(cfg.LeaderElection.RetryPeriod, metav1.Duration{}) {
   128  		o.RetryPeriod = &cfg.LeaderElection.RetryPeriod.Duration
   129  	}
   130  }
   131  
   132  func Encode(scheme *runtime.Scheme, cfg *configapi.Configuration) (string, error) {
   133  	codecs := serializer.NewCodecFactory(scheme)
   134  	const mediaType = runtime.ContentTypeYAML
   135  	info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType)
   136  	if !ok {
   137  		return "", fmt.Errorf("unable to locate encoder -- %q is not a supported media type", mediaType)
   138  	}
   139  
   140  	encoder := codecs.EncoderForVersion(info.Serializer, configapi.GroupVersion)
   141  	buf := new(bytes.Buffer)
   142  	if err := encoder.Encode(cfg, buf); err != nil {
   143  		return "", err
   144  	}
   145  	return buf.String(), nil
   146  }
   147  
   148  // Load returns a set of controller options and configuration from the given file, if the config file path is empty
   149  // it used the default configapi values.
   150  func Load(scheme *runtime.Scheme, configFile string) (ctrl.Options, configapi.Configuration, error) {
   151  	var err error
   152  	options := ctrl.Options{
   153  		Scheme: scheme,
   154  	}
   155  
   156  	cfg := configapi.Configuration{}
   157  	if configFile == "" {
   158  		scheme.Default(&cfg)
   159  	} else {
   160  		err := fromFile(configFile, scheme, &cfg)
   161  		if err != nil {
   162  			return options, cfg, err
   163  		}
   164  	}
   165  	if err := validate(&cfg).ToAggregate(); err != nil {
   166  		return options, cfg, err
   167  	}
   168  	addTo(&options, &cfg)
   169  	return options, cfg, err
   170  }
   171  
   172  func WaitForPodsReadyIsEnabled(cfg *configapi.Configuration) bool {
   173  	return cfg.WaitForPodsReady != nil && cfg.WaitForPodsReady.Enable
   174  }