@@ -107,8 +107,8 @@ type CarvelResponse struct {
107107type ConfigResponse struct {
108108 SystemViews map [string ][]SystemView `json:"systemViews"`
109109 FluxCD FluxCDResponse `json:"fluxcd"`
110- Carvel CarvelResponse `json:"carvel"`
111- }
110+ Carvel CarvelResponse `json:"carvel"`
111+ }
112112
113113// defaultSystemViews contains the built‑in system views that were previously hardcoded in ViewBar.tsx.
114114// They are now served from the backend so they can be centrally controlled and customized.
@@ -176,7 +176,7 @@ var defaultSystemViews = []SystemView{
176176 {Name : "Namespace" , Value : "all-namespaces" },
177177 },
178178 },
179- }
179+ }
180180
181181// defaultSystemViewMap exposes the built‑in system views under the "*"
182182// wildcard key so that all contexts share the same defaults unless
@@ -482,7 +482,8 @@ func (s *Server) Setup() {
482482 })
483483 }
484484
485- // HelmRelease has sourceRef at spec.chart.spec.sourceRef or via spec.chartRef (HelmChart resource),
485+ // HelmRelease has sourceRef at spec.chart.spec.sourceRef or via spec.chartRef
486+ // (either a HelmChart resource which in turn has spec.sourceRef, or directly an OCIRepository).
486487 // while Kustomization and Terraform have it at spec.sourceRef
487488 var sourceRef map [string ]interface {}
488489 if kind == "HelmRelease" {
@@ -495,7 +496,7 @@ func (s *Server) Setup() {
495496 }
496497 }
497498
498- // If no inline chart sourceRef, try chartRef (HelmChart resource)
499+ // If no inline chart sourceRef, try chartRef (HelmChart or OCIRepository resource)
499500 if sourceRef == nil {
500501 if chartRef , ok := spec ["chartRef" ].(map [string ]interface {}); ok {
501502 chartRefKind , _ := chartRef ["kind" ].(string )
@@ -505,37 +506,50 @@ func (s *Server) Setup() {
505506 chartRefNamespace = ns
506507 }
507508
508- // Get the HelmChart resource to find its sourceRef
509- if chartRefKind == "HelmChart" && chartRefName != "" {
510- helmChartAPIPath , err := proxy .getFluxAPIPath (ctx , "HelmChart" )
511- if err != nil {
512- log .Printf ("Error discovering HelmChart API path: %v" , err )
513- return c .JSON (http .StatusInternalServerError , map [string ]string {
514- "error" : fmt .Sprintf ("Failed to discover HelmChart API path: %v" , err ),
515- })
516- }
509+ if chartRefName != "" {
510+ switch chartRefKind {
511+ case "HelmChart" :
512+ // Get the HelmChart resource to find its sourceRef
513+ helmChartAPIPath , err := proxy .getFluxAPIPath (ctx , "HelmChart" )
514+ if err != nil {
515+ log .Printf ("Error discovering HelmChart API path: %v" , err )
516+ return c .JSON (http .StatusInternalServerError , map [string ]string {
517+ "error" : fmt .Sprintf ("Failed to discover HelmChart API path: %v" , err ),
518+ })
519+ }
517520
518- helmChartPath := fmt .Sprintf (helmChartAPIPath , chartRefNamespace , chartRefName )
519- helmChartData , err := clientset .RESTClient ().Get ().AbsPath (helmChartPath ).DoRaw (ctx )
520- if err != nil {
521- log .Printf ("Error getting HelmChart resource: %v" , err )
522- return c .JSON (http .StatusInternalServerError , map [string ]string {
523- "error" : fmt .Sprintf ("Failed to get HelmChart resource: %v" , err ),
524- })
525- }
521+ helmChartPath := fmt .Sprintf (helmChartAPIPath , chartRefNamespace , chartRefName )
522+ helmChartData , err := clientset .RESTClient ().Get ().AbsPath (helmChartPath ).DoRaw (ctx )
523+ if err != nil {
524+ log .Printf ("Error getting HelmChart resource: %v" , err )
525+ return c .JSON (http .StatusInternalServerError , map [string ]string {
526+ "error" : fmt .Sprintf ("Failed to get HelmChart resource: %v" , err ),
527+ })
528+ }
526529
527- var helmChartObj map [string ]interface {}
528- if err := json .Unmarshal (helmChartData , & helmChartObj ); err != nil {
529- log .Printf ("Error parsing HelmChart data: %v" , err )
530- return c .JSON (http .StatusInternalServerError , map [string ]string {
531- "error" : fmt .Sprintf ("Failed to parse HelmChart data: %v" , err ),
532- })
533- }
530+ var helmChartObj map [string ]interface {}
531+ if err := json .Unmarshal (helmChartData , & helmChartObj ); err != nil {
532+ log .Printf ("Error parsing HelmChart data: %v" , err )
533+ return c .JSON (http .StatusInternalServerError , map [string ]string {
534+ "error" : fmt .Sprintf ("Failed to parse HelmChart data: %v" , err ),
535+ })
536+ }
534537
535- if helmChartSpec , ok := helmChartObj ["spec" ].(map [string ]interface {}); ok {
536- if srcRef , ok := helmChartSpec ["sourceRef" ].(map [string ]interface {}); ok {
537- sourceRef = srcRef
538+ if helmChartSpec , ok := helmChartObj ["spec" ].(map [string ]interface {}); ok {
539+ if srcRef , ok := helmChartSpec ["sourceRef" ].(map [string ]interface {}); ok {
540+ sourceRef = srcRef
541+ }
538542 }
543+ case "OCIRepository" :
544+ // When chartRef points directly at an OCIRepository, the repository itself is the source.
545+ srcRef := map [string ]interface {}{
546+ "kind" : "OCIRepository" ,
547+ "name" : chartRefName ,
548+ }
549+ if chartRefNamespace != "" {
550+ srcRef ["namespace" ] = chartRefNamespace
551+ }
552+ sourceRef = srcRef
539553 }
540554 }
541555 }
@@ -1243,7 +1257,6 @@ func (s *Server) Setup() {
12431257 })
12441258 })
12451259
1246-
12471260 // Add endpoint for running a CronJob immediately by creating a one-off Job (context-aware)
12481261 // Equivalent to: kubectl create job --from=cronjob/<name> <generated-name>
12491262 s .echo .POST ("/api/:context/cronjob/run" , func (c echo.Context ) error {
@@ -1333,7 +1346,7 @@ func (s *Server) Setup() {
13331346 })
13341347 }
13351348
1336- log .Printf ("[RemoteResource] Fetching %s/%s from namespace %s via parent %s/%s in namespace %s" ,
1349+ log .Printf ("[RemoteResource] Fetching %s/%s from namespace %s via parent %s/%s in namespace %s" ,
13371350 kind , name , namespace , parentKind , parentName , parentNamespace )
13381351
13391352 // Fetch the parent resource (App or PackageInstall) to get cluster config
@@ -1392,7 +1405,7 @@ func (s *Server) Setup() {
13921405 }
13931406
13941407 resourceName := strings .ToLower (kind ) + "s" // default plural
1395- isNamespaced := true // default to namespaced
1408+ isNamespaced := true // default to namespaced
13961409 if resourceLists != nil {
13971410 for _ , resourceList := range resourceLists {
13981411 gv := strings .Split (resourceList .GroupVersion , "/" )
@@ -1428,8 +1441,8 @@ func (s *Server) Setup() {
14281441
14291442 // Check if managedFields should be included
14301443 includeManagedFields := c .QueryParam ("includeManagedFields" ) == "true"
1431-
1432- log .Printf ("[RemoteResource] Fetching resource with GVR: %s/%s/%s (namespaced: %v, namespace: %s, includeManagedFields: %v)" ,
1444+
1445+ log .Printf ("[RemoteResource] Fetching resource with GVR: %s/%s/%s (namespaced: %v, namespace: %s, includeManagedFields: %v)" ,
14331446 targetGVR .Group , targetGVR .Version , targetGVR .Resource , isNamespaced , namespace , includeManagedFields )
14341447
14351448 // Fetch the resource from remote cluster
@@ -2697,80 +2710,80 @@ func (s *Server) handleExecWebSocketWithClient(c echo.Context, client *kubernete
26972710
26982711 // Try each container and shell combination until one works
26992712 for _ , tryContainer := range containersToTry {
2700- for _ , tryShell := range shells {
2713+ for _ , tryShell := range shells {
27012714 log .Printf ("Trying shell %s in container %s for pod %s/%s" , tryShell , tryContainer , namespace , podname )
27022715
2703- var shellExists bool
2704- testMethods := [][]string {
2705- {tryShell , "--version" },
2706- {tryShell , "--help" },
2707- {tryShell , "-c" , "exit 0" },
2708- }
2716+ var shellExists bool
2717+ testMethods := [][]string {
2718+ {tryShell , "--version" },
2719+ {tryShell , "--help" },
2720+ {tryShell , "-c" , "exit 0" },
2721+ }
27092722
2710- for _ , testCmd := range testMethods {
2711- testReq := client .Clientset .CoreV1 ().RESTClient ().Post ().
2712- Resource ("pods" ).
2713- Name (podname ).
2714- Namespace (namespace ).
2715- SubResource ("exec" ).
2716- VersionedParams (& corev1.PodExecOptions {
2723+ for _ , testCmd := range testMethods {
2724+ testReq := client .Clientset .CoreV1 ().RESTClient ().Post ().
2725+ Resource ("pods" ).
2726+ Name (podname ).
2727+ Namespace (namespace ).
2728+ SubResource ("exec" ).
2729+ VersionedParams (& corev1.PodExecOptions {
27172730 Container : tryContainer ,
27182731 Command : testCmd ,
27192732 Stdin : false ,
27202733 Stdout : true ,
27212734 Stderr : true ,
27222735 TTY : false ,
2723- }, scheme .ParameterCodec )
2736+ }, scheme .ParameterCodec )
27242737
2725- testExec , err := remotecommand .NewSPDYExecutor (client .Config , "POST" , testReq .URL ())
2726- if err != nil {
2727- continue
2728- }
2738+ testExec , err := remotecommand .NewSPDYExecutor (client .Config , "POST" , testReq .URL ())
2739+ if err != nil {
2740+ continue
2741+ }
27292742
2730- var testOut , testErr bytes.Buffer
2743+ var testOut , testErr bytes.Buffer
27312744 err = testExec .StreamWithContext (ctx , remotecommand.StreamOptions {
2732- Stdout : & testOut ,
2733- Stderr : & testErr ,
2734- })
2745+ Stdout : & testOut ,
2746+ Stderr : & testErr ,
2747+ })
27352748
2736- if err == nil {
2737- shellExists = true
2749+ if err == nil {
2750+ shellExists = true
27382751 log .Printf ("Shell %s found in container %s using test: %v" , tryShell , tryContainer , testCmd )
2739- break
2752+ break
2753+ }
27402754 }
2741- }
27422755
2743- if ! shellExists {
2756+ if ! shellExists {
27442757 log .Printf ("Shell %s not found in container %s" , tryShell , tryContainer )
2745- continue
2746- }
2758+ continue
2759+ }
27472760
2748- execCmd = []string {tryShell }
2749- req := client .Clientset .CoreV1 ().RESTClient ().Post ().
2750- Resource ("pods" ).
2751- Name (podname ).
2752- Namespace (namespace ).
2753- SubResource ("exec" ).
2754- VersionedParams (& corev1.PodExecOptions {
2761+ execCmd = []string {tryShell }
2762+ req := client .Clientset .CoreV1 ().RESTClient ().Post ().
2763+ Resource ("pods" ).
2764+ Name (podname ).
2765+ Namespace (namespace ).
2766+ SubResource ("exec" ).
2767+ VersionedParams (& corev1.PodExecOptions {
27552768 Container : tryContainer ,
27562769 Command : execCmd ,
27572770 Stdin : true ,
27582771 Stdout : true ,
27592772 Stderr : true ,
27602773 TTY : true ,
2761- }, scheme .ParameterCodec )
2774+ }, scheme .ParameterCodec )
27622775
2763- exec , err := remotecommand .NewSPDYExecutor (client .Config , "POST" , req .URL ())
2764- if err != nil {
2776+ exec , err := remotecommand .NewSPDYExecutor (client .Config , "POST" , req .URL ())
2777+ if err != nil {
27652778 log .Printf ("Failed to create interactive executor for shell %s in container %s: %v" , tryShell , tryContainer , err )
2766- continue
2767- }
2779+ continue
2780+ }
27682781
2769- executor = exec
2770- shell = tryShell
2782+ executor = exec
2783+ shell = tryShell
27712784 containerName = tryContainer
2772- shellFound = true
2773- break
2785+ shellFound = true
2786+ break
27742787 }
27752788
27762789 if shellFound {
0 commit comments