Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 8 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,40 +354,14 @@ In case multi-cluster support is enabled (default) and you have access to multip

- **kiali_mesh_status** - Get the status of mesh components including Istio, Kiali, Grafana, Prometheus and their interactions, versions, and health status

- **kiali_istio_config** - Get all Istio configuration objects in the mesh including their full YAML resources and details

- **kiali_istio_object_details** - Get detailed information about a specific Istio object including validation and help information
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
- `name` (`string`) **(required)** - Name of the Istio object
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')

- **kiali_istio_object_patch** - Modify an existing Istio object using PATCH method. The JSON patch data will be applied to the existing object.
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
- `json_patch` (`string`) **(required)** - JSON patch data to apply to the object
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
- `name` (`string`) **(required)** - Name of the Istio object
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')

- **kiali_istio_object_create** - Create a new Istio object using POST method. The JSON data will be used to create the new object.
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
- `json_data` (`string`) **(required)** - JSON data for the new object
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
- `namespace` (`string`) **(required)** - Namespace where the Istio object will be created
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')

- **kiali_istio_object_delete** - Delete an existing Istio object using DELETE method.
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
- `name` (`string`) **(required)** - Name of the Istio object
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')

- **kiali_validations_list** - List all the validations in the current cluster from all namespaces
- `namespace` (`string`) - Optional single namespace to retrieve validations from (alternative to namespaces)
- `namespaces` (`string`) - Optional comma-separated list of namespaces to retrieve validations from
- **kiali_manage_istio_config** - Manages Istio configuration objects (Gateways, VirtualServices, etc.). Can list (objects and validations), get, create, patch, or delete objects
- `action` (`string`) **(required)** - Action to perform: list, get, create, patch, or delete
- `group` (`string`) - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
- `json_data` (`string`) - JSON data to apply or create the object
- `kind` (`string`) - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
- `name` (`string`) - Name of the Istio object
- `namespace` (`string`) - Namespace containing the Istio object
- `version` (`string`) - API version of the Istio object (e.g., 'v1', 'v1beta1')

- **kiali_namespaces** - Get all namespaces in the mesh that the user has access to

Expand Down
1 change: 0 additions & 1 deletion pkg/kiali/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ const (
WorkloadDetailsEndpoint = "/api/namespaces/%s/workloads/%s"
WorkloadMetricsEndpoint = "/api/namespaces/%s/workloads/%s/metrics"
ValidationsEndpoint = "/api/istio/validations"
ValidationsListEndpoint = "/api/istio/validations"
)
193 changes: 69 additions & 124 deletions pkg/kiali/istio.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,151 +2,96 @@ package kiali

import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"sync"
)

// IstioConfig calls the Kiali Istio config API to get all Istio objects in the mesh.
// Returns the full YAML resources and additional details about each object.
func (k *Kiali) IstioConfig(ctx context.Context) (string, error) {
endpoint := IstioConfigEndpoint + "?validate=true"

return k.executeRequest(ctx, http.MethodGet, endpoint, "", nil)
type IstioConfigListResponse struct {
Configs json.RawMessage `json:"configs"`
Validations json.RawMessage `json:"validations"`
}

// IstioObjectDetails returns detailed information about a specific Istio object.
// Parameters:
// - namespace: the namespace containing the Istio object
// - group: the API group (e.g., "networking.istio.io", "gateway.networking.k8s.io")
// - version: the API version (e.g., "v1", "v1beta1")
// - kind: the resource kind (e.g., "DestinationRule", "VirtualService", "HTTPRoute")
// - name: the name of the resource
func (k *Kiali) IstioObjectDetails(ctx context.Context, namespace, group, version, kind, name string) (string, error) {
if namespace == "" {
return "", fmt.Errorf("namespace is required")
}
if group == "" {
return "", fmt.Errorf("group is required")
}
if version == "" {
return "", fmt.Errorf("version is required")
}
if kind == "" {
return "", fmt.Errorf("kind is required")
}
if name == "" {
return "", fmt.Errorf("name is required")
}
endpoint := fmt.Sprintf(IstioObjectEndpoint+"?validate=true&help=true",
// Helper builders to avoid repeated url.PathEscape boilerplate
func buildIstioObjectEndpoint(namespace, group, version, kind, name string) string {
return fmt.Sprintf(IstioObjectEndpoint,
url.PathEscape(namespace),
url.PathEscape(group),
url.PathEscape(version),
url.PathEscape(kind),
url.PathEscape(name))

return k.executeRequest(ctx, http.MethodGet, endpoint, "", nil)
url.PathEscape(name),
)
}

// IstioObjectPatch patches an existing Istio object using PATCH method.
// Parameters:
// - namespace: the namespace containing the Istio object
// - group: the API group (e.g., "networking.istio.io", "gateway.networking.k8s.io")
// - version: the API version (e.g., "v1", "v1beta1")
// - kind: the resource kind (e.g., "DestinationRule", "VirtualService", "HTTPRoute")
// - name: the name of the resource
// - jsonPatch: the JSON patch data to apply
func (k *Kiali) IstioObjectPatch(ctx context.Context, namespace, group, version, kind, name, jsonPatch string) (string, error) {
if namespace == "" {
return "", fmt.Errorf("namespace is required")
}
if group == "" {
return "", fmt.Errorf("group is required")
}
if version == "" {
return "", fmt.Errorf("version is required")
}
if kind == "" {
return "", fmt.Errorf("kind is required")
}
if name == "" {
return "", fmt.Errorf("name is required")
}
if jsonPatch == "" {
return "", fmt.Errorf("json patch data is required")
}
endpoint := fmt.Sprintf(IstioObjectEndpoint,
func buildIstioObjectCreateEndpoint(namespace, group, version, kind string) string {
return fmt.Sprintf(IstioObjectCreateEndpoint,
url.PathEscape(namespace),
url.PathEscape(group),
url.PathEscape(version),
url.PathEscape(kind),
url.PathEscape(name))

return k.executeRequest(ctx, http.MethodPatch, endpoint, "application/json", strings.NewReader(jsonPatch))
)
}

// IstioObjectCreate creates a new Istio object using POST method.
// Parameters:
// - namespace: the namespace where the Istio object will be created
// - group: the API group (e.g., "networking.istio.io", "gateway.networking.k8s.io")
// - version: the API version (e.g., "v1", "v1beta1")
// - kind: the resource kind (e.g., "DestinationRule", "VirtualService", "HTTPRoute")
// - jsonData: the JSON data for the new object
func (k *Kiali) IstioObjectCreate(ctx context.Context, namespace, group, version, kind, jsonData string) (string, error) {
if namespace == "" {
return "", fmt.Errorf("namespace is required")
}
if group == "" {
return "", fmt.Errorf("group is required")
}
if version == "" {
return "", fmt.Errorf("version is required")
}
if kind == "" {
return "", fmt.Errorf("kind is required")
}
if jsonData == "" {
return "", fmt.Errorf("json data is required")
}
endpoint := fmt.Sprintf(IstioObjectCreateEndpoint,
url.PathEscape(namespace),
url.PathEscape(group),
url.PathEscape(version),
url.PathEscape(kind))
// IstioConfig calls the Kiali Istio config API to get all Istio objects in the mesh.
// Returns the full YAML resources and additional details about each object.
func (k *Kiali) IstioConfig(ctx context.Context, action string, namespace string, group string, version string, kind string, name string, jsonData string) (string, error) {
switch action {
case "get":
endpoint := buildIstioObjectEndpoint(namespace, group, version, kind, name) + "?validate=true&help=true"
return k.executeRequest(ctx, http.MethodGet, endpoint, "", nil)
case "create":
endpoint := buildIstioObjectCreateEndpoint(namespace, group, version, kind)
return k.executeRequest(ctx, http.MethodPost, endpoint, "application/json", strings.NewReader(jsonData))
case "patch":
endpoint := buildIstioObjectEndpoint(namespace, group, version, kind, name)
return k.executeRequest(ctx, http.MethodPatch, endpoint, "application/json", strings.NewReader(jsonData))
case "delete":
endpoint := buildIstioObjectEndpoint(namespace, group, version, kind, name)
return k.executeRequest(ctx, http.MethodDelete, endpoint, "", nil)
default:
var wg sync.WaitGroup
wg.Add(2)
var configsContent string
var configsErr error
var validationsContent string
var validationsErr error

return k.executeRequest(ctx, http.MethodPost, endpoint, "application/json", strings.NewReader(jsonData))
}
// List configs (existing list behavior)
go func() {
defer wg.Done()
endpoint := IstioConfigEndpoint + "?validate=true"
configsContent, configsErr = k.executeRequest(ctx, http.MethodGet, endpoint, "", nil)
}()

// IstioObjectDelete deletes an existing Istio object using DELETE method.
// Parameters:
// - namespace: the namespace containing the Istio object
// - group: the API group (e.g., "networking.istio.io", "gateway.networking.k8s.io")
// - version: the API version (e.g., "v1", "v1beta1")
// - kind: the resource kind (e.g., "DestinationRule", "VirtualService", "HTTPRoute", "Gateway")
// - name: the name of the resource
func (k *Kiali) IstioObjectDelete(ctx context.Context, namespace, group, version, kind, name string) (string, error) {
if namespace == "" {
return "", fmt.Errorf("namespace is required")
}
if group == "" {
return "", fmt.Errorf("group is required")
}
if version == "" {
return "", fmt.Errorf("version is required")
}
if kind == "" {
return "", fmt.Errorf("kind is required")
}
if name == "" {
return "", fmt.Errorf("name is required")
}
endpoint := fmt.Sprintf(IstioObjectEndpoint,
url.PathEscape(namespace),
url.PathEscape(group),
url.PathEscape(version),
url.PathEscape(kind),
url.PathEscape(name))
// List validations, optionally scoped to provided namespace
go func() {
defer wg.Done()
var namespaces []string
if ns := strings.TrimSpace(namespace); ns != "" {
namespaces = []string{ns}
}
validationsContent, validationsErr = k.ValidationsList(ctx, namespaces)
}()

return k.executeRequest(ctx, http.MethodDelete, endpoint, "", nil)
wg.Wait()
if configsErr != nil {
return "", configsErr
}
if validationsErr != nil {
return "", validationsErr
}

resp := IstioConfigListResponse{
Configs: json.RawMessage([]byte(configsContent)),
Validations: json.RawMessage([]byte(validationsContent)),
}
out, err := json.Marshal(resp)
if err != nil {
return "", fmt.Errorf("failed to marshal istio list response: %v", err)
}
return string(out), nil
}
}
Loading