Skip to content

Commit 03e17b7

Browse files
committed
add state for nic configuration operator
Signed-off-by: Alexander Maslennikov <[email protected]>
1 parent c295d3f commit 03e17b7

File tree

3 files changed

+612
-1
lines changed

3 files changed

+612
-1
lines changed

pkg/state/factory.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,15 @@ func newNicClusterPolicyStates(k8sAPIClient client.Client) ([]State, error) {
129129
if err != nil {
130130
return nil, errors.Wrapf(err, "failed to create doca-telemetry-service State")
131131
}
132+
nicConfigurationOperatorState, _, err := NewStateNicConfigurationOperator(
133+
k8sAPIClient, filepath.Join(manifestBaseDir, "state-nic-configuration-operator"))
134+
if err != nil {
135+
return nil, errors.Wrapf(err, "failed to create NIC Configuration Operator State")
136+
}
132137
return []State{
133138
multusState, cniPluginsState, ipoibState, whereaboutState,
134139
ofedState, sriovDpState, sharedDpState, ibKubernetesState, nvIpamCniState,
135-
nicFeatureDiscoveryState, docaTelemetryServiceState}, nil
140+
nicFeatureDiscoveryState, docaTelemetryServiceState, nicConfigurationOperatorState}, nil
136141
}
137142

138143
// newMacvlanNetworkStates creates states that reconcile MacvlanNetwork CRD
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
2025 NVIDIA CORPORATION & AFFILIATES
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package state //nolint:dupl
18+
19+
import (
20+
"context"
21+
22+
"github.com/go-logr/logr"
23+
"github.com/pkg/errors"
24+
appsv1 "k8s.io/api/apps/v1"
25+
v1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27+
"sigs.k8s.io/controller-runtime/pkg/client"
28+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
29+
"sigs.k8s.io/controller-runtime/pkg/log"
30+
31+
mellanoxv1alpha1 "github.com/Mellanox/network-operator/api/v1alpha1"
32+
"github.com/Mellanox/network-operator/pkg/config"
33+
"github.com/Mellanox/network-operator/pkg/consts"
34+
"github.com/Mellanox/network-operator/pkg/render"
35+
"github.com/Mellanox/network-operator/pkg/utils"
36+
)
37+
38+
// NewStateNicConfigurationOperator creates a new state for NIC Configuration Operator
39+
func NewStateNicConfigurationOperator(
40+
k8sAPIClient client.Client, manifestDir string) (State, ManifestRenderer, error) {
41+
files, err := utils.GetFilesWithSuffix(manifestDir, render.ManifestFileSuffix...)
42+
if err != nil {
43+
return nil, nil, errors.Wrap(err, "failed to get files from manifest dir")
44+
}
45+
46+
renderer := render.NewRenderer(files)
47+
state := &stateNicConfigurationOperator{
48+
stateSkel: stateSkel{
49+
name: "state-nic-configuration-operator",
50+
description: "NIC Configuration Operator deployed in the cluster",
51+
client: k8sAPIClient,
52+
renderer: renderer,
53+
}}
54+
return state, state, nil
55+
}
56+
57+
type nicConfigurationOperatorRuntimeSpec struct {
58+
runtimeSpec
59+
IsOpenshift bool
60+
ContainerResources ContainerResourcesMap
61+
}
62+
63+
type stateNicConfigurationOperator struct {
64+
stateSkel
65+
}
66+
67+
// NicConfigurationOperatorManifestRenderData contains data used to render K8s objects related to NIC Config Operator.
68+
type NicConfigurationOperatorManifestRenderData struct {
69+
CrSpec *mellanoxv1alpha1.NicConfigurationOperatorSpec
70+
NodeAffinity *v1.NodeAffinity
71+
Tolerations []v1.Toleration
72+
RuntimeSpec *nicConfigurationOperatorRuntimeSpec
73+
}
74+
75+
// Sync attempt to get the system to match the desired state which State represent.
76+
// a sync operation must be relatively short and must not block the execution thread.
77+
//
78+
//nolint:dupl
79+
func (s *stateNicConfigurationOperator) Sync(
80+
ctx context.Context, customResource interface{}, infoCatalog InfoCatalog) (SyncState, error) {
81+
reqLogger := log.FromContext(ctx)
82+
cr := customResource.(*mellanoxv1alpha1.NicClusterPolicy)
83+
reqLogger.V(consts.LogLevelInfo).Info(
84+
"Sync Custom resource", "State:", s.name, "Name:", cr.Name, "Namespace:", cr.Namespace)
85+
86+
if cr.Spec.NicConfigurationOperator == nil {
87+
// Either this state was not required to run or an update occurred, and we need to remove
88+
// the resources that where created.
89+
return s.handleStateObjectsDeletion(ctx)
90+
}
91+
92+
staticInfo := infoCatalog.GetStaticConfigProvider()
93+
if staticInfo == nil {
94+
return SyncStateError, errors.New("unexpected state, catalog does not provide static info")
95+
}
96+
97+
clusterInfo := infoCatalog.GetClusterTypeProvider()
98+
if clusterInfo == nil {
99+
return SyncStateError, errors.New("unexpected state, catalog does not provide cluster type info")
100+
}
101+
102+
// Fill ManifestRenderData and render objects
103+
objs, err := s.GetManifestObjects(ctx, cr, infoCatalog, reqLogger)
104+
if err != nil {
105+
return SyncStateNotReady, errors.Wrap(err, "failed to create k8s objects from manifest")
106+
}
107+
if len(objs) == 0 {
108+
return SyncStateNotReady, nil
109+
}
110+
111+
// Create objects if they don't exist, Update objects if they do exist
112+
err = s.createOrUpdateObjs(ctx, func(obj *unstructured.Unstructured) error {
113+
if err := controllerutil.SetControllerReference(cr, obj, s.client.Scheme()); err != nil {
114+
return errors.Wrap(err, "failed to set controller reference for object")
115+
}
116+
return nil
117+
}, objs)
118+
if err != nil {
119+
return SyncStateNotReady, errors.Wrap(err, "failed to create/update objects")
120+
}
121+
122+
waitForStaleObjectsRemoval, err := s.handleStaleStateObjects(ctx, objs)
123+
if err != nil {
124+
return SyncStateNotReady, errors.Wrap(err, "failed to handle state stale objects")
125+
}
126+
if waitForStaleObjectsRemoval {
127+
return SyncStateNotReady, nil
128+
}
129+
// Check objects status
130+
syncState, err := s.getSyncState(ctx, objs)
131+
if err != nil {
132+
return SyncStateNotReady, errors.Wrap(err, "failed to get sync state")
133+
}
134+
return syncState, nil
135+
}
136+
137+
// GetWatchSources returns a map of source kinds that should be watched for the state keyed by the source kind name
138+
func (s *stateNicConfigurationOperator) GetWatchSources() map[string]client.Object {
139+
wr := make(map[string]client.Object)
140+
wr["DaemonSet"] = &appsv1.DaemonSet{}
141+
wr["Deployment"] = &appsv1.Deployment{}
142+
wr["ConfigMap"] = &v1.ConfigMap{}
143+
return wr
144+
}
145+
146+
func (s *stateNicConfigurationOperator) GetManifestObjects(
147+
_ context.Context, cr *mellanoxv1alpha1.NicClusterPolicy,
148+
catalog InfoCatalog, reqLogger logr.Logger) ([]*unstructured.Unstructured, error) {
149+
if cr == nil || cr.Spec.NicConfigurationOperator == nil {
150+
return nil, errors.New("failed to render objects: state spec is nil")
151+
}
152+
153+
clusterInfo := catalog.GetClusterTypeProvider()
154+
if clusterInfo == nil {
155+
return nil, errors.New("clusterInfo provider required")
156+
}
157+
staticConfig := catalog.GetStaticConfigProvider()
158+
if staticConfig == nil {
159+
return nil, errors.New("staticConfig provider required")
160+
}
161+
renderData := &NicConfigurationOperatorManifestRenderData{
162+
CrSpec: cr.Spec.NicConfigurationOperator,
163+
NodeAffinity: cr.Spec.NodeAffinity,
164+
Tolerations: cr.Spec.Tolerations,
165+
RuntimeSpec: &nicConfigurationOperatorRuntimeSpec{
166+
runtimeSpec: runtimeSpec{Namespace: config.FromEnv().State.NetworkOperatorResourceNamespace},
167+
IsOpenshift: clusterInfo.IsOpenshift(),
168+
ContainerResources: createContainerResourcesMap(append(
169+
cr.Spec.NicConfigurationOperator.Operator.ContainerResources,
170+
cr.Spec.NicConfigurationOperator.ConfigurationDaemon.ContainerResources...)),
171+
},
172+
}
173+
174+
// render objects
175+
reqLogger.V(consts.LogLevelDebug).Info("Rendering objects", "data:", renderData)
176+
objs, err := s.renderer.RenderObjects(&render.TemplatingData{Data: renderData})
177+
178+
if err != nil {
179+
return nil, errors.Wrap(err, "failed to render objects")
180+
}
181+
182+
reqLogger.V(consts.LogLevelDebug).Info("Rendered", "objects:", objs)
183+
return objs, nil
184+
}

0 commit comments

Comments
 (0)