1 package nodeagent
2
3 import (
4 "context"
5 "time"
6
7 "github.com/go-logr/logr"
8
9 corev1 "k8s.io/api/core/v1"
10 "k8s.io/apimachinery/pkg/types"
11 kuberecorder "k8s.io/client-go/tools/record"
12 ctrl "sigs.k8s.io/controller-runtime"
13 "sigs.k8s.io/controller-runtime/pkg/client"
14 "sigs.k8s.io/controller-runtime/pkg/reconcile"
15
16 ctrlReconcile "edge-infra.dev/pkg/k8s/runtime/controller/reconcile"
17 "edge-infra.dev/pkg/lib/pprof"
18 "edge-infra.dev/pkg/sds/ien"
19
20 "edge-infra.dev/pkg/k8s/meta/status"
21 "edge-infra.dev/pkg/k8s/runtime/conditions"
22 "edge-infra.dev/pkg/k8s/runtime/controller/metrics"
23 controllerReconciler "edge-infra.dev/pkg/k8s/runtime/controller/reconcile"
24 "edge-infra.dev/pkg/k8s/runtime/events"
25 "edge-infra.dev/pkg/k8s/runtime/patch"
26
27 "edge-infra.dev/pkg/k8s/runtime/controller"
28 v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
29
30 "edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
31 "edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/internal"
32 )
33
34 var (
35 sdsNamespace = "sds"
36 ienctlName = "ienctl"
37 RequeueTime = time.Minute * 2
38 RootPath = "/"
39 )
40
41
42
43
44 var IENodeConditions = controllerReconciler.Conditions{
45 Target: status.ReadyCondition,
46 Owned: []string{
47 string(v1ien.IENController),
48 },
49 Summarize: []string{
50 string(v1ien.IENController),
51 },
52 NegativePolarity: []string{},
53 }
54
55
56 type Controller struct {
57 client.Client
58 kuberecorder.EventRecorder
59 Log logr.Logger
60 Name string
61 RequeueTime time.Duration
62 Config config.Config
63 Conditions controllerReconciler.Conditions
64 Metrics metrics.Metrics
65 *v1ien.IENode
66 }
67
68
69 func Run(flags config.Flags, opts ...controller.Option) error {
70 log := ctrl.Log
71
72 if flags.Pprof != nil && *flags.Pprof {
73 log.Info("serving pprof on /debug/pprof/")
74 opts = append(opts, controller.WithPProf("/", pprof.Router()))
75 }
76
77 cmgr, err := createControllerManager(opts...)
78 if err != nil {
79 return err
80 }
81
82 eventRecorder := events.NewRecorder(cmgr, ctrl.Log, "nodeagent")
83 mgr, err := registerControllers(flags, cmgr, eventRecorder)
84 if err != nil {
85 return err
86 }
87
88 if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
89 log.Error(err, "problem running manager")
90 return err
91 }
92
93 return nil
94 }
95
96
97
98 func (c *Controller) Summarizer(ctx context.Context, patcher *patch.SerialPatcher, result ctrlReconcile.Result) (res ctrl.Result, recErr error) {
99 s := controllerReconciler.NewSummarizer(patcher)
100 return s.SummarizeAndPatch(ctx, c.IENode,
101 controllerReconciler.WithConditions(c.Conditions),
102 controllerReconciler.WithResult(result),
103 controllerReconciler.WithError(recErr),
104 controllerReconciler.WithIgnoreNotFound(),
105 controllerReconciler.WithProcessors(
106 controllerReconciler.RecordReconcileReq,
107 controllerReconciler.RecordResult,
108 ),
109 controllerReconciler.WithFieldOwner(c.Name),
110 controllerReconciler.WithEventRecorder(c.EventRecorder),
111 )
112 }
113
114
115
116 func registerControllers(flags config.Flags, mgr ctrl.Manager, eventRecorder kuberecorder.EventRecorder) (ctrl.Manager, error) {
117 cfg := config.NewConfig(mgr.GetClient(), mgr.GetAPIReader(), eventRecorder, flags)
118 metrics := metrics.New(mgr, "nodeagent",
119 metrics.WithSuspend(),
120 metrics.WithCollectors(
121 internal.NodeAgentReadinessMetric,
122 internal.NodeAgentDurationMetric,
123 ),
124 )
125
126
127 ienctl := newIENController(mgr, cfg, metrics)
128 if err := setupIENControllerWithManager(&ienctl, mgr); err != nil {
129 return nil, err
130 }
131
132
133 fwctl := newGenericController("fwctl", mgr, cfg, metrics, &v1ien.NodeFirewall{})
134 if err := setupNodeFirewallControllerWithManager(&fwctl, mgr); err != nil {
135 return nil, err
136 }
137
138
139 secretctl := newGenericController("secretctl", mgr, cfg, metrics, &corev1.Secret{})
140 if err := setupWithManager(&secretctl, mgr, cfg.GetFlags()); err != nil {
141 return nil, err
142 }
143
144
145 configctl := newGenericController("configctl", mgr, cfg, metrics, &corev1.ConfigMap{})
146 if err := setupWithManager(&configctl, mgr, cfg.GetFlags()); err != nil {
147 return nil, err
148 }
149 return mgr, nil
150 }
151
152
153
154 func (c *Controller) createReconcileRequests(_ context.Context, _ client.Object) []reconcile.Request {
155 hostname, err := ien.GetHostname()
156 if err != nil {
157 c.Log.Error(err, "error getting hostname for node")
158 return []reconcile.Request{}
159 }
160
161 return []reconcile.Request{
162 {
163 NamespacedName: types.NamespacedName{
164 Name: hostname,
165 },
166 },
167 }
168 }
169
170
171
172
173 func (c *Controller) initializeControllerMetrics(ctx context.Context) (*internal.ControllerMetrics, error) {
174 hostname := c.IENode.ObjectMeta.GetName()
175 class := string(c.IENode.Spec.Class)
176
177 node := corev1.Node{}
178 err := c.Client.Get(ctx, client.ObjectKey{Name: hostname}, &node)
179 if err != nil {
180 c.Log.Error(err, "error getting node info")
181 return nil, err
182 }
183
184 ienVersion := node.ObjectMeta.Labels["feature.node.kubernetes.io/ien-version"]
185 lane := node.ObjectMeta.Labels["node.ncr.com/lane"]
186 return internal.CreateNewControllerMetrics(c.IENode, hostname, class, lane, ienVersion), nil
187 }
188
189
190 func (c *Controller) isPluginEnabled(ctx context.Context, ien *v1ien.IENode, pluginName string) bool {
191 pluginEnabled, err := c.Config.IsPluginEnabled(ctx, pluginName)
192 if err != nil {
193 conditions.MarkUnknown(ien, pluginName, string(v1ien.PluginFailed), "error: %v", err)
194 }
195 if !pluginEnabled {
196 conditions.MarkTrue(ien, pluginName, string(v1ien.PluginDisabled), "%s", string(v1ien.Disabled))
197 }
198 return pluginEnabled
199 }
200
View as plain text