diff --git a/client/console_client.go b/client/console_client.go
index 9093dc3..4f5a8f6 100644
--- a/client/console_client.go
+++ b/client/console_client.go
@@ -304,9 +304,12 @@ func (client *Client) Get(kind *schema.Kind, parentPathValue []string, parentQue
return result, err
}
-func (client *Client) Execute(execute schema.Execute, pathValue []string, queryParams map[string]string, body interface{}) ([]byte, error) {
+func (client *Client) Run(run schema.Run, pathValue []string, queryParams map[string]string, body interface{}) ([]byte, error) {
+ if run.BackendType != schema.CONSOLE {
+ return nil, fmt.Errorf("Only console backend type is supported by console client")
+ }
client.setAuthMethodFromEnvIfNeeded()
- path := execute.BuildPath(pathValue)
+ path := run.BuildPath(pathValue)
url := client.baseUrl + path
requestBuilder := client.client.R()
for k, v := range queryParams {
@@ -315,7 +318,7 @@ func (client *Client) Execute(execute schema.Execute, pathValue []string, queryP
if body != nil {
requestBuilder = requestBuilder.SetBody(body)
}
- resp, err := requestBuilder.Execute(execute.GetMethod(), url)
+ resp, err := requestBuilder.Execute(run.Method, url)
if err != nil {
return nil, err
} else if resp.IsError() {
diff --git a/client/gateway_client.go b/client/gateway_client.go
index b810f97..863c971 100644
--- a/client/gateway_client.go
+++ b/client/gateway_client.go
@@ -17,7 +17,7 @@ type GatewayClient struct {
cdkGatewayPassword string
baseUrl string
client *resty.Client
- kinds schema.KindCatalog
+ schemaCatalog *schema.Catalog
}
type GatewayApiParameter struct {
@@ -43,19 +43,19 @@ func MakeGateway(apiParameter GatewayApiParameter) (*GatewayClient, error) {
cdkGatewayPassword: apiParameter.CdkGatewayPassword,
baseUrl: apiParameter.BaseUrl,
client: restyClient,
- kinds: nil,
+ schemaCatalog: nil,
}
result.client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
result.client.SetDisableWarn(true)
result.client.SetBasicAuth(apiParameter.CdkGatewayUser, apiParameter.CdkGatewayPassword)
- err := result.initKindFromApi()
+ err := result.initCatalogFromApi()
if err != nil {
if apiParameter.Debug {
fmt.Fprintf(os.Stderr, "Cannot access the Gateway Conduktor API: %s\nUsing offline defaults.\n", err)
}
- result.kinds = schema.GatewayDefaultCatalog().Kind
+ result.schemaCatalog = schema.GatewayDefaultCatalog()
}
return result, nil
@@ -283,6 +283,28 @@ func (client *GatewayClient) ActivateDebug() {
client.client.SetDebug(true)
}
+func (client *GatewayClient) Run(run schema.Run, pathValue []string, queryParams map[string]string, body interface{}) ([]byte, error) {
+ if run.BackendType != schema.GATEWAY {
+ return nil, fmt.Errorf("Only console backend type is supported by console client")
+ }
+ path := run.BuildPath(pathValue)
+ url := client.baseUrl + path
+ requestBuilder := client.client.R()
+ for k, v := range queryParams {
+ requestBuilder.SetQueryParam(k, v)
+ }
+ if body != nil {
+ requestBuilder = requestBuilder.SetBody(body)
+ }
+ resp, err := requestBuilder.Execute(run.Method, url)
+ if err != nil {
+ return nil, err
+ } else if resp.IsError() {
+ return nil, fmt.Errorf(extractApiError(resp))
+ }
+ return resp.Body(), nil
+}
+
func (client *GatewayClient) Apply(resource *resource.Resource, dryMode bool) (string, error) {
kinds := client.GetKinds()
kind, ok := kinds[resource.Kind]
@@ -328,7 +350,7 @@ func (client *GatewayClient) GetOpenApi() ([]byte, error) {
return resp.Body(), nil
}
-func (client *GatewayClient) initKindFromApi() error {
+func (client *GatewayClient) initCatalogFromApi() error {
data, err := client.GetOpenApi()
if err != nil {
return fmt.Errorf("Cannot get openapi: %s", err)
@@ -338,7 +360,7 @@ func (client *GatewayClient) initKindFromApi() error {
return fmt.Errorf("Cannot parse openapi: %s", err)
}
strict := false
- client.kinds, err = schema.GetGatewayKinds(strict)
+ client.schemaCatalog, err = schema.GetGatewayCatalog(strict)
if err != nil {
fmt.Errorf("Cannot extract schemaCatalog from openapi: %s", err)
}
@@ -346,12 +368,9 @@ func (client *GatewayClient) initKindFromApi() error {
}
func (client *GatewayClient) GetKinds() schema.KindCatalog {
- return client.kinds
+ return client.schemaCatalog.Kind
}
func (client *GatewayClient) GetCatalog() *schema.Catalog {
- return &schema.Catalog{
- Kind: client.GetKinds(),
- Execute: map[string]schema.Execute{},
- }
+ return client.schemaCatalog
}
diff --git a/cmd/consoleMkKind.go b/cmd/consoleMakeCatalog.go
similarity index 57%
rename from cmd/consoleMkKind.go
rename to cmd/consoleMakeCatalog.go
index d0603d6..21ecd9e 100644
--- a/cmd/consoleMkKind.go
+++ b/cmd/consoleMakeCatalog.go
@@ -6,19 +6,19 @@ import (
"github.com/spf13/cobra"
)
-func initConsoleMkKind() {
+func intConsoleMakeCatalog() {
var prettyPrint *bool
var nonStrict *bool
var makeKind = &cobra.Command{
- Use: "makeKind [file]",
- Short: "Make kind json from openapi file if file not given it will read from api",
+ Use: "makeConsoleCatalog [file]",
+ Short: "Make catalog json from openapi file if file not given it will read from api",
Long: ``,
- Aliases: []string{"mkKind", "makeConsoleKind"},
+ Aliases: []string{"mkKind", "makeConsoleKind", "makeKind"}, // for backward compatibility
Args: cobra.RangeArgs(0, 1),
Hidden: !utils.CdkDevMode(),
Run: func(cmd *cobra.Command, args []string) {
- runMkKind(cmd, args, *prettyPrint, *nonStrict, func() ([]byte, error) { return consoleApiClient().GetOpenApi() }, func(schema *schema.OpenApiParser, strict bool) (*schema.Catalog, error) {
+ runMakeCatalog(cmd, args, *prettyPrint, *nonStrict, func() ([]byte, error) { return consoleApiClient().GetOpenApi() }, func(schema *schema.OpenApiParser, strict bool) (*schema.Catalog, error) {
return schema.GetConsoleCatalog(strict)
})
},
diff --git a/cmd/execute.go b/cmd/execute.go
deleted file mode 100644
index 7c5e42a..0000000
--- a/cmd/execute.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package cmd
-
-import (
- "encoding/json"
- "fmt"
- "github.com/conduktor/ctl/schema"
- "github.com/spf13/cobra"
- "os"
-)
-
-var executeCmd = &cobra.Command{
- Use: "execute",
- Short: "execute an action",
- Args: cobra.NoArgs,
- Run: func(cmd *cobra.Command, args []string) {
- // Root command does nothing
- cmd.Help()
- os.Exit(1)
- },
-}
-
-func printExecuteResult(result []byte) {
- var stringJson string
- err := json.Unmarshal(result, &stringJson)
- if err == nil {
- fmt.Println(stringJson)
- return
- }
- var jsonResult interface{}
- err = json.Unmarshal(result, &jsonResult)
- if err == nil {
- jsonOutput, err := json.MarshalIndent(jsonResult, "", " ")
- if err == nil {
- fmt.Println(string(jsonOutput))
- return
- }
- }
- if len(result) > 1 {
- fmt.Println(string(result))
- } else {
- fmt.Println("Ok")
- }
-}
-
-func initExecute(executes schema.ExecuteCatalog) {
- rootCmd.AddCommand(executeCmd)
-
- // Add all kinds to the 'get' command
- for name, execute := range executes {
- args := cobra.MaximumNArgs(0)
- pathFlags := execute.GetPathParameter()
- pathFlagValues := make([]*string, len(pathFlags))
- queryFlags := execute.GetQueryParameter()
- bodyFlags := execute.GetBodyFields()
- queryFlagValues := make(map[string]interface{}, len(queryFlags))
- bodyFlagValues := make(map[string]interface{}, len(bodyFlags))
- subExecuteCmd := &cobra.Command{
- Use: name,
- Short: execute.GetDoc(),
- Args: args,
- Aliases: buildAlias(name),
- Run: func(cmd *cobra.Command, args []string) {
- pathValues := make([]string, len(pathFlagValues))
- queryParams := buildQueryParams(queryFlagValues)
- body := buildQueryParams(bodyFlagValues)
- for i, v := range pathFlagValues {
- pathValues[i] = *v
- }
-
- var err error
-
- if len(bodyFlags) == 0 {
- body = nil
- }
- result, err := consoleApiClient().Execute(execute, pathValues, queryParams, body)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error fetching resources: %s\n", err)
- return
- }
- printExecuteResult(result)
- },
- }
- for i, flag := range pathFlags {
- pathFlagValues[i] = subExecuteCmd.Flags().String(flag, "", "Parent "+flag)
- subExecuteCmd.MarkFlagRequired(flag)
- }
- for key, flag := range queryFlags {
- var isFlagSet bool
- if flag.Type == "string" {
- isFlagSet = true
- queryFlagValues[key] = subExecuteCmd.Flags().String(flag.FlagName, "", "")
- } else if flag.Type == "boolean" {
- isFlagSet = true
- queryFlagValues[key] = subExecuteCmd.Flags().Bool(flag.FlagName, false, "")
- }
- if isFlagSet && flag.Required {
- subExecuteCmd.MarkFlagRequired(flag.FlagName)
- }
- }
- for key, flag := range bodyFlags {
- var isFlagSet bool
- if flag.Type == "string" {
- isFlagSet = true
- bodyFlagValues[key] = subExecuteCmd.Flags().String(flag.FlagName, "", "")
- } else if flag.Type == "boolean" {
- isFlagSet = true
- bodyFlagValues[key] = subExecuteCmd.Flags().Bool(flag.FlagName, false, "")
- }
- if isFlagSet && flag.Required {
- subExecuteCmd.MarkFlagRequired(flag.FlagName)
- }
- }
-
- executeCmd.AddCommand(subExecuteCmd)
- }
-}
diff --git a/cmd/gatewayMkKind.go b/cmd/gatewayMkKind.go
index eb84059..0c41b30 100644
--- a/cmd/gatewayMkKind.go
+++ b/cmd/gatewayMkKind.go
@@ -6,25 +6,25 @@ import (
"github.com/spf13/cobra"
)
-func initGatewayMkKind() {
+func initGatewayMakeCatalog() {
var prettyPrint *bool
var nonStrict *bool
- var makeKind = &cobra.Command{
- Use: "gatewayMakeKind [file]",
- Short: "Make kind json from openapi file if file not given it will read from api",
+ var makeCatalog = &cobra.Command{
+ Use: "gatewayMakeCatalog [file]",
+ Short: "Make catalog json from openapi file if file not given it will read from api",
Long: ``,
- Aliases: []string{"gatewayMkKind", "gwMkKind"},
+ Aliases: []string{"gatewayMkKind", "gwMkKind", "gatewayMakeKind"}, // for backward compatibility
Args: cobra.RangeArgs(0, 1),
Hidden: !utils.CdkDevMode(),
Run: func(cmd *cobra.Command, args []string) {
- runMkKind(cmd, args, *prettyPrint, *nonStrict, func() ([]byte, error) { return gatewayApiClient().GetOpenApi() }, func(schema *schema.OpenApiParser, strict bool) (*schema.Catalog, error) {
+ runMakeCatalog(cmd, args, *prettyPrint, *nonStrict, func() ([]byte, error) { return gatewayApiClient().GetOpenApi() }, func(schema *schema.OpenApiParser, strict bool) (*schema.Catalog, error) {
return schema.GetGatewayCatalog(strict)
})
},
}
- rootCmd.AddCommand(makeKind)
+ rootCmd.AddCommand(makeCatalog)
- prettyPrint = makeKind.Flags().BoolP("pretty", "p", false, "Pretty print the output")
- nonStrict = makeKind.Flags().BoolP("non-strict", "n", false, "Don't be strict on the parsing of the schema")
+ prettyPrint = makeCatalog.Flags().BoolP("pretty", "p", false, "Pretty print the output")
+ nonStrict = makeCatalog.Flags().BoolP("non-strict", "n", false, "Don't be strict on the parsing of the schema")
}
diff --git a/cmd/genericMkKind.go b/cmd/genericMkKind.go
index 40867bf..5137633 100644
--- a/cmd/genericMkKind.go
+++ b/cmd/genericMkKind.go
@@ -9,7 +9,7 @@ import (
"github.com/spf13/cobra"
)
-func runMkKind(cmd *cobra.Command, args []string, prettyPrint bool, nonStrict bool, getOpenApi func() ([]byte, error), getKinds func(*schema.OpenApiParser, bool) (*schema.Catalog, error)) {
+func runMakeCatalog(cmd *cobra.Command, args []string, prettyPrint bool, nonStrict bool, getOpenApi func() ([]byte, error), getCatalog func(*schema.OpenApiParser, bool) (*schema.Catalog, error)) {
var kinds *schema.Catalog
if len(args) == 1 {
data, err := os.ReadFile(args[0])
@@ -20,7 +20,7 @@ func runMkKind(cmd *cobra.Command, args []string, prettyPrint bool, nonStrict bo
if err != nil {
panic(err)
}
- kinds, err = getKinds(schema, !nonStrict)
+ kinds, err = getCatalog(schema, !nonStrict)
if err != nil {
panic(err)
}
@@ -33,7 +33,7 @@ func runMkKind(cmd *cobra.Command, args []string, prettyPrint bool, nonStrict bo
if err != nil {
panic(err)
}
- kinds, err = getKinds(schema, !nonStrict)
+ kinds, err = getCatalog(schema, !nonStrict)
if err != nil {
panic(err)
}
diff --git a/cmd/get.go b/cmd/get.go
index 15acc46..93c33d1 100644
--- a/cmd/get.go
+++ b/cmd/get.go
@@ -49,6 +49,7 @@ func buildQueryParams(params map[string]interface{}) map[string]string {
if value != nil {
str, strOk := value.(*string)
boolValue, boolOk := value.(*bool)
+ intValue, intOk := value.(*int)
if strOk {
if *str != "" {
@@ -56,6 +57,8 @@ func buildQueryParams(params map[string]interface{}) map[string]string {
}
} else if boolOk {
queryParams[key] = strconv.FormatBool(*boolValue)
+ } else if intOk {
+ queryParams[key] = strconv.Itoa(*intValue)
} else {
panic("Unknown query flag type")
}
@@ -229,6 +232,7 @@ func initGet(kinds schema.KindCatalog) {
for i, flag := range parentQueryFlags {
parentQueryFlagValue[i] = kindCmd.Flags().String(flag, "", "Parent "+flag)
}
+ //TODO: factorize with run.go
for key, flag := range listFlags {
var isFlagSet bool
if flag.Type == "string" {
@@ -237,6 +241,9 @@ func initGet(kinds schema.KindCatalog) {
} else if flag.Type == "boolean" {
isFlagSet = true
listFlagValue[key] = kindCmd.Flags().Bool(flag.FlagName, false, "")
+ } else if flag.Type == "integer" {
+ isFlagSet = true
+ listFlagValue[key] = kindCmd.Flags().Int(flag.FlagName, 0, "")
}
if isFlagSet && flag.Required {
kindCmd.MarkFlagRequired(flag.FlagName)
diff --git a/cmd/printKind.go b/cmd/printCatalog.go
similarity index 72%
rename from cmd/printKind.go
rename to cmd/printCatalog.go
index 6c74426..72227f1 100644
--- a/cmd/printKind.go
+++ b/cmd/printCatalog.go
@@ -9,16 +9,17 @@ import (
"github.com/spf13/cobra"
)
-func initPrintKind(kinds schema.KindCatalog) {
+func initPrintCatalog(kinds schema.Catalog) {
var prettyPrint *bool
var printKind = &cobra.Command{
- Use: "printKind",
- Short: "Print kind catalog used",
- Long: ``,
- Args: cobra.NoArgs,
- Hidden: !utils.CdkDevMode(),
+ Use: "printCatalog",
+ Aliases: []string{"printKind"}, // for backward compatibility
+ Short: "Print catalog",
+ Long: ``,
+ Args: cobra.NoArgs,
+ Hidden: !utils.CdkDevMode(),
Run: func(cmd *cobra.Command, args []string) {
var payload []byte
var err error
diff --git a/cmd/root.go b/cmd/root.go
index 2b97e16..9f0195d 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -81,9 +81,9 @@ func init() {
initTemplate(catalog.Kind)
initDelete(catalog.Kind, !*permissive)
initApply(catalog.Kind, !*permissive)
- initConsoleMkKind()
- initGatewayMkKind()
- initPrintKind(catalog.Kind)
+ intConsoleMakeCatalog()
+ initGatewayMakeCatalog()
+ initPrintCatalog(catalog)
initSql(catalog.Kind)
- initExecute(catalog.Execute)
+ initRun(catalog.Run)
}
diff --git a/cmd/run.go b/cmd/run.go
new file mode 100644
index 0000000..29c2349
--- /dev/null
+++ b/cmd/run.go
@@ -0,0 +1,162 @@
+package cmd
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/conduktor/ctl/schema"
+ "github.com/spf13/cobra"
+ "os"
+)
+
+const unprobableInt = -23871
+
+var runCmd = &cobra.Command{
+ Use: "run",
+ Short: "run an action",
+ Args: cobra.NoArgs,
+ Run: func(cmd *cobra.Command, args []string) {
+ // Root command does nothing
+ cmd.Help()
+ os.Exit(1)
+ },
+}
+
+func printExecuteResult(result []byte) {
+ var stringJson string
+ err := json.Unmarshal(result, &stringJson)
+ if err == nil {
+ fmt.Println(stringJson)
+ return
+ }
+ var jsonResult interface{}
+ err = json.Unmarshal(result, &jsonResult)
+ if err == nil {
+ jsonOutput, err := json.MarshalIndent(jsonResult, "", " ")
+ if err == nil {
+ fmt.Println(string(jsonOutput))
+ return
+ }
+ }
+ if len(result) > 1 {
+ fmt.Println(string(result))
+ } else {
+ fmt.Println("Ok")
+ }
+}
+
+func initRun(runs schema.RunCatalog) {
+ rootCmd.AddCommand(runCmd)
+
+ // Add all kinds to the 'get' command
+ for name, run := range runs {
+ args := cobra.MaximumNArgs(0)
+ pathFlags := run.PathParameter
+ pathFlagValues := make([]*string, len(pathFlags))
+ queryFlags := run.QueryParameter
+ bodyFlags := run.BodyFields
+ queryFlagValues := make(map[string]interface{}, len(queryFlags))
+ bodyFlagValues := make(map[string]interface{}, len(bodyFlags))
+ subRunCmd := &cobra.Command{
+ Use: name,
+ Short: run.Doc,
+ Args: args,
+ Aliases: buildAlias(name),
+ Run: func(cmd *cobra.Command, args []string) {
+ pathValues := make([]string, len(pathFlagValues))
+ queryParams := buildQueryParams(queryFlagValues)
+ body := buildBodyParams(bodyFlagValues)
+ for i, v := range pathFlagValues {
+ pathValues[i] = *v
+ }
+
+ var err error
+
+ if len(bodyFlags) == 0 {
+ body = nil
+ }
+ var result []byte
+ if run.BackendType == schema.CONSOLE {
+ result, err = consoleApiClient().Run(run, pathValues, queryParams, body)
+ } else if run.BackendType == schema.GATEWAY {
+ result, err = gatewayApiClient().Run(run, pathValues, queryParams, body)
+ } else {
+ panic("Unknown backend type")
+ }
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error fetching resources: %s\n", err)
+ return
+ }
+ printExecuteResult(result)
+ },
+ }
+ for i, flag := range pathFlags {
+ pathFlagValues[i] = subRunCmd.Flags().String(flag, "", "Parent "+flag)
+ err := subRunCmd.MarkFlagRequired(flag)
+ if err != nil {
+ panic(err)
+ }
+ }
+ for key, flag := range queryFlags {
+ var isFlagSet bool
+ if flag.Type == "string" {
+ isFlagSet = true
+ queryFlagValues[key] = subRunCmd.Flags().String(flag.FlagName, "", "")
+ } else if flag.Type == "boolean" {
+ isFlagSet = true
+ queryFlagValues[key] = subRunCmd.Flags().Bool(flag.FlagName, false, "")
+ } else if flag.Type == "integer" {
+ isFlagSet = true
+ bodyFlagValues[key] = subRunCmd.Flags().Int(flag.FlagName, 0, "")
+ }
+ if isFlagSet && flag.Required {
+ err := subRunCmd.MarkFlagRequired(flag.FlagName)
+ if err != nil {
+ panic(err)
+ }
+ }
+ }
+ for key, flag := range bodyFlags {
+ var isFlagSet bool
+ if flag.Type == "string" {
+ isFlagSet = true
+ bodyFlagValues[key] = subRunCmd.Flags().String(flag.FlagName, "", "")
+ } else if flag.Type == "boolean" {
+ isFlagSet = true
+ bodyFlagValues[key] = subRunCmd.Flags().Bool(flag.FlagName, false, "")
+ } else if flag.Type == "integer" {
+ isFlagSet = true
+ bodyFlagValues[key] = subRunCmd.Flags().Int(flag.FlagName, unprobableInt, "")
+ }
+ if isFlagSet && flag.Required {
+ err := subRunCmd.MarkFlagRequired(flag.FlagName)
+ if err != nil {
+ panic(err)
+ }
+ }
+ }
+
+ runCmd.AddCommand(subRunCmd)
+ }
+}
+func buildBodyParams(params map[string]interface{}) map[string]interface{} {
+ body := make(map[string]interface{})
+ for key, value := range params {
+ if value != nil {
+ str, strOk := value.(*string)
+ intValue, intOk := value.(*int)
+
+ if strOk {
+ if *str != "" {
+ body[key] = str
+ }
+ } else if intOk {
+ if *intValue != unprobableInt {
+ body[key] = intValue
+ }
+ } else {
+ body[key] = value
+ }
+ }
+ }
+ return body
+}
diff --git a/docker/initializer.json b/docker/initializer.json
index 90a14b2..4d7aae8 100644
--- a/docker/initializer.json
+++ b/docker/initializer.json
@@ -27,7 +27,13 @@
},
"httpResponse": {
"statusCode": 200,
- "body": [{"metadata": {"name": "a"}}],
+ "body": [
+ {
+ "metadata": {
+ "name": "a"
+ }
+ }
+ ],
"headers": {
"Content-Type": [
"application/json"
@@ -45,7 +51,11 @@
},
"httpResponse": {
"statusCode": 200,
- "body": {"metadata": {"name": "a"}},
+ "body": {
+ "metadata": {
+ "name": "a"
+ }
+ },
"headers": {
"Content-Type": [
"application/json"
@@ -241,7 +251,11 @@
},
"httpResponse": {
"statusCode": 200,
- "body": {"metadata": {"name": "a"}},
+ "body": {
+ "metadata": {
+ "name": "a"
+ }
+ },
"headers": {
"Content-Type": [
"application/json"
@@ -254,7 +268,9 @@
"method": "POST",
"path": "/api/public/sql/v1/execute",
"queryStringParameters": {
- "maxLine": ["100"]
+ "maxLine": [
+ "100"
+ ]
},
"headers": {
"Authorization": "Bearer yo"
@@ -263,7 +279,28 @@
},
"httpResponse": {
"statusCode": 200,
- "body": {"header": [], "row": []},
+ "body": {
+ "header": [],
+ "row": []
+ },
+ "headers": {
+ "Content-Type": [
+ "application/json"
+ ]
+ }
+ }
+ },
+ {
+ "httpRequest": {
+ "method": "POST",
+ "path": "/api/public/partner-zone/v2/yo/generate-credentials",
+ "headers": {
+ "Authorization": "Bearer yo"
+ }
+ },
+ "httpResponse": {
+ "statusCode": 200,
+ "body": "\"yolo_le_token\"",
"headers": {
"Content-Type": [
"application/json"
@@ -271,5 +308,4 @@
}
}
}
-
]
\ No newline at end of file
diff --git a/docker/initializerGw.json b/docker/initializerGw.json
index f9a636a..8dfa34e 100644
--- a/docker/initializerGw.json
+++ b/docker/initializerGw.json
@@ -400,5 +400,28 @@
]
}
}
+ },
+ {
+ "httpRequest": {
+ "method": "POST",
+ "path": "/gateway/v2/token",
+ "headers": {
+ "Authorization": "Basic YWRtaW46Y29uZHVrdG9y"
+ },
+ "body": {
+ "lifeTimeSeconds": 3600,
+ "username": "yo",
+ "vCluster": "foyer"
+ }
+ },
+ "httpResponse": {
+ "statusCode": 200,
+ "body": "yolo_le_token",
+ "headers": {
+ "Content-Type": [
+ "application/json"
+ ]
+ }
+ }
}
]
\ No newline at end of file
diff --git a/schema/backend_type.go b/schema/backend_type.go
new file mode 100644
index 0000000..4c2f2f1
--- /dev/null
+++ b/schema/backend_type.go
@@ -0,0 +1,8 @@
+package schema
+
+type BackendType int
+
+const (
+ CONSOLE BackendType = iota
+ GATEWAY
+)
diff --git a/schema/catalog.go b/schema/catalog.go
index 490064b..c9cddc1 100644
--- a/schema/catalog.go
+++ b/schema/catalog.go
@@ -1,69 +1,76 @@
package schema
-import "encoding/json"
+import (
+ "encoding/json"
+)
type Catalog struct {
- Kind KindCatalog
- Execute ExecuteCatalog
+ Kind KindCatalog
+ Run RunCatalog
}
type KindCatalog = map[string]Kind
-type ExecuteCatalog = map[string]Execute
+type RunCatalog = map[string]Run
func ConsoleDefaultCatalog() *Catalog {
- return &Catalog{
- Kind: buildKindCatalogFromByteSchema[*ConsoleKindVersion](consoleDefaultByteSchema),
- Execute: map[string]Execute{},
- }
+ return buildCatalogFromByteSchema[*ConsoleKindVersion](consoleDefaultByteSchema, CONSOLE)
}
func GatewayDefaultCatalog() *Catalog {
- return &Catalog{
- Kind: buildKindCatalogFromByteSchema[*GatewayKindVersion](gatewayDefaultByteSchema),
- Execute: map[string]Execute{},
- }
+ return buildCatalogFromByteSchema[*GatewayKindVersion](gatewayDefaultByteSchema, GATEWAY)
}
func (catalog *Catalog) Merge(other *Catalog) Catalog {
result := Catalog{
- Kind: make(map[string]Kind),
- Execute: make(map[string]Execute),
+ Kind: make(map[string]Kind),
+ Run: make(map[string]Run),
}
-
for kindName, kind := range catalog.Kind {
result.Kind[kindName] = kind
}
for kindName, kind := range other.Kind {
result.Kind[kindName] = kind
}
- for executeName, execute := range catalog.Execute {
- result.Execute[executeName] = execute
+ for runName, run := range catalog.Run {
+ result.Run[runName] = run
}
- for executeName, execute := range other.Execute {
- result.Execute[executeName] = execute
+ for runName, run := range other.Run {
+ result.Run[runName] = run
}
return result
}
-func buildKindCatalogFromByteSchema[T KindVersion](byteSchema []byte) KindCatalog {
- var jsonResult map[string]kindGeneric[T]
+func buildCatalogFromByteSchema[T KindVersion](byteSchema []byte, backendType BackendType) *Catalog {
+ var jsonResult CatalogGeneric[T]
err := json.Unmarshal(byteSchema, &jsonResult)
if err != nil {
panic(err)
}
- var result = make(map[string]Kind)
- for kindName, kindGeneric := range jsonResult {
+ var result = Catalog{
+ Kind: KindCatalog{},
+ Run: RunCatalog{},
+ }
+ for kindName, kindGeneric := range jsonResult.Kind {
kind := Kind{
Versions: make(map[int]KindVersion),
}
for version, kindVersion := range kindGeneric.Versions {
kind.Versions[version] = kindVersion
}
- result[kindName] = kind
+ result.Kind[kindName] = kind
}
- return result
+ for runName, run := range jsonResult.Run {
+ run.BackendType = backendType
+ result.Run[runName] = run
+ }
+ return &result
}
type kindGeneric[T KindVersion] struct {
Versions map[int]T
}
+
+type CatalogGeneric[T KindVersion] struct {
+ Kind map[string]kindGeneric[T]
+ Run RunCatalog
+}
diff --git a/schema/default_schema/console.json b/schema/default_schema/console.json
index c0bec30..88bb870 100644
--- a/schema/default_schema/console.json
+++ b/schema/default_schema/console.json
@@ -1 +1 @@
-{"Alert":{"Versions":{"2":{"ListPath":"/public/monitoring/v2/cluster/{cluster}/alert","Name":"Alert","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v2\nkind: Alert\nmetadata:\n name: alert\n cluster: cluster\nspec:\n connectName: connect\n connectorName: connector\n threshold: 1\n operator: GreaterThan\n metric: FailedTaskCount\n type: KafkaConnectAlert\n","Order":15},"3":{"ListPath":"/public/monitoring/v3/alert","Name":"Alert","ParentPathParam":[],"ParentQueryParam":["appInstance","group","user"],"ListQueryParamter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"appInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"cluster":{"FlagName":"cluster","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"group":{"FlagName":"group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"},"user":{"FlagName":"user","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v3\nkind: Alert\nmetadata:\n name: alert\n appInstance: my-app\nspec:\n cluster: cluster\n connectName: connect\n connectorName: connector\n threshold: 1\n operator: GreaterThan\n metric: FailedTaskCount\n type: KafkaConnectAlert\n","Order":15}}},"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v1\nkind: Application\nmetadata:\n name: my-application\nspec:\n title: My Application\n owner: me\n","Order":6}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v1\nkind: ApplicationGroup\nmetadata:\n application: clickstream-app\n name: clickstream-support\nspec:\n displayName: Support Clickstream\n description: |-\n Members of the Support Group are allowed:\n Read access on all the resources\n Can restart owned connectors\n Can reset offsets\n permissions:\n - appInstance: clickstream-app-dev\n patternType: LITERAL\n name: '*'\n permissions:\n - topicConsume\n - topicViewConfig\n resourceType: TOPIC\n members:\n - user1@company.org\n - user2@company.org\n externalGroups:\n - support\n","Order":9}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: ApplicationInstance\nmetadata:\n name: my-app-instance-prod\n application: my-app\nspec:\n cluster: prod-cluster\n topicPolicyRef:\n - my-topic-policy\n resources:\n - type: TOPIC\n name: my-topic\n patternType: LITERAL\n - type: CONSUMER_GROUP\n name: my-consumer-group\n patternType: LITERAL\n serviceAccount: my-service-account\n defaultCatalogVisibility: PUBLIC\n","Order":7}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: ApplicationInstancePermission\nmetadata:\n application: test\n appInstance: test\n name: test\nspec:\n resource:\n type: TOPIC\n name: test\n patternType: LITERAL\n permission: READ\n grantedTo: test\n","Order":8}}},"Connector":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/connect/{connectCluster}/connector","Name":"Connector","ParentPathParam":["cluster","connectCluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: Connector\nmetadata:\n name: my-connector\n cluster: my-cluster\n connectCluster: my-connect\n autoRestart:\n enabled: true\n frequencySeconds: 600\n description: My connector\nspec:\n config: {}\n","Order":13}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: Group\nmetadata:\n name: group\nspec:\n displayName: test\n description: description\n externalGroups:\n - test\n members:\n - user@conduktor.io\n membersFromExternalGroups: []\n permissions:\n - resourceType: TOPIC\n cluster: '*'\n name: test\n patternType: LITERAL\n permissions:\n - topicConsume\n - resourceType: TOPIC\n cluster: '*'\n name: test2\n patternType: PREFIXED\n permissions:\n - topicConsume\n","Order":1}}},"IndexedTopic":{"Versions":{"1":{"ListPath":"/public/sql/v1/cluster/{cluster}/indexed_topic","Name":"IndexedTopic","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v1\nkind: IndexedTopic\nmetadata:\n cluster: my-cluster\n name: my-topic\nspec:\n retentionTimeInSecond: 3600\n","Order":14}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: KafkaCluster\nmetadata:\n name: my-kafka-cluster\n labels:\n env: prod\nspec:\n displayName: yo\n bootstrapServers: localhost:9092\n properties:\n sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"admin-secret\";\n color: '#FF0000'\n icon: icon\n schemaRegistry:\n url: https://my-schema-registry:8081\n security:\n username: admin\n password: admin-secret\n type: BasicAuth\n ignoreUntrustedCertificate: false\n type: ConfluentLike\n","Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: KafkaConnectCluster\nmetadata:\n name: connect-1\n cluster: my-cloud\n labels:\n user-labels: I am a user label\nspec:\n displayName: My kafka connect\n urls: http://localhost:8083\n headers:\n a: b\n c: d\n ignoreUntrustedCertificate: true\n security:\n username: user\n password: password\n type: BasicAuth\n","Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: KsqlDBCluster\nmetadata:\n name: connect-1\n cluster: my-cloud\nspec:\n displayName: My kafka connect\n url: http://localhost:8083\n headers:\n a: b\n c: d\n ignoreUntrustedCertificate: true\n security:\n username: user\n password: password\n type: BasicAuth\n","Order":4}}},"ServiceAccount":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/cluster/{cluster}/service-account","Name":"ServiceAccount","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v1\nkind: ServiceAccount\nmetadata:\n appInstance: my-app-instance-dev\n cluster: my-kafka-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: dev\n user-labels: I am a user label\n name: sa-clicko-dev\nspec:\n authorization:\n acls:\n - type: TOPIC\n name: click.\n patternType: Prefixed\n operations:\n - Write\n host: '*'\n permission: Allow\n","Order":10}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: Subject\nmetadata:\n name: my-subject\n cluster: my-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: staging\nspec:\n format: AVRO\n compatibility: BACKWARD_TRANSITIVE\n schema: '{\"type\": \"long\"}'\n","Order":12}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: Topic\nmetadata:\n name: my-topic\n cluster: my-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: staging\n user-labels: I am a user label\n catalogVisibility: PUBLIC\n descriptionIsEditable: true\n description: This is a topic description\n sqlStorage:\n retentionTimeInSecond: 42\nspec:\n partitions: 1\n replicationFactor: 1\n configs:\n cleanup.policy: delete\n retention.ms: '86400000'\n","Order":11}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: TopicPolicy\nmetadata:\n name: my-app-instance-prod\nspec:\n policies:\n my-policy:\n constraint: OneOf\n optional: true\n values:\n - value1\n - value2\n","Order":5}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParamter":{},"ApplyExample":"apiVersion: v2\nkind: User\nmetadata:\n name: user@conduktor.io\nspec:\n firstName: description\n lastName: test\n permissions: []\n","Order":0}}}}
\ No newline at end of file
+{"Kind":{"Alert":{"Versions":{"2":{"ListPath":"/public/monitoring/v2/cluster/{cluster}/alert","Name":"Alert","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v2\nkind: Alert\nmetadata:\n name: alert\n cluster: cluster\nspec:\n connectName: connect\n connectorName: connector\n threshold: 1\n operator: GreaterThan\n metric: FailedTaskCount\n type: KafkaConnectAlert\n","Order":15},"3":{"ListPath":"/public/monitoring/v3/alert","Name":"Alert","ParentPathParam":[],"ParentQueryParam":["appInstance","group","user"],"ListQueryParameter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"appInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"cluster":{"FlagName":"cluster","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"group":{"FlagName":"group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"},"user":{"FlagName":"user","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v3\nkind: Alert\nmetadata:\n name: alert\n appInstance: my-app\nspec:\n cluster: cluster\n connectName: connect\n connectorName: connector\n threshold: 1\n operator: GreaterThan\n metric: FailedTaskCount\n destination:\n channel: test\n type: Slack\n type: KafkaConnectAlert\n","Order":15}}},"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v1\nkind: Application\nmetadata:\n name: my-application\nspec:\n title: My Application\n owner: me\n","Order":6}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: ApplicationGroup\nmetadata:\n application: clickstream-app\n name: clickstream-support\nspec:\n displayName: Support Clickstream\n description: |-\n Members of the Support Group are allowed:\n Read access on all the resources\n Can restart owned connectors\n Can reset offsets\n permissions:\n - appInstance: clickstream-app-dev\n patternType: LITERAL\n name: '*'\n permissions:\n - topicConsume\n - topicViewConfig\n resourceType: TOPIC\n members:\n - user1@company.org\n - user2@company.org\n externalGroups:\n - support\n","Order":9}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: ApplicationInstance\nmetadata:\n name: my-app-instance-prod\n application: my-app\nspec:\n cluster: prod-cluster\n topicPolicyRef:\n - my-topic-policy\n resources:\n - type: TOPIC\n name: my-topic\n patternType: LITERAL\n - type: CONSUMER_GROUP\n name: my-consumer-group\n patternType: LITERAL\n serviceAccount: my-service-account\n defaultCatalogVisibility: PUBLIC\n","Order":7}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: ApplicationInstancePermission\nmetadata:\n application: test\n appInstance: test\n name: test\nspec:\n resource:\n type: TOPIC\n name: test\n patternType: LITERAL\n permission: READ\n grantedTo: test\n","Order":8}}},"Connector":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/connect/{connectCluster}/connector","Name":"Connector","ParentPathParam":["cluster","connectCluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: Connector\nmetadata:\n name: my-connector\n cluster: my-cluster\n connectCluster: my-connect\n autoRestart:\n enabled: true\n frequencySeconds: 600\n description: My connector\nspec:\n config: {}\n","Order":13}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: Group\nmetadata:\n name: group\nspec:\n displayName: test\n description: description\n externalGroups:\n - test\n members:\n - user@conduktor.io\n membersFromExternalGroups: []\n permissions:\n - resourceType: TOPIC\n cluster: '*'\n name: test\n patternType: LITERAL\n permissions:\n - topicConsume\n - resourceType: TOPIC\n cluster: '*'\n name: test2\n patternType: PREFIXED\n permissions:\n - topicConsume\n","Order":1}}},"IndexedTopic":{"Versions":{"1":{"ListPath":"/public/sql/v1/cluster/{cluster}/indexed_topic","Name":"IndexedTopic","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v1\nkind: IndexedTopic\nmetadata:\n cluster: my-cluster\n name: my-topic\nspec:\n retentionTimeInSecond: 3600\n","Order":14}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: KafkaCluster\nmetadata:\n name: my-kafka-cluster\n labels:\n env: prod\nspec:\n displayName: yo\n bootstrapServers: localhost:9092\n properties:\n sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"admin-secret\";\n color: '#FF0000'\n icon: icon\n schemaRegistry:\n url: https://my-schema-registry:8081\n security:\n username: admin\n password: admin-secret\n type: BasicAuth\n ignoreUntrustedCertificate: false\n type: ConfluentLike\n","Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: KafkaConnectCluster\nmetadata:\n name: connect-1\n cluster: my-cloud\n labels:\n user-labels: I am a user label\nspec:\n displayName: My kafka connect\n urls: http://localhost:8083\n headers:\n a: b\n c: d\n ignoreUntrustedCertificate: true\n security:\n username: user\n password: password\n type: BasicAuth\n","Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: KsqlDBCluster\nmetadata:\n name: connect-1\n cluster: my-cloud\nspec:\n displayName: My kafka connect\n url: http://localhost:8083\n headers:\n a: b\n c: d\n ignoreUntrustedCertificate: true\n security:\n username: user\n password: password\n type: BasicAuth\n","Order":4}}},"PartnerZone":{"Versions":{"2":{"ListPath":"/public/console/v2/partner-zone","Name":"PartnerZone","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: PartnerZone\nmetadata:\n name: john-partner-zone\nspec:\n cluster: my-cluster\n displayName: John's partner zone\n url: http://conduktor.io\n serviceAccount: johndoe\n topics:\n - name: topic-a\n backingTopic: kafka-topic-a\n permission: WRITE\n partner:\n name: John Doe\n role: Data analyst\n email: johndoe@company.io\n phone: 07827 837 177\n","Order":16}}},"ServiceAccount":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/cluster/{cluster}/service-account","Name":"ServiceAccount","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v1\nkind: ServiceAccount\nmetadata:\n appInstance: my-app-instance-dev\n cluster: my-kafka-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: dev\n user-labels: I am a user label\n name: sa-clicko-dev\nspec:\n authorization:\n type: KAFKA_ACL\n acls:\n - type: TOPIC\n name: click.\n patternType: PREFIXED\n operations:\n - Write\n host: '*'\n permission: Allow\n","Order":10}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: Subject\nmetadata:\n name: my-subject\n cluster: my-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: staging\nspec:\n format: AVRO\n compatibility: BACKWARD_TRANSITIVE\n schema: '{\"type\": \"long\"}'\n","Order":12}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: Topic\nmetadata:\n name: my-topic\n cluster: my-cluster\n labels:\n conduktor.io/application: application-a\n conduktor.io/application-instance: staging\n user-labels: I am a user label\n catalogVisibility: PUBLIC\n descriptionIsEditable: true\n description: This is a topic description\n sqlStorage:\n retentionTimeInSecond: 42\nspec:\n partitions: 1\n replicationFactor: 1\n configs:\n cleanup.policy: delete\n retention.ms: '86400000'\n","Order":11}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"ApplyExample":"apiVersion: v1\nkind: TopicPolicy\nmetadata:\n name: my-app-instance-prod\nspec:\n policies:\n my-policy:\n constraint: OneOf\n optional: true\n values:\n - value1\n - value2\n","Order":5}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"ApplyExample":"apiVersion: v2\nkind: User\nmetadata:\n name: user@conduktor.io\nspec:\n firstName: description\n lastName: test\n permissions: []\n","Order":0}}}},"Run":{"partnerZoneGenerateCredentials":{"Path":"/public/partner-zone/v2/{partner-zone-name}/generate-credentials","Name":"partnerZoneGenerateCredentials","Doc":"generate a token for a partner zone service account","QueryParameter":{},"PathParameter":["partner-zone-name"],"BodyFields":{},"Method":"POST"}}}
\ No newline at end of file
diff --git a/schema/default_schema/gateway.json b/schema/default_schema/gateway.json
index aa6c557..be09e0c 100644
--- a/schema/default_schema/gateway.json
+++ b/schema/default_schema/gateway.json
@@ -1 +1 @@
-{"AliasTopic":{"Versions":{"2":{"ListPath":"/gateway/v2/alias-topic","Name":"AliasTopic","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: AliasTopic\napiVersion: gateway/v2\nmetadata:\n name: name1\n vCluster: vCluster1\nspec:\n physicalName: physicalName1\n","Order":8}}},"ConcentrationRule":{"Versions":{"2":{"ListPath":"/gateway/v2/concentration-rule","Name":"ConcentrationRule","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: ConcentrationRule\napiVersion: gateway/v2\nmetadata:\n name: concentrationRule1\n vCluster: vCluster1\nspec:\n pattern: topic.*\n physicalTopics:\n delete: topic\n compact: compact_topic\n deleteCompact: compact_delete_topic\n autoManaged: false\n offsetCorrectness: false\n","Order":9}}},"GatewayGroup":{"Versions":{"2":{"ListPath":"/gateway/v2/group","Name":"GatewayGroup","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"}},"GetAvailable":true,"ApplyExample":"kind: GatewayGroup\napiVersion: gateway/v2\nmetadata:\n name: group1\nspec:\n members:\n - vCluster: vCluster1\n name: serviceAccount1\n - vCluster: vCluster2\n name: serviceAccount2\n - vCluster: vCluster3\n name: serviceAccount3\n externalGroups:\n - GROUP_READER\n - GROUP_WRITER\n","Order":11}}},"GatewayServiceAccount":{"Versions":{"2":{"ListPath":"/gateway/v2/service-account","Name":"GatewayServiceAccount","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"type":{"FlagName":"type","Required":false,"Type":"string"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: GatewayServiceAccount\napiVersion: gateway/v2\nmetadata:\n name: user1\n vCluster: vcluster1\nspec:\n type: EXTERNAL\n externalNames:\n - externalName\n","Order":10}}},"Interceptor":{"Versions":{"2":{"ListPath":"/gateway/v2/interceptor","Name":"Interceptor","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"global":{"FlagName":"global","Required":false,"Type":"boolean"},"group":{"FlagName":"group","Required":false,"Type":"string"},"name":{"FlagName":"name","Required":false,"Type":"string"},"username":{"FlagName":"username","Required":false,"Type":"string"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: Interceptor\napiVersion: gateway/v2\nmetadata:\n name: yellow_cars_filter\n scope:\n vCluster: vCluster1\nspec:\n comment: Filter yellow cars\n pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin\n priority: 1\n config:\n virtualTopic: yellow_cars\n statement: SELECT '$.type' as type, '$.price' as price FROM cars WHERE '$.color' = 'yellow'\n","Order":12}}},"VirtualCluster":{"Versions":{"2":{"ListPath":"/gateway/v2/virtual-cluster","Name":"VirtualCluster","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"GetAvailable":true,"ApplyExample":"kind: VirtualCluster\napiVersion: gateway/v2\nmetadata:\n name: vcluster1\nspec:\n aclEnabled: false\n superUsers:\n - username1\n - username2\n type: Standard\n","Order":7}}}}
\ No newline at end of file
+{"Kind":{"AliasTopic":{"Versions":{"2":{"ListPath":"/gateway/v2/alias-topic","Name":"AliasTopic","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: AliasTopic\napiVersion: gateway/v2\nmetadata:\n name: name1\n vCluster: vCluster1\nspec:\n physicalName: physicalName1\n","Order":8}}},"ConcentrationRule":{"Versions":{"2":{"ListPath":"/gateway/v2/concentration-rule","Name":"ConcentrationRule","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: ConcentrationRule\napiVersion: gateway/v2\nmetadata:\n name: concentrationRule1\n vCluster: vCluster1\nspec:\n pattern: topic.*\n physicalTopics:\n delete: topic\n compact: compact_topic\n deleteCompact: compact_delete_topic\n autoManaged: false\n offsetCorrectness: false\n","Order":9}}},"GatewayGroup":{"Versions":{"2":{"ListPath":"/gateway/v2/group","Name":"GatewayGroup","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"}},"GetAvailable":true,"ApplyExample":"kind: GatewayGroup\napiVersion: gateway/v2\nmetadata:\n name: group1\nspec:\n members:\n - vCluster: vCluster1\n name: serviceAccount1\n - vCluster: vCluster2\n name: serviceAccount2\n - vCluster: vCluster3\n name: serviceAccount3\n externalGroups:\n - GROUP_READER\n - GROUP_WRITER\n","Order":11}}},"GatewayServiceAccount":{"Versions":{"2":{"ListPath":"/gateway/v2/service-account","Name":"GatewayServiceAccount","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"name":{"FlagName":"name","Required":false,"Type":"string"},"showDefaults":{"FlagName":"show-defaults","Required":false,"Type":"boolean"},"type":{"FlagName":"type","Required":false,"Type":"string"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: GatewayServiceAccount\napiVersion: gateway/v2\nmetadata:\n name: user1\n vCluster: vcluster1\nspec:\n type: EXTERNAL\n externalNames:\n - externalName\n","Order":10}}},"Interceptor":{"Versions":{"2":{"ListPath":"/gateway/v2/interceptor","Name":"Interceptor","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{"global":{"FlagName":"global","Required":false,"Type":"boolean"},"group":{"FlagName":"group","Required":false,"Type":"string"},"name":{"FlagName":"name","Required":false,"Type":"string"},"username":{"FlagName":"username","Required":false,"Type":"string"},"vcluster":{"FlagName":"vcluster","Required":false,"Type":"string"}},"GetAvailable":false,"ApplyExample":"kind: Interceptor\napiVersion: gateway/v2\nmetadata:\n name: yellow_cars_filter\n scope:\n vCluster: vCluster1\nspec:\n comment: Filter yellow cars\n pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin\n priority: 1\n config:\n virtualTopic: yellow_cars\n statement: SELECT '$.type' as type, '$.price' as price FROM cars WHERE '$.color' = 'yellow'\n","Order":12}}},"VirtualCluster":{"Versions":{"2":{"ListPath":"/gateway/v2/virtual-cluster","Name":"VirtualCluster","ParentPathParam":[],"ParentQueryParam":null,"ListQueryParameter":{},"GetAvailable":true,"ApplyExample":"kind: VirtualCluster\napiVersion: gateway/v2\nmetadata:\n name: vcluster1\nspec:\n aclEnabled: false\n superUsers:\n - username1\n - username2\n type: Standard\n bootstrapServers: kafka:9092\n clientProperties:\n security.protocol: SASL_PLAINTEXT\n sasl.mechanism: PLAIN\n sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username={{username}} password={{password}};\n","Order":7}}}},"Run":{"generateServiceAccountToken":{"Path":"/gateway/v2/token","Name":"generateServiceAccountToken","Doc":"Generate a token for a service account on a virtual cluster","QueryParameter":{},"PathParameter":[],"BodyFields":{"lifeTimeSeconds":{"FlagName":"life-time-seconds","Required":true,"Type":"integer"},"username":{"FlagName":"username","Required":true,"Type":"string"},"vCluster":{"FlagName":"v-cluster","Required":false,"Type":"string"}},"Method":"POST"}}}
\ No newline at end of file
diff --git a/schema/execute.go b/schema/execute.go
deleted file mode 100644
index 3288ebd..0000000
--- a/schema/execute.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package schema
-
-import (
- "fmt"
- "strings"
-)
-
-type Execute interface {
- GetName() string
- GetDoc() string
- GetPath() string
- BuildPath(pathValue []string) string
- GetQueryParameter() map[string]QueryParameterOption
- GetPathParameter() []string
- GetBodyFields() map[string]BodyField
- GetMethod() string
-}
-
-type ConsoleExecute struct {
- Path string
- Name string
- Doc string
- ListQueryParameter map[string]QueryParameterOption
- PathParameter []string
- BodyFields map[string]BodyField
- Method string
-}
-
-func (c *ConsoleExecute) GetBodyFields() map[string]BodyField {
- return c.BodyFields
-}
-
-func (c *ConsoleExecute) GetName() string {
- return c.Name
-}
-
-func (c *ConsoleExecute) GetPath() string {
- return c.Path
-}
-
-func (c *ConsoleExecute) GetDoc() string {
- return c.Doc
-}
-
-func (c *ConsoleExecute) GetMethod() string {
- return c.Method
-}
-
-// TODO: test
-func (c *ConsoleExecute) BuildPath(pathValue []string) string {
- path := c.GetPath()
- if len(pathValue) != len(c.PathParameter) {
- panic(fmt.Sprintf("BuildPath: pathValue lentgth (%d) does not match execution path parameter length (%d) for %s", len(pathValue), len(c.PathParameter), c.Name))
- }
- for i, pathValue := range pathValue {
- path = strings.Replace(path, fmt.Sprintf("{%s}", c.PathParameter[i]), pathValue, 1)
- }
- return path
-}
-
-func (c *ConsoleExecute) GetQueryParameter() map[string]QueryParameterOption {
- return c.ListQueryParameter
-}
-
-func (c *ConsoleExecute) GetPathParameter() []string {
- return c.PathParameter
-}
diff --git a/schema/openapi_parser.go b/schema/openapi_parser.go
index 6d8116e..c9eaae5 100644
--- a/schema/openapi_parser.go
+++ b/schema/openapi_parser.go
@@ -64,22 +64,22 @@ func getKinds[T KindVersion](s *OpenApiParser, strict bool, buildKindVersion fun
return result, nil
}
-func (s *OpenApiParser) getExecutes() (ExecuteCatalog, error) {
- result := make(ExecuteCatalog, 0)
+func (s *OpenApiParser) getRuns(backendType BackendType) (RunCatalog, error) {
+ result := make(RunCatalog, 0)
for path := s.doc.Model.Paths.PathItems.First(); path != nil; path = path.Next() {
- err := handleExecuteOperation(path.Key(), path.Value().Get, resty.MethodGet, result)
+ err := handleExecuteOperation(backendType, path.Key(), path.Value().Get, resty.MethodGet, result)
if err != nil {
return nil, err
}
- err = handleExecuteOperation(path.Key(), path.Value().Post, resty.MethodPost, result)
+ err = handleExecuteOperation(backendType, path.Key(), path.Value().Post, resty.MethodPost, result)
if err != nil {
return nil, err
}
- err = handleExecuteOperation(path.Key(), path.Value().Put, resty.MethodPut, result)
+ err = handleExecuteOperation(backendType, path.Key(), path.Value().Put, resty.MethodPut, result)
if err != nil {
return nil, err
}
- err = handleExecuteOperation(path.Key(), path.Value().Delete, resty.MethodDelete, result)
+ err = handleExecuteOperation(backendType, path.Key(), path.Value().Delete, resty.MethodDelete, result)
if err != nil {
return nil, err
}
@@ -87,40 +87,41 @@ func (s *OpenApiParser) getExecutes() (ExecuteCatalog, error) {
return result, nil
}
-func handleExecuteOperation(path string, operation *v3high.Operation, method string, result ExecuteCatalog) error {
+func handleExecuteOperation(backendType BackendType, path string, operation *v3high.Operation, method string, result RunCatalog) error {
if operation == nil {
return nil
}
- nameYaml, present := operation.Extensions.Get("x-cdk-execute-action-name")
+ nameYaml, present := operation.Extensions.Get("x-cdk-run-name")
if !present {
return nil
}
name := nameYaml.Value
- docYaml, docPresent := operation.Extensions.Get("x-cdk-execute-action-doc")
+ docYaml, docPresent := operation.Extensions.Get("x-cdk-run-doc")
var doc string
if docPresent {
doc = docYaml.Value
} else {
doc = ""
}
- execute := ConsoleExecute{
- Path: path,
- Name: name,
- Doc: doc,
- ListQueryParameter: make(map[string]QueryParameterOption, len(operation.Parameters)),
- PathParameter: make([]string, 0, len(operation.Parameters)),
- Method: method,
+ run := Run{
+ BackendType: backendType,
+ Path: path,
+ Name: name,
+ Doc: doc,
+ QueryParameter: make(map[string]QueryParameterOption, len(operation.Parameters)),
+ PathParameter: make([]string, 0, len(operation.Parameters)),
+ Method: method,
}
for _, parameter := range operation.Parameters {
if parameter.In == "path" && *parameter.Required {
- execute.PathParameter = append(execute.PathParameter, parameter.Name)
+ run.PathParameter = append(run.PathParameter, parameter.Name)
}
- if parameter.In == "query" && parameter.Name != "dryMode" {
+ if parameter.In == "query" {
schemaTypes := parameter.Schema.Schema().Type
if len(schemaTypes) == 1 {
queryName := parameter.Name
- execute.ListQueryParameter[queryName] = QueryParameterOption{
+ run.QueryParameter[queryName] = QueryParameterOption{
FlagName: computeFlagName(queryName),
Required: *parameter.Required,
Type: schemaTypes[0],
@@ -128,8 +129,8 @@ func handleExecuteOperation(path string, operation *v3high.Operation, method str
}
}
}
- execute.BodyFields = computeBodyFields(operation.RequestBody)
- result[name] = &execute
+ run.BodyFields = computeBodyFields(operation.RequestBody)
+ result[name] = run
return nil
}
@@ -146,7 +147,7 @@ func computeBodyFields(body *v3high.RequestBody) map[string]BodyField {
value := propertiesPair.Value()
if value != nil && value.Schema() != nil {
valueType := value.Schema().Type[0]
- if valueType == "string" || valueType == "boolean" {
+ if valueType == "string" || valueType == "boolean" || valueType == "integer" {
result[key] = BodyField{
FlagName: computeFlagName(key),
Type: valueType,
@@ -164,13 +165,13 @@ func (s *OpenApiParser) GetConsoleCatalog(strict bool) (*Catalog, error) {
if err != nil {
return nil, err
}
- execute, err := s.getExecutes()
+ runs, err := s.getRuns(CONSOLE)
if err != nil {
return nil, err
}
return &Catalog{
- Kind: kinds,
- Execute: execute,
+ Kind: kinds,
+ Run: runs,
}, nil
}
@@ -186,12 +187,16 @@ func (s *OpenApiParser) GetGatewayCatalog(strict bool) (*Catalog, error) {
kinds, err := s.GetGatewayKinds(strict)
if err != nil {
return nil, err
- } else {
- return &Catalog{
- Kind: kinds,
- Execute: map[string]Execute{},
- }, nil
}
+ runs, err := s.getRuns(GATEWAY)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Catalog{
+ Kind: kinds,
+ Run: runs,
+ }, nil
}
func buildConsoleKindVersion(s *OpenApiParser, path, kind string, order int, put *v3high.Operation, get *v3high.Operation, strict bool) (*ConsoleKindVersion, error) {
diff --git a/schema/openapi_parser_console_test.go b/schema/openapi_parser_console_test.go
index 83f4978..81a4683 100644
--- a/schema/openapi_parser_console_test.go
+++ b/schema/openapi_parser_console_test.go
@@ -361,7 +361,7 @@ func TestKindNotRequiredMetadataField(t *testing.T) {
func TestGetExecutes(t *testing.T) {
t.Run("gets execute endpoint from schema", func(t *testing.T) {
- schemaContent, err := os.ReadFile("testdata/execute.yaml")
+ schemaContent, err := os.ReadFile("testdata/console_run.yaml")
if err != nil {
t.Fatalf("failed reading file: %s", err)
}
@@ -371,27 +371,29 @@ func TestGetExecutes(t *testing.T) {
t.Fatalf("failed creating new schema: %s", err)
}
- result, err := schema.getExecutes()
+ result, err := schema.getRuns(CONSOLE)
if err != nil {
t.Fatalf("failed getting execute: %s", err)
}
- expected := ExecuteCatalog{
- "partnerZoneGenerateCredentials": &ConsoleExecute{
- Path: "/public/partner-zone/v2/{partner-zone-name}/generate-credentials",
- Name: "partnerZoneGenerateCredentials",
- PathParameter: []string{"partner-zone-name"},
- Doc: "generate a token for a partner zone service account",
- ListQueryParameter: map[string]QueryParameterOption{},
- BodyFields: map[string]BodyField{},
- Method: "POST",
+ //all the token runs are not present in real life just present in the yaml test file used here
+ expected := RunCatalog{
+ "partnerZoneGenerateCredentials": Run{
+ Path: "/public/partner-zone/v2/{partner-zone-name}/generate-credentials",
+ Name: "partnerZoneGenerateCredentials",
+ PathParameter: []string{"partner-zone-name"},
+ Doc: "generate a token for a partner zone service account",
+ QueryParameter: map[string]QueryParameterOption{},
+ BodyFields: map[string]BodyField{},
+ Method: "POST",
+ BackendType: CONSOLE,
},
- "createAdminToken": &ConsoleExecute{
- Path: "/token/v1/admin_tokens",
- Name: "createAdminToken",
- Doc: "Create an admin token",
- ListQueryParameter: map[string]QueryParameterOption{},
- PathParameter: []string{},
+ "createAdminToken": Run{
+ Path: "/token/v1/admin_tokens",
+ Name: "createAdminToken",
+ Doc: "Create an admin token",
+ QueryParameter: map[string]QueryParameterOption{},
+ PathParameter: []string{},
BodyFields: map[string]BodyField{
"name": {
FlagName: "name",
@@ -399,13 +401,14 @@ func TestGetExecutes(t *testing.T) {
Type: "string",
},
},
- Method: "POST",
+ Method: "POST",
+ BackendType: CONSOLE,
},
- "createApplicationInstanceToken": &ConsoleExecute{
- Path: "/token/v1/application_instance_tokens/{application-instance-name}",
- Name: "createApplicationInstanceToken",
- Doc: "Create an application instance token",
- ListQueryParameter: map[string]QueryParameterOption{},
+ "createApplicationInstanceToken": Run{
+ Path: "/token/v1/application_instance_tokens/{application-instance-name}",
+ Name: "createApplicationInstanceToken",
+ Doc: "Create an application instance token",
+ QueryParameter: map[string]QueryParameterOption{},
PathParameter: []string{
"application-instance-name",
},
@@ -416,36 +419,40 @@ func TestGetExecutes(t *testing.T) {
Type: "string",
},
},
- Method: "POST",
+ Method: "POST",
+ BackendType: CONSOLE,
},
- "deleteToken": &ConsoleExecute{
- Path: "/token/v1/{token-id}",
- Name: "deleteToken",
- Doc: "Delete a token",
- ListQueryParameter: map[string]QueryParameterOption{},
- PathParameter: []string{"token-id"},
- BodyFields: map[string]BodyField{},
- Method: "DELETE",
+ "deleteToken": Run{
+ Path: "/token/v1/{token-id}",
+ Name: "deleteToken",
+ Doc: "Delete a token",
+ QueryParameter: map[string]QueryParameterOption{},
+ PathParameter: []string{"token-id"},
+ BodyFields: map[string]BodyField{},
+ Method: "DELETE",
+ BackendType: CONSOLE,
},
- "listAdminToken": &ConsoleExecute{
- Path: "/token/v1/admin_tokens",
- Name: "listAdminToken",
- Doc: "List admin token",
- ListQueryParameter: map[string]QueryParameterOption{},
- PathParameter: []string{},
- BodyFields: map[string]BodyField{},
- Method: "GET",
+ "listAdminToken": Run{
+ Path: "/token/v1/admin_tokens",
+ Name: "listAdminToken",
+ Doc: "List admin token",
+ QueryParameter: map[string]QueryParameterOption{},
+ PathParameter: []string{},
+ BodyFields: map[string]BodyField{},
+ Method: "GET",
+ BackendType: CONSOLE,
},
- "listApplicationInstanceToken": &ConsoleExecute{
- Path: "/token/v1/application_instance_tokens/{application-instance-name}",
- Name: "listApplicationInstanceToken",
- Doc: "List application instance token",
- ListQueryParameter: map[string]QueryParameterOption{},
+ "listApplicationInstanceToken": Run{
+ Path: "/token/v1/application_instance_tokens/{application-instance-name}",
+ Name: "listApplicationInstanceToken",
+ Doc: "List application instance token",
+ QueryParameter: map[string]QueryParameterOption{},
PathParameter: []string{
"application-instance-name",
},
- BodyFields: map[string]BodyField{},
- Method: "GET",
+ BodyFields: map[string]BodyField{},
+ Method: "GET",
+ BackendType: CONSOLE,
},
}
if !reflect.DeepEqual(result, expected) {
diff --git a/schema/openapi_parser_gateway_test.go b/schema/openapi_parser_gateway_test.go
index 1a0a0cf..0c8c269 100644
--- a/schema/openapi_parser_gateway_test.go
+++ b/schema/openapi_parser_gateway_test.go
@@ -262,3 +262,54 @@ spec:
}
})
}
+func TestGetExecutesForGateway(t *testing.T) {
+ t.Run("gets execute endpoint from schema", func(t *testing.T) {
+ schemaContent, err := os.ReadFile("testdata/gateway_run.yaml")
+ if err != nil {
+ t.Fatalf("failed reading file: %s", err)
+ }
+
+ schema, err := NewOpenApiParser(schemaContent)
+ if err != nil {
+ t.Fatalf("failed creating new schema: %s", err)
+ }
+
+ result, err := schema.getRuns(GATEWAY)
+ if err != nil {
+ t.Fatalf("failed getting execute: %s", err)
+ }
+
+ //all the token runs are not present in real life just present in the yaml test file used here
+ expected := RunCatalog{
+ "generateServiceAccountToken": Run{
+ Path: "/gateway/v2/token",
+ Name: "generateServiceAccountToken",
+ Doc: "Generate a token for a service account on a virtual cluster",
+ QueryParameter: map[string]QueryParameterOption{},
+ PathParameter: []string{},
+ BodyFields: map[string]BodyField{
+ "vCluster": {
+ FlagName: "v-cluster",
+ Required: false,
+ Type: "string",
+ },
+ "lifeTimeSeconds": {
+ Type: "integer",
+ Required: true,
+ FlagName: "life-time-seconds",
+ },
+ "username": {
+ FlagName: "username",
+ Required: true,
+ Type: "string",
+ },
+ },
+ Method: "POST",
+ BackendType: GATEWAY,
+ },
+ }
+ if !reflect.DeepEqual(result, expected) {
+ t.Error(spew.Printf("got %v, want %v", result, expected))
+ }
+ })
+}
diff --git a/schema/run.go b/schema/run.go
new file mode 100644
index 0000000..d2aaf44
--- /dev/null
+++ b/schema/run.go
@@ -0,0 +1,30 @@
+package schema
+
+import (
+ "fmt"
+ "strings"
+)
+
+type Run struct {
+ Path string
+ Name string
+ Doc string
+ QueryParameter map[string]QueryParameterOption
+ PathParameter []string
+ BodyFields map[string]BodyField
+ Method string
+
+ BackendType BackendType `json:"-"`
+}
+
+// TODO: test
+func (c *Run) BuildPath(pathValue []string) string {
+ path := c.Path
+ if len(pathValue) != len(c.PathParameter) {
+ panic(fmt.Sprintf("BuildPath: pathValue lentgth (%d) does not match execution path parameter length (%d) for %s", len(pathValue), len(c.PathParameter), c.Name))
+ }
+ for i, pathValue := range pathValue {
+ path = strings.Replace(path, fmt.Sprintf("{%s}", c.PathParameter[i]), pathValue, 1)
+ }
+ return path
+}
diff --git a/schema/testdata/execute.yaml b/schema/testdata/console_run.yaml
similarity index 99%
rename from schema/testdata/execute.yaml
rename to schema/testdata/console_run.yaml
index 4d60d81..9ee58cb 100644
--- a/schema/testdata/execute.yaml
+++ b/schema/testdata/console_run.yaml
@@ -251,8 +251,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: listAdminToken
- x-cdk-execute-action-doc: List admin token
+ x-cdk-run-version: '1'
+ x-cdk-run-name: listAdminToken
+ x-cdk-run-doc: List admin token
post:
tags:
- tokens
@@ -313,8 +314,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: createAdminToken
- x-cdk-execute-action-doc: Create an admin token
+ x-cdk-run-version: '1'
+ x-cdk-run-name: createAdminToken
+ x-cdk-run-doc: Create an admin token
/token/v1/{token-id}:
delete:
tags:
@@ -373,8 +375,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: deleteToken
- x-cdk-execute-action-doc: Delete a token
+ x-cdk-run-version: '1'
+ x-cdk-run-name: deleteToken
+ x-cdk-run-doc: Delete a token
/token/v1/application_instance_tokens/{application-instance-name}:
get:
tags:
@@ -439,8 +442,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: listApplicationInstanceToken
- x-cdk-execute-action-doc: List application instance token
+ x-cdk-run-version: '1'
+ x-cdk-run-name: listApplicationInstanceToken
+ x-cdk-run-doc: List application instance token
post:
tags:
- tokens
@@ -509,8 +513,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: createApplicationInstanceToken
- x-cdk-execute-action-doc: Create an application instance token
+ x-cdk-run-version: '1'
+ x-cdk-run-name: createApplicationInstanceToken
+ x-cdk-run-doc: Create an application instance token
/public/v1/groups:
get:
tags:
@@ -8719,8 +8724,9 @@ paths:
title: An unexpected error occurred in the server
security:
- httpAuth: []
- x-cdk-execute-action-name: partnerZoneGenerateCredentials
- x-cdk-execute-action-doc: generate a token for a partner zone service account
+ x-cdk-run-version: '1'
+ x-cdk-run-name: partnerZoneGenerateCredentials
+ x-cdk-run-doc: generate a token for a partner zone service account
x-codeSamples:
- lang: Shell + Curl
source: |-
diff --git a/schema/testdata/gateway_run.yaml b/schema/testdata/gateway_run.yaml
new file mode 100644
index 0000000..fce101f
--- /dev/null
+++ b/schema/testdata/gateway_run.yaml
@@ -0,0 +1,3356 @@
+openapi: 3.1.0
+info:
+ title: Conduktor Gateway API
+ version: v2
+ summary: The API to interact with Conduktor Gateway programmatically
+ contact:
+ email: contact@conduktor.io
+ url: https://docs.conduktor.io
+ x-logo:
+ url: https://raw.githubusercontent.com/conduktor/conduktor.io-public/main/logo/conduktor-gateway-api.png
+ backgroundColor: '#FFFFFF'
+ altText: Conduktor logo
+tags:
+- name: Introduction
+ description: |
+ The Conduktor Gateway REST API 's aim is to help you configure your Gateway.
+
+ The legacy (v1) API is available but deprecated ([V1 documentation](./?apiVersion=v1)).
+
+ Get started with Conduktor Gateway [self-hosted](https://docs.conduktor.io/gateway/installation/) today. Setup takes only a few minutes.
+- name: Authentication
+ description: |-
+ Authentication to the API requires a basic authentication.
+
+ To get a token and use it you must go through the following steps:
+
+ * Configure the admin password in the Gateway YAML configuration file.
+
+ * Use the password in the **authorization** header of your requests.
+
+ Example:
+
+ ```shell
+ curl -X GET "https://your.gateway-api.host/gateway/v2/virtual-cluster" \
+ -H "accept: application/json" \
+ --user "admin:password"
+ ```
+- name: Kinds
+ description: |
+ ### Definition
+
+ Kinds the resource types of the Conduktor gateway.
+
+ ### Conduktor Gateway Kinds
+
+ The following kinds are available in the Conduktor Gateway API:
+
+ * `VirtualCluster`
+ * `AliasTopic`
+ * `ConcentratedTopic`
+ * `ConcentrationRule`
+ * `Interceptor`
+ * `Plugin`
+ * `GatewayServiceAccount`
+ * `Token`
+ * `GatewayGroup`
+- name: Api Groups
+ description: |+
+ ### Definition
+
+ API groups a set of resources that share the same API path prefix. They are used to organize the API endpoints and the
+ resources they manage.
+ The versioning is set at this level, so all the resources in the same group share the same version.
+
+ ### Conduktor Api Groups
+
+ The Gateway API consist of a single API group right now (`gateway`), and it manages the following resources:
+
+ | Api Group | Version | Kinds |
+ |------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
+ | `/gateway` | `/v2` | `/virtual-cluster`, `/alias-topic`, `/concentrated-topic`, `/concentration-rule`, `/interceptor`, `/plugin`, `/service-account`, `/group`, `/token` |
+
+
+
+- name: Versioning
+ description: |+
+ * __The version is set at the api group level__. It is incremented when a breaking change happens in the schema of an endpoint of the group (that has been marked `stable`). The n-1 version is still available for a while to allow users to migrate. The version is part of the endpoint path.
+ * The API version (v2) is the global version of the Conduktor Gateway API, it should not change unless there is a complete overhaul of the API.
+
+
+ Endpoint also have a status to manage their API lifecycle, following the order below:
+ * __preview__: this is an early-stage feature, really likely to change
+ * __beta__: early access feature, breaking change
+ * __stable__: Production-ready endpoint, no breaking change
+ * __deprecated__: This endpoint isn't supported anymore and the user should migrate
+
+
+- name: Conventions
+ description: |+
+ ### Path conventions
+
+ The API follows as much as possible the endpoints structure below for each kind of resource:
+
+ * `GET /{api-group}/{version}/{kind}/{name}` to read a resource
+ * `GET /{api-group}/{version}/{kind}` to list resources of a kind
+ * `PUT /{api-group}/{version}/{kind}` to update or create a resource
+ * `DELETE /{api-group}/{version}/{kind}/{name}` to delete a resource (returns 204 No Content)
+ * `POST` is used for specific operations that don't fit this CRUD model. PUT is the default verb for updates and
+ creations.
+ * Important principle: the result of a GET can be reused as the body of a PUT to update the resource.
+
+ __Non-unique names__:
+ When a `name` is not enough to uniquely identify a resource, the GET and DELETE endpoint are different
+ The GET by name is replaced by query parameters (returning lists or the searched item if the criteria are the elements
+ of the key), and the DELETE by name is replaced by a DELETE with a body.
+ For example, an `alias-topic` is identified by its `name` and the `vCluster` gives the following endpoints:
+
+ * `GET /gateway/v2/alias-topic?name={name}&vcluster={vcluster}`
+ * `PUT /gateway/v2/alias-topic`
+ * `DELETE /gateway/v2/alias-topic` with a body containing the `name` and the `vCluster`
+
+ ### Other conventions
+
+ * All requests and responses are in JSON and should have their `content-type` header set to `application/json`
+ * Every kind has a lower-cased name (e.g. `virtual-cluster` for the `VirtualCluster` kind) that is used in the endpoint
+ path.
+ * Errors have a standard format:
+ * The HTTP status code is used to indicate the type of error.
+ * The response body contains a common JSON object for every error:
+ * `title`: a unique error code for the error.
+ * `message`: a human-readable message for the error.
+ * `cause`: additional information about the error.
+ * All timestamps are in ISO 8601 format.
+
+- name: token
+ description: |+
+ ### Definition
+
+ The token group contains just a utility endpoint to generate a token for a given Local ServiceAccount (on a given
+ virtual cluster, or `passthrough` if omitted).
+
+ This token can be used to authenticate against the Gateway API in the `sasl_plaintext` authentication mode.
+ More information on this case here : https://docs.conduktor.io/gateway/concepts/Clients/#sasl_plaintext
+
+ ### Available operations
+
+ * Generate a token
+
+ ### Identity
+
+ N/A.
+
+- name: cli_virtual-cluster_gateway_v2_7
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Virtual%20Cluster/
+
+ ### Available operations
+
+ * List virtual clusters
+ * Get a virtual cluster
+ * Upsert a virtual cluster
+ * Delete a virtual cluster
+
+ ### Identity
+
+ A virtual cluster is identified by the `name`.
+
+ ### Schema
+
+
+
+
+ x-displayName: virtual-cluster
+- name: cli_alias-topic_gateway_v2_8
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Logical_topics/Alias%20topics/
+
+ ### Available operations
+
+ * List alias topics
+ * Upsert an alias topic
+ * Delete an alias topic
+
+ ### Identity
+
+ An alias topic is identified by the `name` inside a `vCluster` (`passthrough` if omitted).
+
+ ### Schema
+
+
+
+
+ x-displayName: alias-topic
+- name: cli_concentrated-topic_gateway_v2_0
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Logical_topics/Concentration/
+
+ ### Available operations
+
+ * List concentrated topics
+
+ Concentrated topics are created when a concentration rule is applied. They are not created or deleted directly by the API.
+
+ ### Identity
+
+ A concentrated topic is identified by the `name` and the `vCluster` (`passthrough` if omitted).
+
+ ### Schema
+
+
+
+
+ x-displayName: concentrated-topic
+- name: cli_concentration-rule_gateway_v2_9
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Logical_topics/Concentration/
+
+ ### Available operations
+
+ * List concentration rules
+ * Get a concentration rule
+ * Upsert a concentration rule
+ * Delete a concentration rule
+
+
+ ### Identity
+
+ A concentration rule is identified by its `name` inside a `vCluster`.
+
+ ### Schema
+
+
+
+
+ x-displayName: concentration-rule
+- name: cli_interceptor_gateway_v2_12
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Interceptors-and-plugins/
+
+ ### Available operations
+
+ * List the interceptors
+ * Get an interceptor
+ * Upsert an interceptor
+ * Delete an interceptor
+
+ ### Identity
+
+ An interceptor is identified by its `name` and its `scope`.
+ The `scope` is itself composed of 3 optional fields `vCluster`, `group`, `username`.
+ A __global__ interceptor is an interceptor whose `scope` has its fields empty.
+
+ ### Schema
+
+
+
+
+ x-displayName: interceptor
+- name: plugin
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/Interceptors-and-plugins/
+
+ ### Available operations
+
+ * List the available plugins of the Gateway
+
+ ### Identity
+
+ A plugin is identified by its `pluginId`.
+
+ The list of plugins is fixed for a given Gateway instance.
+ The list is fixed and cannot be modified.
+
+ ### Schema
+
+
+
+
+- name: cli_gateway-service-account_gateway_v2_10
+ description: |+
+ ### Definition
+
+ https://docs.conduktor.io/gateway/concepts/service-accounts-authentication-authorization/
+
+ ### Available operations
+
+ * List service accounts
+ * Upsert a service account
+ * Delete a service account
+
+ ### Identity
+
+ The service account is identified by the `name` and the `vCluster`.
+
+ The `vCluster` name is not mandatory, but if omitted, the `passthrough` virtual cluster will be used.
+ Thus, a service account is always associated with one and only one virtual cluster.
+
+ ### Local and external service accounts
+
+ A service account can be `Local` or `External`.
+
+ * A `Local` service account is just a local user that allows to generate Gateway tokens for your Kafka client
+ applications (SASL).
+ * An `External` service account is a user that is authenticated by an external system (OIDC). In such a
+ scenario you will only need to create external service accounts in 2 cases : either to rename the OIDC principal
+ for you Kafka applications OR to gather service accounts into `Groups`. Gateway Tokens are not issued for external
+ service accounts since the authentication must be done by the external system.
+
+ To create an external service account you must provide have an `principal` that is the name of the user in the
+ external system.
+ It can be equal or not to the service account `name` (up to you), but note that __the `principal` must be unique
+ across all virtual clusters__.
+
+ ### Schema
+
+
+
+
+ x-displayName: service-account
+- name: cli_gateway-group_gateway_v2_11
+ description: |+
+ ### Definition
+
+ Groups a defined by name a allow to regroup Gateway users in order to apply interceptors rules.
+
+ ### Available operations
+
+ * List groups
+ * Get a group
+ * Upsert a group
+ * Delete a group
+
+ ### Identity
+
+ The group is identified by its `name` (unique across all the virtual clusters).
+
+ A group can be added external groups (coming from LDAP, OIDC claims etc.) which will allow the Gateway to bind them on the Gateway Group.
+
+ ### Schema
+
+
+
+
+ x-displayName: group
+paths:
+ /gateway/v2/token:
+ post:
+ tags:
+ - token
+ description: |2+
+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Create a new token for given service account and a given virtual cluster.
+
+ If the vcluster is not provided, the token will be created for the passthrough virtual cluster.
+
+ operationId: Generate a token for a service account on a virtual cluster
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TokenRequest'
+ example:
+ vCluster: vcluster1
+ username: user1
+ lifeTimeSeconds: 3600
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TokenResponse'
+ example:
+ token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMSIsIm5hbWUiOiJ1c2VyMSIsImlhdCI6MTUxNjIzOTAyMn0.1Q2JjNz
+ '400':
+ description: 'Invalid value for: body'
+ content:
+ text/plain:
+ schema:
+ type: string
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The searched entity was not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The searched entity was not found
+ '409':
+ description: Requesting a JWT token when no user pool service is configured
+ in the Gateway or requesting a token for an external service account.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: Requesting a JWT token when no user pool service is configured
+ in the Gateway or requesting a token for an external service account.
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-cdk-run-version: '1'
+ x-cdk-run-name: generateServiceAccountToken
+ x-cdk-run-doc: Generate a token for a service account on a virtual cluster
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request POST \
+ --url 'http://localhost:8888/gateway/v2/token' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{"vCluster":"vcluster1","username":"user1","lifeTimeSeconds":3600000}'
+ /gateway/v2/virtual-cluster:
+ get:
+ tags:
+ - cli_virtual-cluster_gateway_v2_7
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the virtual clusters
+
+ operationId: List the virtual clusters
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ uniqueItems: true
+ items:
+ $ref: '#/components/schemas/VirtualCluster'
+ example:
+ - kind: VirtualCluster
+ apiVersion: gateway/v2
+ metadata:
+ name: vcluster1
+ spec:
+ aclEnabled: false
+ superUsers:
+ - username1
+ - username2
+ type: Standard
+ bootstrapServers: kafka:9092
+ clientProperties:
+ security.protocol: SASL_PLAINTEXT
+ sasl.mechanism: PLAIN
+ sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule
+ required username={{username}} password={{password}};
+ '400':
+ description: Virtual cluster is not supported on security protocol PLAINTEXT
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: Virtual cluster is not supported on security protocol PLAINTEXT
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/virtual-cluster' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_virtual-cluster_gateway_v2_7
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert a virtual cluster
+
+ operationId: Upsert a virtual cluster
+ parameters:
+ - name: dryMode
+ in: query
+ description: If true, the operation will be simulated and no changes will
+ be made
+ required: false
+ schema:
+ default: false
+ type: boolean
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/VirtualCluster'
+ example:
+ kind: VirtualCluster
+ apiVersion: gateway/v2
+ metadata:
+ name: vcluster1
+ spec:
+ aclEnabled: false
+ superUsers:
+ - username1
+ - username2
+ type: Standard
+ bootstrapServers: kafka:9092
+ clientProperties:
+ security.protocol: SASL_PLAINTEXT
+ sasl.mechanism: PLAIN
+ sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule
+ required username={{username}} password={{password}};
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_VirtualCluster'
+ example:
+ resource:
+ kind: VirtualCluster
+ apiVersion: gateway/v2
+ metadata:
+ name: vcluster1
+ spec:
+ aclEnabled: false
+ superUsers:
+ - username1
+ - username2
+ type: Standard
+ bootstrapServers: kafka:9092
+ clientProperties:
+ security.protocol: SASL_PLAINTEXT
+ sasl.mechanism: PLAIN
+ sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule
+ required username={{username}} password={{password}};
+ upsertResult: UPDATED
+ '400':
+ description: Wrong format or usage of reserved keywords (e.g. passthrough)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: Wrong format or usage of reserved keywords (e.g. passthrough)
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '409':
+ description: The given prefix is already used by another virtual cluster
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: The given prefix is already used by another virtual cluster
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/virtual-cluster?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "VirtualCluster",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "vcluster1"
+ },
+ "spec" : {
+ "aclEnabled" : false,
+ "superUsers" : [
+ "username1",
+ "username2"
+ ],
+ "type" : "Standard",
+ "bootstrapServers" : "kafka:9092",
+ "clientProperties" : {
+ "security.protocol" : "SASL_PLAINTEXT",
+ "sasl.mechanism" : "PLAIN",
+ "sasl.jaas.config" : "org.apache.kafka.common.security.plain.PlainLoginModule required username={{username}} password={{password}};"
+ }
+ }
+ }'
+ /gateway/v2/virtual-cluster/{vCluster}:
+ get:
+ tags:
+ - cli_virtual-cluster_gateway_v2_7
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Get a virtual cluster
+
+ operationId: Get a virtual cluster
+ parameters:
+ - name: vCluster
+ in: path
+ description: The name of the virtual cluster
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/VirtualCluster'
+ example:
+ kind: VirtualCluster
+ apiVersion: gateway/v2
+ metadata:
+ name: vcluster1
+ spec:
+ aclEnabled: false
+ superUsers:
+ - username1
+ - username2
+ type: Standard
+ bootstrapServers: kafka:9092
+ clientProperties:
+ security.protocol: SASL_PLAINTEXT
+ sasl.mechanism: PLAIN
+ sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule
+ required username={{username}} password={{password}};
+ '400':
+ description: Virtual cluster is not supported on security protocol PLAINTEXT
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: Virtual cluster is not supported on security protocol PLAINTEXT
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/virtual-cluster/vcluster1' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ delete:
+ tags:
+ - cli_virtual-cluster_gateway_v2_7
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete a virtual cluster
+
+ operationId: Delete a virtual cluster
+ parameters:
+ - name: vCluster
+ in: path
+ description: The name of the virtual cluster
+ required: true
+ schema:
+ type: string
+ responses:
+ '204':
+ description: ''
+ '400':
+ description: Default `passthrough` virtual cluster cannot be deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: Default `passthrough` virtual cluster cannot be deleted
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '409':
+ description: The given virtual cluster has references (logical topics, interceptors,
+ concentration rules, service accounts) and cannot be deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: The given virtual cluster has references (logical topics, interceptors,
+ concentration rules, service accounts) and cannot be deleted
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/virtual-cluster/vcluster1' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ /gateway/v2/alias-topic:
+ get:
+ tags:
+ - cli_alias-topic_gateway_v2_8
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the alias topics of a virtual cluster
+
+ operationId: List the alias topics
+ parameters:
+ - name: vcluster
+ in: query
+ description: The virtual cluster filter
+ required: false
+ schema:
+ type: string
+ - name: name
+ in: query
+ description: The name filter
+ required: false
+ schema:
+ type: string
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/AliasTopic'
+ example:
+ - kind: AliasTopic
+ apiVersion: gateway/v2
+ metadata:
+ name: name1
+ vCluster: vCluster1
+ spec:
+ physicalName: physicalName1
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/alias-topic?showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_alias-topic_gateway_v2_8
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert an alias topic in a virtual cluster
+
+ operationId: Upsert an alias topic
+ parameters:
+ - name: dryMode
+ in: query
+ description: Whether to simulate the operation or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AliasTopic'
+ example:
+ kind: AliasTopic
+ apiVersion: gateway/v2
+ metadata:
+ name: name1
+ vCluster: vCluster1
+ spec:
+ physicalName: physicalName1
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_AliasTopic'
+ example:
+ resource:
+ kind: AliasTopic
+ apiVersion: gateway/v2
+ metadata:
+ name: name1
+ vCluster: vCluster1
+ spec:
+ physicalName: physicalName1
+ upsertResult: UPDATED
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '409':
+ description: |2
+
+ The virtual cluster is of type Standard and does not target main physical cluster
+ The virtual cluster is of type Partner and does not target a valid physical cluster
+ The physical cluster of an alias topic cannot be changed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: |2
+
+ The virtual cluster is of type Standard and does not target main physical cluster
+ The virtual cluster is of type Partner and does not target a valid physical cluster
+ The physical cluster of an alias topic cannot be changed
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/alias-topic?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "AliasTopic",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "name1",
+ "vCluster" : "vCluster1"
+ },
+ "spec" : {
+ "physicalName" : "physicalName1"
+ }
+ }'
+ delete:
+ tags:
+ - cli_alias-topic_gateway_v2_8
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete an alias topic in a virtual cluster
+
+ operationId: Delete an alias topic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AliasTopicId'
+ required: true
+ responses:
+ '204':
+ description: ''
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given name does not exist in the given virtual cluster
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given name does not exist in the given virtual cluster
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/alias-topic' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name" : "name1",
+ "vCluster" : "vCluster1"
+ }'
+ /gateway/v2/concentrated-topic:
+ get:
+ tags:
+ - cli_concentrated-topic_gateway_v2_0
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the concentrated topics of a vcluster
+
+ operationId: List the concentrated topics
+ parameters:
+ - name: vcluster
+ in: query
+ description: The virtual cluster filter
+ required: false
+ schema:
+ type: string
+ - name: name
+ in: query
+ description: The name filter
+ required: false
+ schema:
+ type: string
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ConcentratedTopic'
+ example:
+ - kind: ConcentratedTopic
+ apiVersion: gateway/v2
+ metadata:
+ name: name1
+ vCluster: vCluster1
+ spec:
+ physicalName: physicalName1
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/concentrated-topic?showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ /gateway/v2/concentration-rule:
+ get:
+ tags:
+ - cli_concentration-rule_gateway_v2_9
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the concentration rules of a vcluster
+
+ operationId: List the concentration rules
+ parameters:
+ - name: vcluster
+ in: query
+ description: The virtual cluster filter
+ required: false
+ schema:
+ type: string
+ - name: name
+ in: query
+ description: The name filter
+ required: false
+ schema:
+ type: string
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ConcentrationRule'
+ example:
+ - kind: ConcentrationRule
+ apiVersion: gateway/v2
+ metadata:
+ name: concentrationRule1
+ vCluster: vCluster1
+ spec:
+ pattern: topic.*
+ physicalTopics:
+ delete: topic
+ compact: compact_topic
+ deleteCompact: compact_delete_topic
+ autoManaged: false
+ offsetCorrectness: false
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/concentration-rule?showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_concentration-rule_gateway_v2_9
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert a concentration rule in a vcluster
+
+ operationId: Upsert a concentration rule
+ parameters:
+ - name: dryMode
+ in: query
+ description: Whether to simulate the operation or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ConcentrationRule'
+ example:
+ kind: ConcentrationRule
+ apiVersion: gateway/v2
+ metadata:
+ name: concentrationRule1
+ vCluster: vCluster1
+ spec:
+ pattern: topic.*
+ physicalTopics:
+ delete: topic
+ compact: compact_topic
+ deleteCompact: compact_delete_topic
+ autoManaged: false
+ offsetCorrectness: false
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_ConcentrationRule'
+ example:
+ resource:
+ kind: ConcentrationRule
+ apiVersion: gateway/v2
+ metadata:
+ name: concentrationRule1
+ vCluster: vCluster1
+ spec:
+ pattern: topic.*
+ physicalTopics:
+ delete: topic
+ compact: compact_topic
+ deleteCompact: compact_delete_topic
+ autoManaged: false
+ offsetCorrectness: false
+ upsertResult: CREATED
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given virtual cluster does not exist or one of the physical
+ topics does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given virtual cluster does not exist or one of the physical
+ topics does not exist
+ '409':
+ description: One of the physical topics exists with an incompatible cleanup.policy
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: One of the physical topics exists with an incompatible cleanup.policy
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/concentration-rule?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "ConcentrationRule",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "concentrationRule1",
+ "vCluster" : "vCluster1"
+ },
+ "spec" : {
+ "pattern" : "topic.*",
+ "physicalTopics" : {
+ "delete" : "topic",
+ "compact" : "compact_topic",
+ "deleteCompact" : "compact_delete_topic"
+ },
+ "autoManaged" : false,
+ "offsetCorrectness" : false
+ }
+ }'
+ delete:
+ tags:
+ - cli_concentration-rule_gateway_v2_9
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete a concentration rule in a vcluster
+
+ operationId: Delete a concentration rule
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ConcentrationRuleId'
+ example:
+ name: concentrationRule1
+ vCluster: vCluster1
+ required: true
+ responses:
+ '204':
+ description: ''
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given name does not exist in the given virtual cluster
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given name does not exist in the given virtual cluster
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/concentration-rule' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name" : "concentrationRule1",
+ "vCluster" : "vCluster1"
+ }'
+ /gateway/v2/interceptor:
+ get:
+ tags:
+ - cli_interceptor_gateway_v2_12
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the interceptors
+
+ operationId: List the interceptors
+ parameters:
+ - name: name
+ in: query
+ description: Filter by name
+ required: false
+ schema:
+ type: string
+ - name: global
+ in: query
+ description: Keep only global interceptors
+ required: false
+ schema:
+ type: boolean
+ - name: vcluster
+ in: query
+ description: Filter by virtual cluster
+ required: false
+ schema:
+ type: string
+ - name: group
+ in: query
+ description: Filter by group
+ required: false
+ schema:
+ type: string
+ - name: username
+ in: query
+ description: Filter by service account
+ required: false
+ schema:
+ type: string
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ uniqueItems: true
+ items:
+ $ref: '#/components/schemas/Interceptor'
+ example:
+ - kind: Interceptor
+ apiVersion: gateway/v2
+ metadata:
+ name: yellow_cars_filter
+ scope:
+ vCluster: vCluster1
+ spec:
+ comment: Filter yellow cars
+ pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin
+ priority: 1
+ config:
+ virtualTopic: yellow_cars
+ statement: SELECT '$.type' as type, '$.price' as price FROM cars
+ WHERE '$.color' = 'yellow'
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/interceptor?name=interceptor-name&global=true&vcluster=passthrough&group=group1&username=user1' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_interceptor_gateway_v2_12
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert an interceptor
+
+ operationId: Upsert an interceptor
+ parameters:
+ - name: dryMode
+ in: query
+ description: Whether to simulate the operation or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Interceptor'
+ example:
+ kind: Interceptor
+ apiVersion: gateway/v2
+ metadata:
+ name: yellow_cars_filter
+ scope:
+ vCluster: vCluster1
+ spec:
+ comment: Filter yellow cars
+ pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin
+ priority: 1
+ config:
+ virtualTopic: yellow_cars
+ statement: SELECT '$.type' as type, '$.price' as price FROM cars
+ WHERE '$.color' = 'yellow'
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_Interceptor'
+ example:
+ resource:
+ kind: Interceptor
+ apiVersion: gateway/v2
+ metadata:
+ name: yellow_cars_filter
+ scope:
+ vCluster: vCluster1
+ spec:
+ comment: Filter yellow cars
+ pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin
+ priority: 1
+ config:
+ virtualTopic: yellow_cars
+ statement: SELECT '$.type' as type, '$.price' as price FROM
+ cars WHERE '$.color' = 'yellow'
+ upsertResult: CREATED
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The virtual cluster or the group specified in the scope does
+ not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The virtual cluster or the group specified in the scope does
+ not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/interceptor?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "Interceptor",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "yellow_cars_filter",
+ "scope" : {
+ "vCluster" : "vCluster1",
+ "group" : null,
+ "username" : null
+ }
+ },
+ "spec" : {
+ "comment" : "Filter yellow cars",
+ "pluginClass" : "io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin",
+ "priority" : 1,
+ "config" : {
+ "virtualTopic" : "yellow_cars",
+ "statement" : "SELECT \'$.type\' as type, \'$.price\' as price FROM cars WHERE \'$.color\' = \'yellow\'"
+ }
+ }
+ }'
+ /gateway/v2/interceptor/{name}:
+ delete:
+ tags:
+ - cli_interceptor_gateway_v2_12
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete an interceptor
+
+ operationId: Delete an interceptor
+ parameters:
+ - name: name
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InterceptorScope'
+ required: true
+ responses:
+ '204':
+ description: ''
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given interceptor does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given interceptor does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/interceptor/yellow_cars_filter' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "vCluster" : "vCluster1",
+ "group" : null,
+ "username" : null
+ }'
+ /gateway/v2/interceptor/resolve:
+ post:
+ tags:
+ - cli_interceptor_gateway_v2_12
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ A utility endpoint to resolve the interceptors for a given virtual cluster, groups and username.
+ Helps to understand which interceptors will be applied for a given request.
+
+ operationId: Resolve interceptors
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InterceptorResolverRequest'
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ uniqueItems: true
+ items:
+ $ref: '#/components/schemas/Interceptor'
+ example:
+ - kind: Interceptor
+ apiVersion: gateway/v2
+ metadata:
+ name: yellow_cars_filter
+ scope:
+ vCluster: vCluster1
+ spec:
+ comment: Filter yellow cars
+ pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin
+ priority: 1
+ config:
+ virtualTopic: yellow_cars
+ statement: SELECT '$.type' as type, '$.price' as price FROM cars
+ WHERE '$.color' = 'yellow'
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request POST \
+ --url 'http://localhost:8888/gateway/v2/interceptor/resolve' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "vCluster" : "passthrough",
+ "groups" : [
+ "group1",
+ "group2"
+ ],
+ "username" : "user1"
+ }'
+ /gateway/v2/plugin:
+ get:
+ tags:
+ - plugin
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the available plugins of the gateway
+
+ operationId: List the Plugins of the Gateway
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ uniqueItems: true
+ items:
+ $ref: '#/components/schemas/Plugin'
+ example:
+ - plugin: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin
+ pluginId: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin
+ readme: |2+
+
+ ---
+ version: ${project.version}
+ title: Simulate Slow Producers and Consumers
+ description: Validate your application behaves correctly when there are delays in responses from the Kafka cluster.
+ parent: console
+ license: enterprise
+ ---
+
+ ## Introduction
+
+ This interceptor slows responses from the brokers.
+
+ It will operate only on a set of topics rather than all traffic.
+
+ This interceptor only works on Produce requests and Fetch requests.
+
+ ## Configuration
+
+ | key | type | default | description |
+ |:--------------|:--------|:--------|:----------------------------------------------------------------|
+ | topic | String | `.*` | Topics that match this regex will have the interceptor applied. |
+ | rateInPercent | int | | The percentage of requests that will apply this interceptor |
+ | minLatencyMs | int | | Minimum for the random response latency in milliseconds |
+ | maxLatencyMs | int | | Maximum for the random response latency in milliseconds |
+
+ ## Example
+
+ ```json
+ {
+ "name": "mySimulateSlowProducersConsumersInterceptor",
+ "pluginClass": "io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin",
+ "priority": 100,
+ "config": {
+ "rateInPercent": 100,
+ "minLatencyMs": 50,
+ "maxLatencyMs": 1200
+ }
+ }
+ ```
+
+ parent: Console
+ license: enterprise
+ description: Validate your application behaves correctly when broker
+ errors occur.
+ title: Broker errors
+ version: 3.0.1
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/plugin' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ /gateway/v2/service-account:
+ get:
+ tags:
+ - cli_gateway-service-account_gateway_v2_10
+ description: |2+
+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the service accounts
+
+ operationId: List the service accounts
+ parameters:
+ - name: vcluster
+ in: query
+ description: Filter by virtual cluster
+ required: false
+ schema:
+ type: string
+ - name: name
+ in: query
+ description: Filter by name
+ required: false
+ schema:
+ type: string
+ - name: type
+ in: query
+ description: Filter by type (External or Local)
+ required: false
+ schema:
+ type: string
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/GatewayServiceAccount'
+ example:
+ - kind: GatewayServiceAccount
+ apiVersion: gateway/v2
+ metadata:
+ name: user1
+ vCluster: vcluster1
+ spec:
+ type: EXTERNAL
+ externalNames:
+ - externalName
+ - kind: GatewayServiceAccount
+ apiVersion: gateway/v2
+ metadata:
+ name: user1
+ vCluster: vcluster1
+ spec:
+ type: LOCAL
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/service-account?vcluster=vCluster1&name=user1&type=External&showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_gateway-service-account_gateway_v2_10
+ description: |2+
+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert a service account
+
+ operationId: Upsert a service account
+ parameters:
+ - name: dryMode
+ in: query
+ description: Whether to simulate the operation or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GatewayServiceAccount'
+ example:
+ kind: GatewayServiceAccount
+ apiVersion: gateway/v2
+ metadata:
+ name: user1
+ vCluster: vcluster1
+ spec:
+ type: EXTERNAL
+ externalNames:
+ - externalName
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_GatewayServiceAccount'
+ example:
+ resource:
+ kind: GatewayServiceAccount
+ apiVersion: gateway/v2
+ metadata:
+ name: user1
+ vCluster: vcluster1
+ spec:
+ type: EXTERNAL
+ externalNames:
+ - externalName
+ upsertResult: CREATED
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given service account references a non-existing virtual
+ cluster
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given service account references a non-existing virtual
+ cluster
+ '409':
+ description: The service account already exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: The service account already exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/service-account?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "GatewayServiceAccount",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "user1",
+ "vCluster" : "vcluster1"
+ },
+ "spec" : {
+ "type" : "EXTERNAL",
+ "externalNames" : [
+ "externalName"
+ ]
+ }
+ }'
+ delete:
+ tags:
+ - cli_gateway-service-account_gateway_v2_10
+ description: |2+
+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete a service account
+
+ operationId: Delete a service account
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GatewayServiceAccountId'
+ required: true
+ responses:
+ '204':
+ description: ''
+ '400':
+ description: Gateway service account is not supported on security protocol
+ PLAINTEXT.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: Gateway service account is not supported on security protocol
+ PLAINTEXT.
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given service account does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given service account does not exist
+ '409':
+ description: The service account is still used by groups
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: The service account is still used by groups
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/service-account' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name" : "user1"
+ }'
+ /gateway/v2/group:
+ get:
+ tags:
+ - cli_gateway-group_gateway_v2_11
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ List the groups
+
+ operationId: List the groups
+ parameters:
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/GatewayGroup'
+ example:
+ - kind: GatewayGroup
+ apiVersion: gateway/v2
+ metadata:
+ name: group1
+ spec:
+ members:
+ - vCluster: vCluster1
+ name: serviceAccount1
+ - vCluster: vCluster2
+ name: serviceAccount2
+ - vCluster: vCluster3
+ name: serviceAccount3
+ externalGroups:
+ - GROUP_READER
+ - GROUP_WRITER
+ '400':
+ description: 'Invalid value for: query parameter showDefaults'
+ content:
+ text/plain:
+ schema:
+ type: string
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/group?showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ put:
+ tags:
+ - cli_gateway-group_gateway_v2_11
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Upsert a group
+
+ operationId: Upsert a group
+ parameters:
+ - name: dryMode
+ in: query
+ description: Whether to simulate the operation or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GatewayGroup'
+ example:
+ kind: GatewayGroup
+ apiVersion: gateway/v2
+ metadata:
+ name: group1
+ spec:
+ members:
+ - vCluster: vCluster1
+ name: serviceAccount1
+ - vCluster: vCluster2
+ name: serviceAccount2
+ - vCluster: vCluster3
+ name: serviceAccount3
+ externalGroups:
+ - GROUP_READER
+ - GROUP_WRITER
+ required: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApplyResult_GatewayGroup'
+ example:
+ resource:
+ kind: GatewayGroup
+ apiVersion: gateway/v2
+ metadata:
+ name: group1
+ spec:
+ members:
+ - vCluster: vCluster1
+ name: serviceAccount1
+ - vCluster: vCluster2
+ name: serviceAccount2
+ - vCluster: vCluster3
+ name: serviceAccount3
+ externalGroups:
+ - GROUP_READER
+ - GROUP_WRITER
+ upsertResult: UPDATED
+ '400':
+ description: The request is not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BadRequest'
+ example:
+ title: The request is not valid
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The group contains a service account that does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The group contains a service account that does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request PUT \
+ --url 'http://localhost:8888/gateway/v2/group?dryMode=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "kind" : "GatewayGroup",
+ "apiVersion" : "gateway/v2",
+ "metadata" : {
+ "name" : "group1"
+ },
+ "spec" : {
+ "members" : [
+ {
+ "vCluster" : "vCluster1",
+ "name" : "serviceAccount1"
+ },
+ {
+ "vCluster" : "vCluster2",
+ "name" : "serviceAccount2"
+ },
+ {
+ "vCluster" : "vCluster3",
+ "name" : "serviceAccount3"
+ }
+ ],
+ "externalGroups" : [
+ "GROUP_READER",
+ "GROUP_WRITER"
+ ]
+ }
+ }'
+ /gateway/v2/group/{name}:
+ get:
+ tags:
+ - cli_gateway-group_gateway_v2_11
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Get a group
+
+ operationId: Get a group
+ parameters:
+ - name: name
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: showDefaults
+ in: query
+ description: Whether to show default values or not
+ required: false
+ schema:
+ default: false
+ type: boolean
+ example: true
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GatewayGroup'
+ example:
+ kind: GatewayGroup
+ apiVersion: gateway/v2
+ metadata:
+ name: group1
+ spec:
+ members:
+ - vCluster: vCluster1
+ name: serviceAccount1
+ - vCluster: vCluster2
+ name: serviceAccount2
+ - vCluster: vCluster3
+ name: serviceAccount3
+ externalGroups:
+ - GROUP_READER
+ - GROUP_WRITER
+ '400':
+ description: 'Invalid value for: query parameter showDefaults'
+ content:
+ text/plain:
+ schema:
+ type: string
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given group does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given group does not exist
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request GET \
+ --url 'http://localhost:8888/gateway/v2/group/group1?showDefaults=false' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+ delete:
+ tags:
+ - cli_gateway-group_gateway_v2_11
+ description: |2+
+
+ [![Beta](https://img.shields.io/badge/Lifecycle-Beta-orange)](#tag/Versioning)
+
+ Delete a group
+
+ operationId: Delete a group
+ parameters:
+ - name: name
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '204':
+ description: ''
+ '401':
+ description: The given credentials are not valid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unauthorized'
+ example:
+ title: The given credentials are not valid
+ '404':
+ description: The given group does not exist
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFound'
+ example:
+ title: The given group does not exist
+ '409':
+ description: The group is still referenced by interceptors
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Conflict'
+ example:
+ title: The group is still referenced by interceptors
+ '500':
+ description: An unexpected error occurred in the server
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ServerError'
+ example:
+ title: An unexpected error occurred in the server
+ security:
+ - httpAuth: []
+ x-codeSamples:
+ - lang: Shell
+ source: |-
+ curl \
+ --request DELETE \
+ --url 'http://localhost:8888/gateway/v2/group/group1' \
+ --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y'
+components:
+ schemas:
+ AliasTopic:
+ title: AliasTopic
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the alias topic
+ type: string
+ apiVersion:
+ description: The api version of the alias topic
+ type: string
+ metadata:
+ $ref: '#/components/schemas/AliasTopicMetadata'
+ spec:
+ $ref: '#/components/schemas/AliasTopicSpec'
+ AliasTopicId:
+ title: AliasTopicId
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the alias topic
+ type: string
+ vCluster:
+ description: 'The virtual cluster of the alias topic (default: `passthrough`)'
+ type: string
+ AliasTopicMetadata:
+ title: AliasTopicMetadata
+ description: The metadata of the alias topic
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the alias topic
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ vCluster:
+ description: 'The virtual cluster of the alias topic (default: `passthrough`)'
+ type: string
+ format: ^[a-zA-Z0-9_-]+$
+ AliasTopicSpec:
+ title: AliasTopicSpec
+ description: The specification of the alias topic
+ type: object
+ required:
+ - physicalName
+ properties:
+ physicalName:
+ description: The physical name of the alias topic
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ physicalCluster:
+ description: |2
+
+ The physical kafka cluster hosting the physical topic.
+ The field is optional and only useful for alias topics referencing __Partner__ virtual clusters.
+ For alias topics linked to virtual clusters of type __Standard__, the physical cluster can only be "main" (automatically set to "main" if the field is missing).
+ The physical cluster must be one of the configured list of physical clusters of the gateway.
+ type: string
+ ApplyResult_AliasTopic:
+ title: ApplyResult_AliasTopic
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/AliasTopic'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ ApplyResult_ConcentrationRule:
+ title: ApplyResult_ConcentrationRule
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/ConcentrationRule'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ ApplyResult_GatewayGroup:
+ title: ApplyResult_GatewayGroup
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/GatewayGroup'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ ApplyResult_GatewayServiceAccount:
+ title: ApplyResult_GatewayServiceAccount
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/GatewayServiceAccount'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ ApplyResult_Interceptor:
+ title: ApplyResult_Interceptor
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/Interceptor'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ ApplyResult_VirtualCluster:
+ title: ApplyResult_VirtualCluster
+ type: object
+ required:
+ - resource
+ - upsertResult
+ properties:
+ resource:
+ $ref: '#/components/schemas/VirtualCluster'
+ description: The resource that was upserted
+ upsertResult:
+ $ref: '#/components/schemas/UpsertResult'
+ BadRequest:
+ title: BadRequest
+ type: object
+ required:
+ - title
+ properties:
+ title:
+ type: string
+ msg:
+ type: string
+ cause:
+ type: string
+ ConcentratedTopic:
+ title: ConcentratedTopic
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the concentrated topic
+ type: string
+ apiVersion:
+ description: The api version of the concentrated topic
+ type: string
+ metadata:
+ $ref: '#/components/schemas/ConcentratedTopicMetadata'
+ spec:
+ $ref: '#/components/schemas/ConcentratedTopicSpec'
+ ConcentratedTopicMetadata:
+ title: ConcentratedTopicMetadata
+ description: The metadata of the concentrated topic
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the concentrated topic
+ type: string
+ vCluster:
+ description: The virtual cluster of the concentrated topic. If not provided,
+ defaulted to passthrough virtual cluster.
+ type: string
+ ConcentratedTopicSpec:
+ title: ConcentratedTopicSpec
+ description: The specification of the concentrated topic
+ type: object
+ required:
+ - physicalName
+ properties:
+ physicalName:
+ description: The physical name of the concentrated topic
+ type: string
+ ConcentrationRule:
+ title: ConcentrationRule
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the concentration rule
+ type: string
+ apiVersion:
+ description: The api version of the concentration rule
+ type: string
+ metadata:
+ $ref: '#/components/schemas/ConcentrationRuleMetadata'
+ spec:
+ $ref: '#/components/schemas/ConcentrationRuleSpec'
+ ConcentrationRuleId:
+ title: ConcentrationRuleId
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the concentration rule (identifier in a vCluster)
+ type: string
+ vCluster:
+ description: The virtual cluster of the concentration rule. Default to `passthrough`
+ if not provided.
+ type: string
+ ConcentrationRuleMetadata:
+ title: ConcentrationRuleMetadata
+ description: The metadata of the concentration rule
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the concentration rule (identifier in a vCluster)
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ vCluster:
+ description: The virtual cluster of the concentration rule. Default to `passthrough`
+ if not provided.
+ type: string
+ ConcentrationRuleSpec:
+ title: ConcentrationRuleSpec
+ description: The specification of the concentration rule
+ type: object
+ required:
+ - pattern
+ - physicalTopics
+ properties:
+ pattern:
+ description: The pattern of the concentration rule
+ type: string
+ physicalTopics:
+ $ref: '#/components/schemas/PhysicalTopics'
+ autoManaged:
+ description: Whether the concentration rule is auto managed
+ type: boolean
+ offsetCorrectness:
+ description: |2
+
+ Set the offset management on/off for the logical topics created with this rule (default to false).
+ Setting it on can have some impacts on the performances and the memory usage.
+ type: boolean
+ Conflict:
+ title: Conflict
+ type: object
+ required:
+ - title
+ properties:
+ title:
+ type: string
+ msg:
+ type: string
+ cause:
+ type: string
+ Created:
+ title: Created
+ type: object
+ External:
+ title: External
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the service account
+ type: string
+ apiVersion:
+ description: The api version of the service account
+ type: string
+ metadata:
+ $ref: '#/components/schemas/ExternalMetadata'
+ spec:
+ $ref: '#/components/schemas/ExternalSpec'
+ ExternalMetadata:
+ title: ExternalMetadata
+ description: Metadata of the service account
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the service account (identifier)
+ type: string
+ format: ^[a-zA-Z0-9_-]{3,64}$
+ vCluster:
+ description: |2
+
+ The name of the virtual cluster the service account belongs to.
+
+ If not provided, the service account will be created in the default `passthrough` virtual cluster.
+ type: string
+ format: ^[a-zA-Z0-9_-]+$
+ ExternalSpec:
+ title: ExternalSpec
+ description: Spec of the service account
+ type: object
+ required:
+ - type
+ properties:
+ externalNames:
+ description: |2
+
+ List of the external names of the service account.
+ Used to keep a fixed reference of the service account in interceptors or groups if the values of the external user DB happen to change
+ (ex: OIDC principal, key in delegated auth mode with Confluent etc...)
+ At the moment, an external service account should have exactly one external name (The support for many external names will be available soon)
+ type: array
+ items:
+ type: string
+ type:
+ description: 'The type of the service account : `LOCAL` or `EXTERNAL` (case
+ insensitive)'
+ type: string
+ GatewayGroup:
+ title: GatewayGroup
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the group
+ type: string
+ apiVersion:
+ description: The api version of the group
+ type: string
+ metadata:
+ $ref: '#/components/schemas/GroupMetadata'
+ spec:
+ $ref: '#/components/schemas/GroupSpec'
+ GatewayServiceAccount:
+ title: GatewayServiceAccount
+ oneOf:
+ - $ref: '#/components/schemas/External'
+ - $ref: '#/components/schemas/Local'
+ GatewayServiceAccountId:
+ title: GatewayServiceAccountId
+ type: object
+ required:
+ - name
+ properties:
+ vCluster:
+ description: |2
+
+ The name of the virtual cluster the service account belongs to.
+
+ If not provided, the service account will be created in the default `passthrough` virtual cluster.
+ type: string
+ name:
+ description: The name of the service account (identifier)
+ type: string
+ GroupMetadata:
+ title: GroupMetadata
+ description: The metadata of the group
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the group
+ type: string
+ format: ^[a-zA-Z0-9_-]{1,100}$
+ GroupSpec:
+ title: GroupSpec
+ description: The specification of the group
+ type: object
+ properties:
+ members:
+ description: The service accounts belonging to the group
+ type: array
+ uniqueItems: true
+ items:
+ $ref: '#/components/schemas/GatewayServiceAccountId'
+ externalGroups:
+ description: The external groups (LDAP, OIDC...) mapped on the group
+ type: array
+ uniqueItems: true
+ items:
+ type: string
+ Interceptor:
+ title: Interceptor
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the interceptor
+ type: string
+ apiVersion:
+ description: The api version of the interceptor
+ type: string
+ metadata:
+ $ref: '#/components/schemas/InterceptorMetadata'
+ spec:
+ $ref: '#/components/schemas/InterceptorSpec'
+ InterceptorMetadata:
+ title: InterceptorMetadata
+ description: Metadata of the interceptor
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the interceptor
+ type: string
+ scope:
+ $ref: '#/components/schemas/InterceptorScope'
+ description: |2
+
+ The scope of the interceptor.
+ It can be applied to a specific virtual cluster or group or username.
+ If none of them is set, it will be applied Globally to the gateway.
+ InterceptorResolverRequest:
+ title: InterceptorResolverRequest
+ type: object
+ properties:
+ vCluster:
+ description: The virtual cluster to test the interceptors resolution
+ type: string
+ groups:
+ description: The groups to test the interceptors resolution
+ type: array
+ items:
+ type: string
+ username:
+ description: The username to test the interceptors resolution
+ type: string
+ InterceptorScope:
+ title: InterceptorScope
+ type: object
+ properties:
+ vCluster:
+ description: An optional vCluster to filter the interceptors
+ type: string
+ group:
+ description: An optional group to filter the interceptors
+ type: string
+ username:
+ description: An optional username to filter the interceptors
+ type: string
+ InterceptorSpec:
+ title: InterceptorSpec
+ description: Spec of the interceptor
+ type: object
+ required:
+ - pluginClass
+ - priority
+ - config
+ properties:
+ comment:
+ description: An optional comment for the interceptor
+ type: string
+ pluginClass:
+ description: The class of the plugin
+ type: string
+ priority:
+ description: The priority of the interceptor
+ type: integer
+ format: int32
+ config:
+ $ref: '#/components/schemas/Map_Json'
+ Local:
+ title: Local
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the service account
+ type: string
+ apiVersion:
+ description: The api version of the service account
+ type: string
+ metadata:
+ $ref: '#/components/schemas/LocalMetadata'
+ spec:
+ $ref: '#/components/schemas/LocalSpec'
+ LocalMetadata:
+ title: LocalMetadata
+ description: Metadata of the service account
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the service account (identifier)
+ type: string
+ format: ^[a-zA-Z0-9_-]{3,64}$
+ vCluster:
+ description: |2
+
+ The name of the virtual cluster the service account belongs to.
+
+ If not provided, the service account will be created in the default `passthrough` virtual cluster.
+ type: string
+ format: ^[a-zA-Z0-9_-]+$
+ LocalSpec:
+ title: LocalSpec
+ description: Spec of the service account
+ type: object
+ required:
+ - type
+ properties:
+ type:
+ description: 'The type of the service account : `LOCAL` or `EXTERNAL` (case
+ insensitive)'
+ type: string
+ Map_Json:
+ title: Map_Json
+ description: The configuration of the interceptor
+ type: object
+ additionalProperties: {}
+ Map_String:
+ title: Map_String
+ description: |2
+
+ The client properties to help create a connection to the virtual cluster.
+ This field is automatically managed by the gateway
+ Contains placeholders to replace with your actual values: {{username}}, {{password}}...
+ type: object
+ additionalProperties:
+ type: string
+ NotChanged:
+ title: NotChanged
+ type: object
+ NotFound:
+ title: NotFound
+ type: object
+ required:
+ - title
+ properties:
+ title:
+ type: string
+ msg:
+ type: string
+ cause:
+ type: string
+ PhysicalTopics:
+ title: PhysicalTopics
+ description: The physical topics backing the concentrated logical topics
+ type: object
+ required:
+ - delete
+ properties:
+ delete:
+ description: |2
+
+ The name of the physical topic to store the data of the concentrated topics created with a 'delete' policy.
+ The topic must exist in the physical kafka cluster with a 'delete' cleanup.policy (except if you use the autoManaged mode)
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ compact:
+ description: |2
+
+ The name of the physical topic to store the data of the concentrated topics created with a 'compact' policy.
+ If specified, the topic must exist in the physical kafka cluster with a 'compact' cleanup.policy (except if you use the autoManaged mode)
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ deleteCompact:
+ description: |2
+
+ The name of the physical topic to store the data of the concentrated topics created with a 'delete,compact' policy.
+ If specified, the topic must exist in the physical kafka cluster with a 'delete,compact' cleanup.policy (except if you use the autoManaged mode)
+ type: string
+ format: ^[a-zA-Z0-9._-]+$
+ Plugin:
+ title: Plugin
+ type: object
+ required:
+ - plugin
+ - pluginId
+ - readme
+ properties:
+ plugin:
+ description: The name of the plugin
+ type: string
+ pluginId:
+ description: The id of the plugin
+ type: string
+ readme:
+ description: The readme of the plugin
+ type: string
+ parent:
+ description: The parent of the plugin
+ type: string
+ license:
+ description: The license of the plugin
+ type: string
+ description:
+ description: The description of the plugin
+ type: string
+ title:
+ description: The title of the plugin
+ type: string
+ version:
+ description: The version of the plugin
+ type: string
+ ServerError:
+ title: ServerError
+ type: object
+ required:
+ - title
+ properties:
+ title:
+ type: string
+ msg:
+ type: string
+ cause:
+ type: string
+ TokenRequest:
+ title: TokenRequest
+ type: object
+ required:
+ - username
+ - lifeTimeSeconds
+ properties:
+ vCluster:
+ description: 'The name of the virtual cluster to create the token for. "passthrough
+ if omitted" '
+ type: string
+ username:
+ description: The username of the local service account to create the token
+ for.
+ type: string
+ lifeTimeSeconds:
+ description: The life time of the token in seconds.
+ type: integer
+ format: int64
+ TokenResponse:
+ title: TokenResponse
+ type: object
+ required:
+ - token
+ properties:
+ token:
+ description: The token created for the given username on the given vcluster.
+ type: string
+ Unauthorized:
+ title: Unauthorized
+ type: object
+ required:
+ - title
+ properties:
+ title:
+ type: string
+ msg:
+ type: string
+ cause:
+ type: string
+ Updated:
+ title: Updated
+ type: object
+ UpsertResult:
+ title: UpsertResult
+ description: The result of the upsert operation (created, updated, not changed)
+ oneOf:
+ - $ref: '#/components/schemas/Created'
+ - $ref: '#/components/schemas/NotChanged'
+ - $ref: '#/components/schemas/Updated'
+ VirtualCluster:
+ title: VirtualCluster
+ type: object
+ required:
+ - kind
+ - apiVersion
+ - metadata
+ - spec
+ properties:
+ kind:
+ description: The kind of the virtual cluster
+ type: string
+ apiVersion:
+ description: The api version of the virtual cluster
+ type: string
+ metadata:
+ $ref: '#/components/schemas/VirtualClusterMetadata'
+ spec:
+ $ref: '#/components/schemas/VirtualClusterSpec'
+ VirtualClusterMetadata:
+ title: VirtualClusterMetadata
+ description: Metadata of the virtual cluster
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ description: The name of the virtual cluster
+ type: string
+ format: ^[a-zA-Z0-9_-]+$
+ VirtualClusterSpec:
+ title: VirtualClusterSpec
+ description: Spec of the virtual cluster
+ type: object
+ properties:
+ aclEnabled:
+ description: Enable ACL for the virtual cluster
+ type: boolean
+ superUsers:
+ description: List of service account's username that are super users of
+ the virtual cluster
+ type: array
+ items:
+ type: string
+ type:
+ description: 'The type of the virtual cluster : Standard, Partner'
+ type: string
+ bootstrapServers:
+ description: |2
+
+ The bootstrap servers to create a connection to the virtual cluster.
+ This field is automatically managed by the gateway
+ type: string
+ clientProperties:
+ $ref: '#/components/schemas/Map_String'
+ securitySchemes:
+ httpAuth:
+ type: http
+ scheme: basic
+x-tagGroups:
+- name: 🐺 Conduktor Gateway API
+ tags:
+ - Introduction
+ - Authentication
+ - Kinds
+ - Api Groups
+ - Versioning
+ - Conventions
+- name: 🌉 gateway/v2
+ tags:
+ - cli_virtual-cluster_gateway_v2_7
+ - cli_alias-topic_gateway_v2_8
+ - cli_concentrated-topic_gateway_v2_0
+ - cli_concentration-rule_gateway_v2_9
+ - cli_interceptor_gateway_v2_12
+ - plugin
+ - cli_gateway-service-account_gateway_v2_10
+ - cli_gateway-group_gateway_v2_11
+ - token
diff --git a/test_final_exec.sh b/test_final_exec.sh
index 67abfef..028f233 100755
--- a/test_final_exec.sh
+++ b/test_final_exec.sh
@@ -49,6 +49,7 @@ main() {
run conduktor delete aliastopic aliastopicname --vcluster=v1
run conduktor delete concentrationrule cr1 --vcluster=v1
run conduktor delete gatewayserviceaccount s1 --vcluster=v1
+ run conduktor run partnerZoneGenerateCredentials --partner-zone-name yo
}
main "$@"