Loading...
Loading...
Compare original and translation side by side
grafana-app-sdk project component add operatorgrafana-app-sdk project component add operatoroperator.TypedReconcilerReconcileFunctype MyKindReconciler struct {
operator.TypedReconciler[*v1alpha1.MyKind]
client resource.Client
}
func NewMyKindReconciler(client resource.Client) *MyKindReconciler {
r := &MyKindReconciler{client: client}
r.ReconcileFunc = r.reconcile // wire the typed func
return r
}
func (r *MyKindReconciler) reconcile(
ctx context.Context,
req operator.TypedReconcileRequest[*v1alpha1.MyKind],
) (operator.ReconcileResult, error) {
obj := req.Object
// Skip if already reconciled this generation
if obj.GetGeneration() == obj.Status.LastObservedGeneration && req.Action != operator.ReconcileActionDeleted {
return operator.ReconcileResult{}, nil
}
log := logging.FromContext(ctx).With("name", obj.GetName(), "namespace", obj.GetNamespace())
log.Info("reconciling", "action", operator.ResourceActionFromReconcileAction(req.Action))
// Handle deletion
if req.Action == operator.ReconcileActionDeleted {
return operator.ReconcileResult{}, nil
}
// ... business logic ...
// Atomic status update with conflict resolution
_, err := resource.UpdateObject(ctx, r.client, obj.GetStaticMetadata().Identifier(),
func(obj *v1alpha1.MyKind, _ bool) (*v1alpha1.MyKind, error) {
obj.Status.LastObservedGeneration = obj.GetGeneration()
obj.Status.State = "Ready"
return obj, nil
},
resource.UpdateOptions{Subresource: "status"},
)
return operator.ReconcileResult{}, err
}operator.ReconcileActionReconcileActionCreatedReconcileActionUpdatedReconcileActionDeletedReconcileActionResyncedRequeueAfterreturn operator.ReconcileResult{RequeueAfter: 10 * time.Second}, niloperator.TypedReconcilerReconcileFunctype MyKindReconciler struct {
operator.TypedReconciler[*v1alpha1.MyKind]
client resource.Client
}
func NewMyKindReconciler(client resource.Client) *MyKindReconciler {
r := &MyKindReconciler{client: client}
r.ReconcileFunc = r.reconcile // 绑定类型化函数
return r
}
func (r *MyKindReconciler) reconcile(
ctx context.Context,
req operator.TypedReconcileRequest[*v1alpha1.MyKind],
) (operator.ReconcileResult, error) {
obj := req.Object
// 若当前世代已完成 reconcile,则跳过
if obj.GetGeneration() == obj.Status.LastObservedGeneration && req.Action != operator.ReconcileActionDeleted {
return operator.ReconcileResult{}, nil
}
log := logging.FromContext(ctx).With("name", obj.GetName(), "namespace", obj.GetNamespace())
log.Info("reconciling", "action", operator.ResourceActionFromReconcileAction(req.Action))
// 处理删除操作
if req.Action == operator.ReconcileActionDeleted {
return operator.ReconcileResult{}, nil
}
// ... 业务逻辑 ...
// 带冲突解决的原子状态更新
_, err := resource.UpdateObject(ctx, r.client, obj.GetStaticMetadata().Identifier(),
func(obj *v1alpha1.MyKind, _ bool) (*v1alpha1.MyKind, error) {
obj.Status.LastObservedGeneration = obj.GetGeneration()
obj.Status.State = "Ready"
return obj, nil
},
resource.UpdateOptions{Subresource: "status"},
)
return operator.ReconcileResult{}, err
}operator.ReconcileActionReconcileActionCreatedReconcileActionUpdatedReconcileActionDeletedReconcileActionResyncedRequeueAfterreturn operator.ReconcileResult{RequeueAfter: 10 * time.Second}, nilresource.UpdateObjectresource.UpdateObjectresource.UpdateObject409 Conflict_, err := resource.UpdateObject(ctx, r.client, identifier,
func(obj *v1alpha1.MyKind, exists bool) (*v1alpha1.MyKind, error) {
obj.Status.LastObservedGeneration = obj.GetGeneration()
obj.Status.State = "Ready"
obj.Status.Message = ""
return obj, nil
},
resource.UpdateOptions{Subresource: "status"},
)client.Updateresource.UpdateObject409 Conflict_, err := resource.UpdateObject(ctx, r.client, identifier,
func(obj *v1alpha1.MyKind, exists bool) (*v1alpha1.MyKind, error) {
obj.Status.LastObservedGeneration = obj.GetGeneration()
obj.Status.State = "Ready"
obj.Status.Message = ""
return obj, nil
},
resource.UpdateOptions{Subresource: "status"},
)client.UpdateLastObservedGenerationif obj.GetGeneration() == obj.Status.LastObservedGeneration {
return operator.ReconcileResult{}, nil
}LastObservedGenerationif obj.GetGeneration() == obj.Status.LastObservedGeneration {
return operator.ReconcileResult{}, nil
}BasicReconcileOptionsAppManagedKind{
Kind: mykindv1alpha1.MyKindKind(),
Reconciler: reconciler,
ReconcileOptions: simple.BasicReconcileOptions{
Namespace: "my-namespace", // watch one namespace; default is all
LabelFilters: []string{"env=prod"}, // only reconcile matching resources
FieldSelectors: []string{"status.phase=Running"},
UsePlain: false, // false = wrap in OpinionatedReconciler (default)
// true = use reconciler directly, no finalizer management
},
},UsePlain: falseOpinionatedReconcilerAppManagedKindBasicReconcileOptions{
Kind: mykindv1alpha1.MyKindKind(),
Reconciler: reconciler,
ReconcileOptions: simple.BasicReconcileOptions{
Namespace: "my-namespace", // 监听单个命名空间;默认监听所有
LabelFilters: []string{"env=prod"}, // 仅 reconcile 匹配标签的资源
FieldSelectors: []string{"status.phase=Running"},
UsePlain: false, // false = 使用 OpinionatedReconciler 包装(默认)
// true = 直接使用 reconciler,不管理终结器
},
},UsePlain: falseOpinionatedReconcilerWatcherAddUpdateDeletetype MyKindWatcher struct {
client resource.Client
}
func (w *MyKindWatcher) Add(ctx context.Context, obj resource.Object) error {
typed := obj.(*v1alpha1.MyKind)
// handle create
return nil
}
func (w *MyKindWatcher) Update(ctx context.Context, obj, old resource.Object) error {
typed := obj.(*v1alpha1.MyKind)
// handle update
return nil
}
func (w *MyKindWatcher) Delete(ctx context.Context, obj resource.Object) error {
// handle delete
return nil
}
func (w *MyKindWatcher) Sync(ctx context.Context, obj resource.Object) error {
// called on resync; handle like Add if needed
return nil
}WatcherReconcilerAppManagedKindWatcherAddUpdateDeletetype MyKindWatcher struct {
client resource.Client
}
func (w *MyKindWatcher) Add(ctx context.Context, obj resource.Object) error {
typed := obj.(*v1alpha1.MyKind)
// 处理创建操作
return nil
}
func (w *MyKindWatcher) Update(ctx context.Context, obj, old resource.Object) error {
typed := obj.(*v1alpha1.MyKind)
// 处理更新操作
return nil
}
func (w *MyKindWatcher) Delete(ctx context.Context, obj resource.Object) error {
// 处理删除操作
return nil
}
func (w *MyKindWatcher) Sync(ctx context.Context, obj resource.Object) error {
// 重新同步时调用;若需要可按 Add 逻辑处理
return nil
}AppManagedKindWatcherReconcilerUnmanagedKindsAppConfigUnmanagedKinds: []simple.AppUnmanagedKind{
{
Kind: corev1.ConfigMapKind(),
Reconciler: &ConfigMapReconciler{},
ReconcileOptions: simple.UnmanagedKindReconcileOptions{
Namespace: "my-namespace",
LabelFilters: []string{"app=my-app"},
UseOpinionated: false, // don't add finalizers to unmanaged resources
},
},
},AppConfigUnmanagedKindsUnmanagedKinds: []simple.AppUnmanagedKind{
{
Kind: corev1.ConfigMapKind(),
Reconciler: &ConfigMapReconciler{},
ReconcileOptions: simple.UnmanagedKindReconcileOptions{
Namespace: "my-namespace",
LabelFilters: []string{"app=my-app"},
UseOpinionated: false, // 不为非托管资源添加终结器
},
},
},func New(cfg app.Config) (app.App, error) {
cfg.KubeConfig.APIPath = "/apis"
client, err := k8s.NewClientRegistry(cfg.KubeConfig, k8s.DefaultClientConfig()).
ClientFor(mykindv1alpha2.MyKindKind())
if err != nil {
return nil, fmt.Errorf("creating client: %w", err)
}
a, err := simple.NewApp(simple.AppConfig{
Name: "my-app",
KubeConfig: cfg.KubeConfig,
ManagedKinds: []simple.AppManagedKind{
{
Kind: mykindv1alpha1.MyKindKind(),
Validator: NewValidator(),
Mutator: NewMutator(),
},
{
// Attach reconciler to latest version only
Kind: mykindv1alpha2.MyKindKind(),
Reconciler: NewMyKindReconciler(client),
Validator: NewValidator(),
Mutator: NewMutator(),
},
},
})
if err != nil {
return nil, fmt.Errorf("error creating app: %w", err)
}
if err = a.ValidateManifest(cfg.ManifestData); err != nil {
return nil, fmt.Errorf("app manifest validation failed: %w", err)
}
return a, nil
}func New(cfg app.Config) (app.App, error) {
cfg.KubeConfig.APIPath = "/apis"
client, err := k8s.NewClientRegistry(cfg.KubeConfig, k8s.DefaultClientConfig()).
ClientFor(mykindv1alpha2.MyKindKind())
if err != nil {
return nil, fmt.Errorf("creating client: %w", err)
}
a, err := simple.NewApp(simple.AppConfig{
Name: "my-app",
KubeConfig: cfg.KubeConfig,
ManagedKinds: []simple.AppManagedKind{
{
Kind: mykindv1alpha1.MyKindKind(),
Validator: NewValidator(),
Mutator: NewMutator(),
},
{
// 仅将 reconciler 附加到最新版本
Kind: mykindv1alpha2.MyKindKind(),
Reconciler: NewMyKindReconciler(client),
Validator: NewValidator(),
Mutator: NewMutator(),
},
},
})
if err != nil {
return nil, fmt.Errorf("error creating app: %w", err)
}
if err = a.ValidateManifest(cfg.ManifestData); err != nil {
return nil, fmt.Errorf("app manifest validation failed: %w", err)
}
return a, nil
}