mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-01-27 18:18:41 +00:00
## What this PR does In a previous patch (#1555) the reconciliation loop for the OpenAPI UI resources was accidentally removed. This patch reintroduces a separate controller, which handles updates to CozystackResourceDefinitions and creates, updates, or deletes the dashboard's custom resources. ### Release note ```release-note [dashboard] Reintroduce the accidentally removed reconciler that autoconfigures custom dashboard resources for the OpenAPI UI. ``` Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
82 lines
2.3 KiB
Go
82 lines
2.3 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
dashv1alpha1 "github.com/cozystack/cozystack/api/dashboard/v1alpha1"
|
|
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
|
|
|
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
)
|
|
|
|
// ensureCustomFormsPrefill creates or updates a CustomFormsPrefill resource for the given CRD
|
|
func (m *Manager) ensureCustomFormsPrefill(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) (reconcile.Result, error) {
|
|
logger := log.FromContext(ctx)
|
|
|
|
app := crd.Spec.Application
|
|
group, version, kind := pickGVK(crd)
|
|
plural := pickPlural(kind, crd)
|
|
|
|
name := fmt.Sprintf("%s.%s.%s", group, version, plural)
|
|
customizationID := fmt.Sprintf("default-/%s/%s/%s", group, version, plural)
|
|
|
|
values, err := buildPrefillValues(app.OpenAPISchema)
|
|
if err != nil {
|
|
return reconcile.Result{}, err
|
|
}
|
|
|
|
// Always prefill metadata.name (empty string if not specified in CRD)
|
|
var nameValue string
|
|
if crd.Spec.Dashboard != nil {
|
|
nameValue = strings.TrimSpace(crd.Spec.Dashboard.Name)
|
|
}
|
|
values = append([]interface{}{
|
|
map[string]interface{}{
|
|
"path": toIfaceSlice([]string{"metadata", "name"}),
|
|
"value": nameValue,
|
|
},
|
|
}, values...)
|
|
|
|
cfp := &dashv1alpha1.CustomFormsPrefill{}
|
|
cfp.Name = name // cluster-scoped
|
|
|
|
specMap := map[string]any{
|
|
"customizationId": customizationID,
|
|
"values": values,
|
|
}
|
|
// Use json.Marshal with sorted keys to ensure consistent output
|
|
specBytes, err := json.Marshal(specMap)
|
|
if err != nil {
|
|
return reconcile.Result{}, err
|
|
}
|
|
|
|
_, err = controllerutil.CreateOrUpdate(ctx, m.Client, cfp, func() error {
|
|
if err := controllerutil.SetOwnerReference(crd, cfp, m.Scheme); err != nil {
|
|
return err
|
|
}
|
|
// Add dashboard labels to dynamic resources
|
|
m.addDashboardLabels(cfp, crd, ResourceTypeDynamic)
|
|
|
|
// Only update spec if it's different to avoid unnecessary updates
|
|
newSpec := dashv1alpha1.ArbitrarySpec{
|
|
JSON: apiextv1.JSON{Raw: specBytes},
|
|
}
|
|
if !compareArbitrarySpecs(cfp.Spec, newSpec) {
|
|
cfp.Spec = newSpec
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return reconcile.Result{}, err
|
|
}
|
|
|
|
logger.Info("Applied CustomFormsPrefill", "name", cfp.Name)
|
|
return reconcile.Result{}, nil
|
|
}
|