agones.dev/agones@v1.54.0/pkg/cloudproduct/cloudproduct.go (about) 1 // Copyright 2022 Google LLC All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cloudproduct 16 17 import ( 18 "context" 19 20 agonesv1 "agones.dev/agones/pkg/apis/agones/v1" 21 "agones.dev/agones/pkg/client/informers/externalversions" 22 "agones.dev/agones/pkg/cloudproduct/generic" 23 "agones.dev/agones/pkg/cloudproduct/gke" 24 "agones.dev/agones/pkg/portallocator" 25 "agones.dev/agones/pkg/util/runtime" 26 "github.com/pkg/errors" 27 "github.com/spf13/pflag" 28 "github.com/spf13/viper" 29 corev1 "k8s.io/api/core/v1" 30 "k8s.io/client-go/informers" 31 "k8s.io/client-go/kubernetes" 32 ) 33 34 // The Cloud Product abstraction currently consists of disjoint interfaces: 35 // * ControllerHooks() is an interface available to the pkg/controller binaries 36 // * api hooks are separated into api group and registered directly with the API 37 // 38 // Users should bind flags with Bind{Flags,Env}, then call Initialize with a 39 // k8s client to initialize. 40 41 // ControllerHooksInterface provides a generic interface that abstracts cloud product 42 // specific functionality for pkg/controller packages. 43 type ControllerHooksInterface interface { 44 agonesv1.APIHooks 45 46 // SyncPodPortsToGameServer runs after a Pod has been assigned to a Node and before we sync 47 // Pod host ports to the GameServer status. 48 SyncPodPortsToGameServer(*agonesv1.GameServer, *corev1.Pod) error 49 50 // NewPortAllocator creates a PortAllocator. See gameservers.NewPortAllocator for parameters. 51 NewPortAllocator(map[string]portallocator.PortRange, informers.SharedInformerFactory, externalversions.SharedInformerFactory) portallocator.Interface 52 53 // WaitOnFreePorts 54 WaitOnFreePorts() bool 55 } 56 57 const ( 58 cloudProductFlag = "cloud-product" 59 60 // If --cloud-product=auto, auto-detect 61 autoDetectString = "auto" 62 63 genericProduct = "generic" 64 gkeAutopilotProduct = "gke-autopilot" 65 ) 66 67 var ( 68 logger = runtime.NewLoggerWithSource("cloudproduct") 69 productDetectors = []func(context.Context, *kubernetes.Clientset) string{gke.Detect} 70 ) 71 72 // BindFlags binds the --cloud-product flag. 73 func BindFlags() { 74 viper.SetDefault(cloudProductFlag, autoDetectString) 75 pflag.String(cloudProductFlag, viper.GetString(cloudProductFlag), "Cloud product. Set to 'auto' to auto-detect, set to 'generic' to force generic behavior, set to 'gke-autopilot' for GKE Autopilot. Can also use CLOUD_PRODUCT env variable.") 76 } 77 78 // BindEnv binds the CLOUD_PRODUCT env variable. 79 func BindEnv() error { 80 return viper.BindEnv(cloudProductFlag) 81 } 82 83 // NewFromFlag instantiates a new CloudProduct interface from the flags in BindFlags/BindEnv. 84 func NewFromFlag(ctx context.Context, kc *kubernetes.Clientset) (ControllerHooksInterface, error) { 85 product := autoDetect(ctx, viper.GetString(cloudProductFlag), kc) 86 87 switch product { 88 case gkeAutopilotProduct: 89 return gke.Autopilot(), nil 90 case genericProduct: 91 return generic.New(), nil 92 } 93 return nil, errors.Errorf("unknown cloud product: %q", product) 94 } 95 96 func autoDetect(ctx context.Context, product string, kc *kubernetes.Clientset) string { 97 if product != autoDetectString { 98 logger.Infof("Cloud product forced to %q, skipping auto-detection", product) 99 return product 100 } 101 for _, detect := range productDetectors { 102 product = detect(ctx, kc) 103 if product != "" { 104 logger.Infof("Cloud product detected as %q", product) 105 return product 106 } 107 } 108 logger.Infof("Cloud product defaulted to %q", genericProduct) 109 return genericProduct 110 }