@@ -17,19 +17,27 @@ limitations under the License.
17
17
package main
18
18
19
19
import (
20
+ "context"
20
21
"flag"
22
+ "fmt"
21
23
"os"
24
+ "strings"
22
25
"time"
23
26
24
27
instascale "github.com/project-codeflare/instascale/controllers"
28
+ instascaleconfig "github.com/project-codeflare/instascale/pkg/config"
25
29
mcadv1beta1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1"
26
30
quotasubtreev1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/quotaplugins/quotasubtree/v1"
27
31
mcadconfig "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/config"
28
32
mcad "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/controller/queuejob"
29
33
"go.uber.org/zap/zapcore"
30
34
35
+ corev1 "k8s.io/api/core/v1"
36
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
37
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31
38
"k8s.io/apimachinery/pkg/runtime"
32
39
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
40
+ "k8s.io/client-go/kubernetes"
33
41
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
34
42
_ "k8s.io/client-go/plugin/pkg/client/auth"
35
43
"k8s.io/client-go/rest"
@@ -38,6 +46,7 @@ import (
38
46
ctrl "sigs.k8s.io/controller-runtime"
39
47
"sigs.k8s.io/controller-runtime/pkg/healthz"
40
48
"sigs.k8s.io/controller-runtime/pkg/log/zap"
49
+ "sigs.k8s.io/yaml"
41
50
42
51
"github.com/project-codeflare/codeflare-operator/pkg/config"
43
52
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
@@ -57,6 +66,11 @@ func init() {
57
66
}
58
67
59
68
func main () {
69
+ var configMapName string
70
+ flag .StringVar (& configMapName , "config" , "codeflare-operator-config" ,
71
+ "The name of the ConfigMap to load the operator configuration from. " +
72
+ "If it does not exist, the operator will create and initialise it." )
73
+
60
74
zapOptions := zap.Options {
61
75
Development : true ,
62
76
TimeEncoder : zapcore .TimeEncoderOfLayout (time .RFC3339 ),
@@ -67,20 +81,41 @@ func main() {
67
81
68
82
ctx := ctrl .SetupSignalHandler ()
69
83
70
- cfg := config.CodeFlareOperatorConfiguration {
84
+ cfg := & config.CodeFlareOperatorConfiguration {
85
+ ClientConnection : & config.ClientConnection {
86
+ QPS : pointer .Float32 (50 ),
87
+ Burst : pointer .Int32 (100 ),
88
+ },
71
89
ControllerManager : config.ControllerManager {
90
+ Metrics : config.MetricsConfiguration {
91
+ BindAddress : ":8080" ,
92
+ },
93
+ Health : config.HealthConfiguration {
94
+ BindAddress : ":8081" ,
95
+ ReadinessEndpointName : "readyz" ,
96
+ LivenessEndpointName : "healthz" ,
97
+ },
72
98
LeaderElection : & configv1alpha1.LeaderElectionConfiguration {},
73
99
},
74
- MCAD : & mcadconfig.MCADConfiguration {},
75
- InstaScale : & config.InstaScaleConfiguration {},
100
+ MCAD : & mcadconfig.MCADConfiguration {},
101
+ InstaScale : & config.InstaScaleConfiguration {
102
+ Enabled : pointer .Bool (false ),
103
+ InstaScaleConfiguration : instascaleconfig.InstaScaleConfiguration {
104
+ MaxScaleoutAllowed : 5 ,
105
+ },
106
+ },
76
107
}
77
108
78
109
kubeConfig , err := ctrl .GetConfig ()
79
110
exitOnError (err , "unable to get client config" )
80
-
81
111
if kubeConfig .UserAgent == "" {
82
112
kubeConfig .UserAgent = "codeflare-operator"
83
113
}
114
+ kubeClient , err := kubernetes .NewForConfig (kubeConfig )
115
+ exitOnError (err , "unable to create Kubernetes client" )
116
+
117
+ exitOnError (loadIntoOrCreate (ctx , kubeClient , namespaceOrDie (), configMapName , cfg ), "unable to initialise configuration" )
118
+
84
119
kubeConfig .Burst = int (pointer .Int32Deref (cfg .ClientConnection .Burst , int32 (rest .DefaultBurst )))
85
120
kubeConfig .QPS = pointer .Float32Deref (cfg .ClientConnection .QPS , rest .DefaultQPS )
86
121
setupLog .V (2 ).Info ("REST client" , "qps" , kubeConfig .QPS , "burst" , kubeConfig .Burst )
@@ -122,6 +157,66 @@ func main() {
122
157
exitOnError (mgr .Start (ctx ), "error running manager" )
123
158
}
124
159
160
+ func loadIntoOrCreate (ctx context.Context , client kubernetes.Interface , ns , name string , cfg * config.CodeFlareOperatorConfiguration ) error {
161
+ configMap , err := client .CoreV1 ().ConfigMaps (ns ).Get (ctx , name , metav1.GetOptions {})
162
+ if apierrors .IsNotFound (err ) {
163
+ return createConfigMap (ctx , client , ns , name , cfg )
164
+ } else if err != nil {
165
+ return err
166
+ }
167
+
168
+ if len (configMap .Data ) != 1 {
169
+ return fmt .Errorf ("cannot resolve config from ConfigMap %s/%s" , configMap .Namespace , configMap .Name )
170
+ }
171
+
172
+ for _ , data := range configMap .Data {
173
+ return yaml .Unmarshal ([]byte (data ), cfg )
174
+ }
175
+
176
+ return nil
177
+ }
178
+
179
+ func createConfigMap (ctx context.Context , client kubernetes.Interface , ns , name string , cfg * config.CodeFlareOperatorConfiguration ) error {
180
+ content , err := yaml .Marshal (cfg )
181
+ if err != nil {
182
+ return err
183
+ }
184
+
185
+ configMap := & corev1.ConfigMap {
186
+ TypeMeta : metav1.TypeMeta {
187
+ Kind : "ConfigMap" ,
188
+ APIVersion : "v1" ,
189
+ },
190
+ ObjectMeta : metav1.ObjectMeta {
191
+ Name : name ,
192
+ Namespace : ns ,
193
+ },
194
+ Data : map [string ]string {
195
+ "config.yaml" : string (content ),
196
+ },
197
+ }
198
+
199
+ _ , err = client .CoreV1 ().ConfigMaps (ns ).Create (ctx , configMap , metav1.CreateOptions {})
200
+ return err
201
+ }
202
+
203
+ func namespaceOrDie () string {
204
+ // This way assumes you've set the NAMESPACE environment variable either manually, when running
205
+ // the operator standalone, or using the downward API, when running the operator in-cluster.
206
+ if ns := os .Getenv ("NAMESPACE" ); ns != "" {
207
+ return ns
208
+ }
209
+
210
+ // Fall back to the namespace associated with the service account token, if available
211
+ if data , err := os .ReadFile ("/var/run/secrets/kubernetes.io/serviceaccount/namespace" ); err == nil {
212
+ if ns := strings .TrimSpace (string (data )); len (ns ) > 0 {
213
+ return ns
214
+ }
215
+ }
216
+
217
+ panic ("unable to determine current namespace" )
218
+ }
219
+
125
220
func exitOnError (err error , msg string ) {
126
221
if err != nil {
127
222
setupLog .Error (err , msg )
0 commit comments