diff --git a/business/istio_config.go b/business/istio_config.go index 531094ca16..3f8bd7be8e 100644 --- a/business/istio_config.go +++ b/business/istio_config.go @@ -161,7 +161,7 @@ func (in *IstioConfigService) GetIstioConfigListForNamespace(ctx context.Context if _, err := in.businessLayer.Namespace.GetClusterNamespace(ctx, namespace, cluster); err != nil { // Check if the namespace exists on the cluster in multi-cluster mode. // TODO: Remove this once other business methods stop looping over all clusters. - if api_errors.IsNotFound(err) && len(in.userClients) > 1 { + if (api_errors.IsNotFound(err) || api_errors.IsForbidden(err)) && len(in.userClients) > 1 { return &models.IstioConfigList{}, nil } return nil, err diff --git a/business/namespaces.go b/business/namespaces.go index f5899efaa8..8b212bcc1a 100644 --- a/business/namespaces.go +++ b/business/namespaces.go @@ -598,7 +598,10 @@ func (in *NamespaceService) GetClusterNamespace(ctx context.Context, namespace s } // Refresh namespace in cache since we've just fetched it from the API. - in.kialiCache.SetNamespace(client.GetToken(), result) + if _, err := in.GetClusterNamespaces(ctx, cluster); err != nil { + log.Errorf("Unable to refresh cache for cluster [%s]: %s", cluster, err) + } + return &result, nil } @@ -634,7 +637,11 @@ func (in *NamespaceService) UpdateNamespace(ctx context.Context, namespace strin kubeCache.Refresh(namespace) in.kialiCache.RefreshTokenNamespaces(cluster) - // Call GetNamespace to update the caching + // Call GetClusterNamespaces to update the cache for this cluster. + if _, err := in.GetClusterNamespaces(ctx, cluster); err != nil { + return nil, err + } + return in.GetClusterNamespace(ctx, namespace, cluster) } diff --git a/business/services.go b/business/services.go index 74f7aa1dd6..3b58f34506 100644 --- a/business/services.go +++ b/business/services.go @@ -668,7 +668,6 @@ func (in *SvcService) UpdateService(ctx context.Context, cluster, namespace, ser return nil, err } kubeCache.Refresh(namespace) - in.kialiCache.RefreshTokenNamespaces(cluster) // After the update we fetch the whole workload return in.GetServiceDetails(ctx, cluster, namespace, service, interval, queryTime) diff --git a/handlers/apps.go b/handlers/apps.go index 5949f72ade..80cb284197 100644 --- a/handlers/apps.go +++ b/handlers/apps.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/gorilla/mux" + "golang.org/x/exp/slices" "github.com/kiali/kiali/business" "github.com/kiali/kiali/models" @@ -48,23 +49,27 @@ func (p *appParams) extract(r *http.Request) { // ClustersApps is the API handler to fetch all the apps to be displayed, related to a single cluster func ClustersApps(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - namespaces := query.Get("namespaces") // csl of namespaces - nss := []string{} - if len(namespaces) > 0 { - nss = strings.Split(namespaces, ",") - } + namespacesQueryParam := query.Get("namespaces") // csl of namespaces p := appParams{} p.extract(r) - // Get business layer businessLayer, err := getBusiness(r) if err != nil { RespondWithError(w, http.StatusInternalServerError, "Apps initialization error: "+err.Error()) return } - if len(nss) == 0 { - loadedNamespaces, _ := businessLayer.Namespace.GetClusterNamespaces(r.Context(), p.ClusterName) - for _, ns := range loadedNamespaces { + + nss := []string{} + namespacesFromQueryParams := strings.Split(namespacesQueryParam, ",") + loadedNamespaces, _ := businessLayer.Namespace.GetClusterNamespaces(r.Context(), p.ClusterName) + for _, ns := range loadedNamespaces { + // If namespaces have been provided in the query, further filter the results to only include those namespaces. + if len(namespacesQueryParam) > 0 { + if slices.Contains(namespacesFromQueryParams, ns.Name) { + nss = append(nss, ns.Name) + } + } else { + // Otherwise no namespaces have been provided in the query params, so include all namespaces the user has access to. nss = append(nss, ns.Name) } } @@ -75,8 +80,10 @@ func ClustersApps(w http.ResponseWriter, r *http.Request) { } for _, ns := range nss { - criteria := business.AppCriteria{Cluster: p.ClusterName, Namespace: ns, IncludeIstioResources: p.IncludeIstioResources, - IncludeHealth: p.IncludeHealth, RateInterval: p.RateInterval, QueryTime: p.QueryTime} + criteria := business.AppCriteria{ + Cluster: p.ClusterName, Namespace: ns, IncludeIstioResources: p.IncludeIstioResources, + IncludeHealth: p.IncludeHealth, RateInterval: p.RateInterval, QueryTime: p.QueryTime, + } if p.IncludeHealth { rateInterval, err := adjustRateInterval(r.Context(), businessLayer, ns, p.RateInterval, p.QueryTime, p.ClusterName) @@ -104,8 +111,10 @@ func AppDetails(w http.ResponseWriter, r *http.Request) { p := appParams{} p.extract(r) - criteria := business.AppCriteria{Namespace: p.Namespace, AppName: p.AppName, IncludeIstioResources: true, IncludeHealth: p.IncludeHealth, - RateInterval: p.RateInterval, QueryTime: p.QueryTime, Cluster: p.ClusterName} + criteria := business.AppCriteria{ + Namespace: p.Namespace, AppName: p.AppName, IncludeIstioResources: true, IncludeHealth: p.IncludeHealth, + RateInterval: p.RateInterval, QueryTime: p.QueryTime, Cluster: p.ClusterName, + } // Get business layer business, err := getBusiness(r)