Skip to content

imuxin/ksql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ksql, a SQL-like language tool for kubernetes

Codacy Badge Codacy Badge

Install

CGO_ENABLED=0 go install github.com/imuxin/ksql

Goal #1: bring SQL lanugage for kubernetes command line tool

Rule #1: JSONPath Support in column name and where filter

More jsonpath support details, please check kubernetes kubectl jsonpath support.

Rule #2: NAMESPACE LABEL NAME keyword support in sql statement

  • ps1: NS is abbreviation for NAMESPACE
  • ps2: NAME and LABEL are allowed to have multiple inputs
  • ps3: NS or NAMESPACE is required once NAME is used.

Examples:

  • SELECT
ksql> SELECT * FROM service NAMESPACE default NAME kubernetes
+------------+-----------+
| NAME       | NAMESPACE |
+------------+-----------+
| kubernetes | default   |
+------------+-----------+
ksql> SELECT "{ .metadata.name }" AS NAME, "{ .spec.clusterIP }" AS "CLUSTER-IP", "{ .spec.ports }" FROM svc NAMESPACE default NAME kubernetes
+------------+------------+------------------------------------------------------------------+
| NAME       | CLUSTER-IP | { .SPEC.PORTS }                                                  |
+------------+------------+------------------------------------------------------------------+
| kubernetes | 10.8.0.1   | [{"name":"https","port":443,"protocol":"TCP","targetPort":6443}] |
+------------+------------+------------------------------------------------------------------+
  • DESC
ksql> DESC envoyfilters.networking.istio.io
+-------------------------------------------------------------------------------------------------+----------+
| SCHEMA                                                                                          | VERSION  |
+-------------------------------------------------------------------------------------------------+----------+
| type EnvoyFilter struct {                                                                       | v1alpha3 |
|     // Customizing Envoy configuration generated by Istio. See more details at:                 |          |
|     // https://istio.io/docs/reference/config/networking/envoy-filter.html                      |          |
|     spec struct {                                                                               |          |
|         // One or more patches with match conditions.                                           |          |
|         configPatches []struct {                                                                |          |
|             applyTo string                                                                      |          |
|             // Match on listener/route configuration/cluster.                                   |          |
|             match struct {                                                                      |          |
|                 // Match on envoy cluster attributes.                                           |          |
|                 cluster struct {                                                                |          |
|                     // The exact name of the cluster to match.                                  |          |
|                     name string                                                                 |          |
|                     // The service port for which this cluster was generated.                   |          |
|                     portNumber int                                                              |          |
|                     // The fully qualified service name for this cluster.                       |          |
|                     service string                                                              |          |
|                     // The subset associated with the service.                                  |          |
|                     subset string                                                               |          |
|                 }                                                                               |          |
|                                                                                                 |          |
|                 ...                                                                             |          |
|                                                                                                 |          |
|     status map[string]interface{}                                                               |          |
| }                                                                                               |          |
+-------------------------------------------------------------------------------------------------+----------+

more usages, see EBNF description:

const EBNF = `KSQL = UseStat* SelectStat* .
UseStat = "USE" <ident> .
SelectStat = "SELECT" SelectExpr "FROM" FromExpr ("WHERE" WhereExpr)? (("NAMESPACE" | "NS") (<ident> | <string>))? KubernetesFilter* .
SelectExpr = "*" | (Column ("," Column)*) .
Column = (<ident> | <string>) ("AS" (<ident> | <string> | "NAMESPACE" | "NS" | "NAME" | "SELECT" | "LABEL"))? .
FromExpr = (<ident> | "NAMESPACE" | "NS" | "NAME" | "SELECT" | "LABEL") ("@" <ident>)? .
WhereExpr = Compare Condition* .
Compare = "NOT"? (<ident> | <string>) Operation .
Operation = (("NOT"? "EXISTS") | (("<>" | "<=" | ">=" | "=" | "==" | "<" | ">" | "!=" | ("NOT"? "IN")) Value)) .
Value = (<number> | <string> | <ident> | ("TRUE" | "FALSE") | "NULL" | Array) .
Array = "(" Value ("," Value)* ")" .
Condition = ("AND" | "OR" | "NOT") Compare .
KubernetesFilter = ("LABEL" Compare) | ("NAME" (<ident> | <string>)) .`

Goal #2: make code easier to maintain

client-go ksql
func list() ([]T, error) {
    kubeConfig := getKubeConfig()

    client, err := dynamic.
        NewForConfig(kubeConfig)
    if err != nil {
        return nil, err
    }

    gvr :=
        schema.GroupVersionResource{
            Group:    "k8s.io",
            Version:  "v1alpha1",
            Resource: "tttt",
        }

    s := labels.NewSelector()
    req, err := labels.NewRequirement(
        "key",
        selection.Equals,
        []string{"val"})
    if err != nil {
        return nil, err
    }
    s = s.Add(*req)

    us, err := client.
        Resource(gvr).
        List(context.TODO(),
            metav1.ListOptions{
            LabelSelector: s.String(),
        })
    if err != nil {
        return nil, err
    }

    var results []T
    for _, item := range us.Items {
        obj := &T{}
        if err := FromUnstructured(
            item.Object, obj); err != nil {
            return nil, err
        }
        results = append(results, *obj)
    }
    return results, nil
}
import "github.com/imuxin/ksql/pkg/executor"

func list() ([]T, error) {
    kubeConfig := getKubeConfig()
    sql := `SELECT * FROM
            tttt.v1alpha1.k8s.io
            LABEL key = val`
    return executor.Execute[T](sql, kubeConfig)
}

Roadmap

  • Support SELECT stat
  • Support FROM
  • Support AS LABEL NAMESPACE NAME
  • Support WHERE expr
  • Support DESC expr
  • Support USE stat
  • Support DELETE stat
  • Support UPDATE stat
  • Support custom TABLE extensions
  • ...