dynamo/deploy/cloud/operator/internal/controller_common/predicate.go

117 lines
3.6 KiB
Go

/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package controller_common
import (
"context"
"strings"
"time"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/discovery"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
type GroveConfig struct {
// Enabled is automatically determined by checking if Grove CRDs are installed in the cluster
Enabled bool
// TerminationDelay configures the termination delay for Grove PodGangSets
TerminationDelay time.Duration
}
type Config struct {
// Enable resources filtering, only the resources belonging to the given namespace will be handled.
RestrictedNamespace string
EnableLWS bool
Grove GroveConfig
EtcdAddress string
NatsAddress string
IngressConfig IngressConfig
}
type IngressConfig struct {
VirtualServiceGateway string
IngressControllerClassName string
IngressControllerTLSSecret string
IngressHostSuffix string
}
func (i *IngressConfig) UseVirtualService() bool {
return i.VirtualServiceGateway != ""
}
// DetectGroveAvailability checks if Grove is available by checking if the Grove API group is registered
// This approach uses the discovery client which is simpler and more reliable
func DetectGroveAvailability(ctx context.Context, mgr ctrl.Manager) bool {
logger := log.FromContext(ctx)
// Use the discovery client to check if Grove API groups are available
cfg := mgr.GetConfig()
if cfg == nil {
logger.Info("Grove detection failed, no discovery client available")
return false
}
// Try to create a discovery client
discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg)
if err != nil {
logger.Error(err, "Grove detection failed, could not create discovery client")
return false
}
// Check if grove.io API group is available
apiGroups, err := discoveryClient.ServerGroups()
if err != nil {
logger.Error(err, "Grove detection failed, could not list server groups")
return false
}
for _, group := range apiGroups.Groups {
if group.Name == "grove.io" {
logger.Info("Grove is available, grove.io API group found")
return true
}
}
logger.Info("Grove not available, grove.io API group not found")
return false
}
func EphemeralDeploymentEventFilter(config Config) predicate.Predicate {
return predicate.NewPredicateFuncs(func(o client.Object) bool {
l := log.FromContext(context.Background())
objMeta, err := meta.Accessor(o)
if err != nil {
l.Error(err, "Error extracting object metadata")
return false
}
if config.RestrictedNamespace != "" {
// in case of a restricted namespace, we only want to process the events that are in the restricted namespace
return objMeta.GetNamespace() == config.RestrictedNamespace
}
// in all other cases, discard the event if it is destined to an ephemeral deployment
if strings.Contains(objMeta.GetNamespace(), "ephemeral") {
return false
}
return true
})
}