Skip to content

Commit 73dcb21

Browse files
astefanuttiopenshift-merge-robot
authored andcommitted
Init and load operator ConfigMap
1 parent 7857bb8 commit 73dcb21

File tree

7 files changed

+105
-102
lines changed

7 files changed

+105
-102
lines changed

config/default/kustomization.yaml

-49
Original file line numberDiff line numberDiff line change
@@ -17,57 +17,8 @@ bases:
1717
- ../crd
1818
- ../rbac
1919
- ../manager
20-
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
21-
# crd/kustomization.yaml
22-
# - ../webhook
23-
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
24-
# - ../certmanager
2520
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
2621
# - ../prometheus
2722

2823
resources:
29-
# Add metrics service
3024
- metrics_service.yaml
31-
32-
# Mount the controller config file for loading manager configurations
33-
# through a ComponentConfig type
34-
# - manager_config_patch.yaml
35-
36-
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
37-
# crd/kustomization.yaml
38-
# - manager_webhook_patch.yaml
39-
40-
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
41-
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
42-
# 'CERTMANAGER' needs to be enabled to use ca injection
43-
# - webhookcainjection_patch.yaml
44-
45-
# the following config is for teaching kustomize how to do var substitution
46-
vars:
47-
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
48-
# - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
49-
# objref:
50-
# kind: Certificate
51-
# group: cert-manager.io
52-
# version: v1
53-
# name: serving-cert # this name should match the one in certificate.yaml
54-
# fieldref:
55-
# fieldpath: metadata.namespace
56-
# - name: CERTIFICATE_NAME
57-
# objref:
58-
# kind: Certificate
59-
# group: cert-manager.io
60-
# version: v1
61-
# name: serving-cert # this name should match the one in certificate.yaml
62-
# - name: SERVICE_NAMESPACE # namespace of the service
63-
# objref:
64-
# kind: Service
65-
# version: v1
66-
# name: webhook-service
67-
# fieldref:
68-
# fieldpath: metadata.namespace
69-
# - name: SERVICE_NAME
70-
# objref:
71-
# kind: Service
72-
# version: v1
73-
# name: webhook-service

config/default/manager_config_patch.yaml

-20
This file was deleted.

config/manager/controller_manager_config.yaml

-21
This file was deleted.

config/manager/kustomization.yaml

-7
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,3 @@ resources:
33

44
generatorOptions:
55
disableNameSuffixHash: true
6-
7-
configMapGenerator:
8-
- files:
9-
- controller_manager_config.yaml
10-
name: manager-config
11-
apiVersion: kustomize.config.k8s.io/v1beta1
12-
kind: Kustomization

config/manager/manager.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ spec:
4242
capabilities:
4343
drop:
4444
- "ALL"
45+
env:
46+
- name: NAMESPACE
47+
valueFrom:
48+
fieldRef:
49+
fieldPath: metadata.namespace
4550
ports:
4651
- containerPort: 8080
4752
protocol: TCP

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
k8s.io/component-base v0.26.2
1818
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5
1919
sigs.k8s.io/controller-runtime v0.14.6
20+
sigs.k8s.io/yaml v1.3.0
2021
)
2122

2223
replace sigs.k8s.io/custom-metrics-apiserver => sigs.k8s.io/custom-metrics-apiserver v1.25.1-0.20230306170449-63d8c93851f3
@@ -133,5 +134,4 @@ require (
133134
sigs.k8s.io/custom-metrics-apiserver v0.0.0 // indirect
134135
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
135136
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
136-
sigs.k8s.io/yaml v1.3.0 // indirect
137137
)

main.go

+99-4
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,27 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"context"
2021
"flag"
22+
"fmt"
2123
"os"
24+
"strings"
2225
"time"
2326

2427
instascale "github.com/project-codeflare/instascale/controllers"
28+
instascaleconfig "github.com/project-codeflare/instascale/pkg/config"
2529
mcadv1beta1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1"
2630
quotasubtreev1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/quotaplugins/quotasubtree/v1"
2731
mcadconfig "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/config"
2832
mcad "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/controller/queuejob"
2933
"go.uber.org/zap/zapcore"
3034

35+
corev1 "k8s.io/api/core/v1"
36+
apierrors "k8s.io/apimachinery/pkg/api/errors"
37+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3138
"k8s.io/apimachinery/pkg/runtime"
3239
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
40+
"k8s.io/client-go/kubernetes"
3341
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3442
_ "k8s.io/client-go/plugin/pkg/client/auth"
3543
"k8s.io/client-go/rest"
@@ -38,6 +46,7 @@ import (
3846
ctrl "sigs.k8s.io/controller-runtime"
3947
"sigs.k8s.io/controller-runtime/pkg/healthz"
4048
"sigs.k8s.io/controller-runtime/pkg/log/zap"
49+
"sigs.k8s.io/yaml"
4150

4251
"github.com/project-codeflare/codeflare-operator/pkg/config"
4352
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
@@ -57,6 +66,11 @@ func init() {
5766
}
5867

5968
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+
6074
zapOptions := zap.Options{
6175
Development: true,
6276
TimeEncoder: zapcore.TimeEncoderOfLayout(time.RFC3339),
@@ -67,20 +81,41 @@ func main() {
6781

6882
ctx := ctrl.SetupSignalHandler()
6983

70-
cfg := config.CodeFlareOperatorConfiguration{
84+
cfg := &config.CodeFlareOperatorConfiguration{
85+
ClientConnection: &config.ClientConnection{
86+
QPS: pointer.Float32(50),
87+
Burst: pointer.Int32(100),
88+
},
7189
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+
},
7298
LeaderElection: &configv1alpha1.LeaderElectionConfiguration{},
7399
},
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+
},
76107
}
77108

78109
kubeConfig, err := ctrl.GetConfig()
79110
exitOnError(err, "unable to get client config")
80-
81111
if kubeConfig.UserAgent == "" {
82112
kubeConfig.UserAgent = "codeflare-operator"
83113
}
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+
84119
kubeConfig.Burst = int(pointer.Int32Deref(cfg.ClientConnection.Burst, int32(rest.DefaultBurst)))
85120
kubeConfig.QPS = pointer.Float32Deref(cfg.ClientConnection.QPS, rest.DefaultQPS)
86121
setupLog.V(2).Info("REST client", "qps", kubeConfig.QPS, "burst", kubeConfig.Burst)
@@ -122,6 +157,66 @@ func main() {
122157
exitOnError(mgr.Start(ctx), "error running manager")
123158
}
124159

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+
125220
func exitOnError(err error, msg string) {
126221
if err != nil {
127222
setupLog.Error(err, msg)

0 commit comments

Comments
 (0)