sigs.k8s.io/kueue@v0.6.2/pkg/controller/jobframework/setup.go (about)

     1  /*
     2  Copyright 2024 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 jobframework
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"os"
    24  
    25  	"github.com/go-logr/logr"
    26  	"k8s.io/apimachinery/pkg/api/meta"
    27  	ctrl "sigs.k8s.io/controller-runtime"
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  	"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
    30  
    31  	"sigs.k8s.io/kueue/pkg/controller/jobs/noop"
    32  )
    33  
    34  var (
    35  	errFailedMappingResource = errors.New("restMapper failed mapping resource")
    36  )
    37  
    38  // SetupControllers setups all controllers and webhooks for integrations.
    39  // When the platform developers implement a separate kueue-manager to manage the in-house custom jobs,
    40  // they can easily setup controllers and webhooks for the in-house custom jobs.
    41  //
    42  // Note that the first argument, "mgr" must be initialized on the outside of this function.
    43  // In addition, if the manager uses the kueue's internal cert management for the webhooks,
    44  // this function needs to be called after the certs get ready because the controllers won't work
    45  // until the webhooks are operating, and the webhook won't work until the
    46  // certs are all in place.
    47  func SetupControllers(mgr ctrl.Manager, log logr.Logger, opts ...Option) error {
    48  	options := ProcessOptions(opts...)
    49  
    50  	return ForEachIntegration(func(name string, cb IntegrationCallbacks) error {
    51  		logger := log.WithValues("jobFrameworkName", name)
    52  		fwkNamePrefix := fmt.Sprintf("jobFrameworkName %q", name)
    53  
    54  		if options.EnabledFrameworks.Has(name) {
    55  			if cb.CanSupportIntegration != nil {
    56  				if canSupport, err := cb.CanSupportIntegration(opts...); !canSupport || err != nil {
    57  					log.Error(err, "Failed to configure reconcilers")
    58  					os.Exit(1)
    59  				}
    60  			}
    61  			gvk, err := apiutil.GVKForObject(cb.JobType, mgr.GetScheme())
    62  			if err != nil {
    63  				return fmt.Errorf("%s: %w: %w", fwkNamePrefix, errFailedMappingResource, err)
    64  			}
    65  			if _, err = mgr.GetRESTMapper().RESTMapping(gvk.GroupKind(), gvk.Version); err != nil {
    66  				if !meta.IsNoMatchError(err) {
    67  					return fmt.Errorf("%s: %w", fwkNamePrefix, err)
    68  				}
    69  				logger.Info("No matching API in the server for job framework, skipped setup of controller and webhook")
    70  			} else {
    71  				if err = cb.NewReconciler(
    72  					mgr.GetClient(),
    73  					mgr.GetEventRecorderFor(fmt.Sprintf("%s-%s-controller", name, options.ManagerName)),
    74  					opts...,
    75  				).SetupWithManager(mgr); err != nil {
    76  					return fmt.Errorf("%s: %w", fwkNamePrefix, err)
    77  				}
    78  				if err = cb.SetupWebhook(mgr, opts...); err != nil {
    79  					return fmt.Errorf("%s: unable to create webhook: %w", fwkNamePrefix, err)
    80  				}
    81  				logger.Info("Set up controller and webhook for job framework")
    82  				return nil
    83  			}
    84  		}
    85  		if err := noop.SetupWebhook(mgr, cb.JobType); err != nil {
    86  			return fmt.Errorf("%s: unable to create noop webhook: %w", fwkNamePrefix, err)
    87  		}
    88  		return nil
    89  	})
    90  }
    91  
    92  // SetupIndexes setups the indexers for integrations.
    93  // When the platform developers implement a separate kueue-manager to manage the in-house custom jobs,
    94  // they can easily setup indexers for the in-house custom jobs.
    95  //
    96  // Note that the second argument, "indexer" needs to be the fieldIndexer obtained from the Manager.
    97  func SetupIndexes(ctx context.Context, indexer client.FieldIndexer, opts ...Option) error {
    98  	options := ProcessOptions(opts...)
    99  	return ForEachIntegration(func(name string, cb IntegrationCallbacks) error {
   100  		if options.EnabledFrameworks.Has(name) {
   101  			if err := cb.SetupIndexes(ctx, indexer); err != nil {
   102  				return fmt.Errorf("jobFrameworkName %q: %w", name, err)
   103  			}
   104  		}
   105  		return nil
   106  	})
   107  }