diff --git a/client/client.go b/client/client.go index 9037d62..e230eed 100644 --- a/client/client.go +++ b/client/client.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/conduktor/ctl/printutils" "github.com/conduktor/ctl/resource" + "github.com/conduktor/ctl/schema" "github.com/conduktor/ctl/utils" "github.com/go-resty/resty/v2" "os" @@ -16,10 +17,13 @@ type Client struct { token string baseUrl string client *resty.Client + kinds schema.KindCatalog } func Make(token string, baseUrl string, debug bool, key, cert string) (*Client, error) { - restyClient := resty.New().SetDebug(debug).SetHeader("Authorization", "Bearer "+token).SetHeader("X-CDK-CLIENT", "CLI/"+utils.GetConduktorVersion()) + //token is set later because it's not mandatory for getting the openapi and parsing different kind + restyClient := resty.New().SetDebug(debug).SetHeader("X-CDK-CLIENT", "CLI/"+utils.GetConduktorVersion()) + if (key == "" && cert != "") || (key != "" && cert == "") { return nil, fmt.Errorf("key and cert must be provided together") } else if key != "" && cert != "" { @@ -30,38 +34,47 @@ func Make(token string, baseUrl string, debug bool, key, cert string) (*Client, } } - return &Client{ + result := &Client{ token: token, baseUrl: baseUrl, client: restyClient, - }, nil -} + kinds: nil, + } -func MakeFromEnv() *Client { - token := os.Getenv("CDK_TOKEN") - if token == "" { - fmt.Fprintln(os.Stderr, "Please set CDK_TOKEN") - os.Exit(1) + if token != "" { + result.setTokenInRestClient() + } else { + //it will be set later only when really needed + //so aim is not fail when CDK_TOKEN is not set before printing the cmd help } + + err := result.initKindFromApi() + if err != nil { + fmt.Fprintf(os.Stderr, "Cannot init kinds from api: %s\nLet's switch to default from ctl binary\n", err) + result.kinds = schema.DefaultKind() + } + + return result, nil +} + +func MakeFromEnv() (*Client, error) { baseUrl := os.Getenv("CDK_BASE_URL") if baseUrl == "" { - fmt.Fprintln(os.Stderr, "Please set CDK_BASE_URL") - os.Exit(2) + return nil, fmt.Errorf("Please set CDK_BASE_URL") } debug := strings.ToLower(os.Getenv("CDK_DEBUG")) == "true" key := os.Getenv("CDK_KEY") cert := os.Getenv("CDK_CERT") - client, err := Make(token, baseUrl, debug, key, cert) + client, err := Make("", baseUrl, debug, key, cert) if err != nil { - fmt.Fprintf(os.Stderr, "Cannot create client: %s", err) - os.Exit(3) + return nil, fmt.Errorf("Cannot create client: %s", err) } insecure := strings.ToLower(os.Getenv("CDK_INSECURE")) == "true" if insecure { client.IgnoreUntrustedCertificate() } - return client + return client, nil } type UpsertResponse struct { @@ -72,6 +85,21 @@ func (c *Client) IgnoreUntrustedCertificate() { c.client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) } +func (c *Client) setTokenFromEnvIfNeeded() { + if c.token == "" { + token := os.Getenv("CDK_TOKEN") + if token == "" { + fmt.Fprintln(os.Stderr, "Please set CDK_TOKEN") + os.Exit(1) + } + c.token = token + c.setTokenInRestClient() + } +} + +func (c *Client) setTokenInRestClient() { + c.client = c.client.SetHeader("Authorization", "Bearer "+c.token) +} func extractApiError(resp *resty.Response) string { var apiError ApiError jsonError := json.Unmarshal(resp.Body(), &apiError) @@ -91,7 +119,17 @@ func (client *Client) ActivateDebug() { } func (client *Client) Apply(resource *resource.Resource, dryMode bool) (string, error) { - url := client.publicV1Url() + "/" + utils.UpperCamelToKebab(resource.Kind) + client.setTokenFromEnvIfNeeded() + kinds := client.GetKinds() + kind, ok := kinds[resource.Kind] + if !ok { + return "", fmt.Errorf("kind %s not found", resource.Kind) + } + applyPath, err := kind.ApplyPath(resource) + if err != nil { + return "", err + } + url := client.baseUrl + applyPath builder := client.client.R().SetBody(resource.Json) if dryMode { builder = builder.SetQueryParam("dryMode", "true") @@ -121,8 +159,9 @@ func printResponseAsYaml(bytes []byte) error { return printutils.PrintResourceLikeYamlFile(os.Stdout, data) } -func (client *Client) Get(kind string) error { - url := client.publicV1Url() + "/" + utils.UpperCamelToKebab(kind) +func (client *Client) Get(kind *schema.Kind, parentPathValue []string) error { + client.setTokenFromEnvIfNeeded() + url := client.baseUrl + kind.ListPath(parentPathValue) resp, err := client.client.R().Get(url) if err != nil { return err @@ -132,26 +171,28 @@ func (client *Client) Get(kind string) error { return printResponseAsYaml(resp.Body()) } -func (client *Client) Describe(kind, name string) error { - url := client.publicV1Url() + "/" + utils.UpperCamelToKebab(kind) + "/" + name +func (client *Client) Describe(kind *schema.Kind, parentPathValue []string, name string) error { + client.setTokenFromEnvIfNeeded() + url := client.baseUrl + kind.DescribePath(parentPathValue, name) resp, err := client.client.R().Get(url) if err != nil { return err } else if resp.IsError() { - return fmt.Errorf("error describing resources %s/%s, got status code: %d:\n %s", kind, name, resp.StatusCode(), string(resp.Body())) + return fmt.Errorf("error describing resources %s/%s, got status code: %d:\n %s", kind.GetName(), name, resp.StatusCode(), string(resp.Body())) } return printResponseAsYaml(resp.Body()) } -func (client *Client) Delete(kind, name string) error { - url := client.publicV1Url() + "/" + utils.UpperCamelToKebab(kind) + "/" + name +func (client *Client) Delete(kind *schema.Kind, parentPathValue []string, name string) error { + client.setTokenFromEnvIfNeeded() + url := client.baseUrl + kind.DescribePath(parentPathValue, name) resp, err := client.client.R().Delete(url) if err != nil { return err } else if resp.IsError() { return fmt.Errorf(extractApiError(resp)) } else { - fmt.Printf("%s/%s deleted\n", kind, name) + fmt.Printf("%s/%s deleted\n", kind.GetName(), name) } return err @@ -167,3 +208,24 @@ func (client *Client) GetOpenApi() ([]byte, error) { } return resp.Body(), nil } + +func (client *Client) initKindFromApi() error { + data, err := client.GetOpenApi() + if err != nil { + return fmt.Errorf("Cannot get openapi: %s", err) + } + schema, err := schema.New(data) + if err != nil { + return fmt.Errorf("Cannot parse openapi: %s", err) + } + strict := false + client.kinds, err = schema.GetKinds(strict) + if err != nil { + fmt.Errorf("Cannot extract kinds from openapi: %s", err) + } + return nil +} + +func (client *Client) GetKinds() schema.KindCatalog { + return client.kinds +} diff --git a/client/client_test.go b/client/client_test.go index 08e5af5..31a3910 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -15,6 +15,7 @@ func TestApplyShouldWork(t *testing.T) { if err != nil { panic(err) } + client.setTokenFromEnvIfNeeded() httpmock.ActivateNonDefault( client.client.GetClient(), ) @@ -24,12 +25,15 @@ func TestApplyShouldWork(t *testing.T) { Json: []byte(`{"yolo": "data"}`), Kind: "Topic", Name: "toto", - Version: "v1", + Version: "v2", + Metadata: map[string]interface{}{ + "cluster": "local", + }, } httpmock.RegisterMatcherResponderWithQuery( "PUT", - "http://baseUrl/public/v1/topic", + "http://baseUrl/public/kafka/v2/cluster/local/topic", nil, httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.HeaderIs("X-CDK-CLIENT", "CLI/unknown")). @@ -61,14 +65,14 @@ func TestApplyWithDryModeShouldWork(t *testing.T) { topic := resource.Resource{ Json: []byte(`{"yolo": "data"}`), - Kind: "Topic", + Kind: "Application", Name: "toto", Version: "v1", } httpmock.RegisterMatcherResponderWithQuery( "PUT", - "http://baseUrl/public/v1/topic", + "http://baseUrl/public/self-serve/v1/application", "dryMode=true", httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.BodyContainsBytes(topic.Json)), @@ -102,14 +106,14 @@ func TestApplyShouldFailIfNo2xx(t *testing.T) { topic := resource.Resource{ Json: []byte(`{"yolo": "data"}`), - Kind: "Topic", + Kind: "Application", Name: "toto", Version: "v1", } httpmock.RegisterMatcherResponderWithQuery( "PUT", - "http://baseUrl/public/v1/topic", + "http://baseUrl/public/self-serve/v1/application", nil, httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.BodyContainsBytes(topic.Json)), @@ -140,75 +144,15 @@ func TestGetShouldWork(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "GET", - "http://baseUrl/public/v1/application", + "http://baseUrl/public/self-serve/v1/application", nil, httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.HeaderIs("X-CDK-CLIENT", "CLI/unknown")), responder, ) - err = client.Get("Application") - if err != nil { - t.Error(err) - } -} - -func TestGetShouldApplyCaseTransformation(t *testing.T) { - defer httpmock.Reset() - baseUrl := "http://baseUrl" - token := "aToken" - client, err := Make(token, baseUrl, false, "", "") - if err != nil { - panic(err) - } - httpmock.ActivateNonDefault( - client.client.GetClient(), - ) - responder, err := httpmock.NewJsonResponder(200, "[]") - if err != nil { - panic(err) - } - - httpmock.RegisterMatcherResponderWithQuery( - "GET", - "http://baseUrl/public/v1/application-instance", - nil, - httpmock.HeaderIs("Authorization", "Bearer "+token), - responder, - ) - - err = client.Get("ApplicationInstance") - if err != nil { - t.Error(err) - } -} - -func TestGetShouldKeepCase(t *testing.T) { - defer httpmock.Reset() - baseUrl := "http://baseUrl" - token := "aToken" - client, err := Make(token, baseUrl, false, "", "") - if err != nil { - panic(err) - } - - httpmock.ActivateNonDefault( - client.client.GetClient(), - ) - responder, err := httpmock.NewJsonResponder(200, "[]") - if err != nil { - panic(err) - } - - httpmock.RegisterMatcherResponderWithQuery( - "GET", - "http://baseUrl/public/v1/application-instance", - nil, - httpmock.HeaderIs("Authorization", "Bearer "+token), - responder, - ) - - err = client.Get("application-instance") + app := client.GetKinds()["Application"] + err = client.Get(&app, []string{}) if err != nil { t.Error(err) } @@ -232,13 +176,14 @@ func TestGetShouldFailIfN2xx(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "GET", - "http://baseUrl/public/v1/application", + "http://baseUrl/public/self-serve/v1/application", nil, httpmock.HeaderIs("Authorization", "Bearer "+token), responder, ) - err = client.Get("Application") + app := client.GetKinds()["Application"] + err = client.Get(&app, []string{}) if err == nil { t.Failed() } @@ -262,14 +207,15 @@ func TestDescribeShouldWork(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "GET", - "http://baseUrl/public/v1/application/yo", + "http://baseUrl/public/self-serve/v1/application/yo", nil, httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.HeaderIs("X-CDK-CLIENT", "CLI/unknown")), responder, ) - err = client.Describe("Application", "yo") + app := client.GetKinds()["Application"] + err = client.Describe(&app, []string{}, "yo") if err != nil { t.Error(err) } @@ -293,13 +239,14 @@ func TestDescribeShouldFailIfNo2xx(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "GET", - "http://baseUrl/public/v1/application/yo", + "http://baseUrl/public/self-serve/v1/application/yo", nil, httpmock.HeaderIs("Authorization", "Bearer "+token), responder, ) - err = client.Describe("Application", "yo") + app := client.GetKinds()["Application"] + err = client.Describe(&app, []string{}, "yo") if err == nil { t.Failed() } @@ -323,14 +270,15 @@ func TestDeleteShouldWork(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "DELETE", - "http://baseUrl/public/v1/application/yo", + "http://baseUrl/public/self-serve/v1/application/yo", nil, httpmock.HeaderIs("Authorization", "Bearer "+token). And(httpmock.HeaderIs("X-CDK-CLIENT", "CLI/unknown")), responder, ) - err = client.Delete("Application", "yo") + app := client.GetKinds()["Application"] + err = client.Delete(&app, []string{}, "yo") if err != nil { t.Error(err) } @@ -353,13 +301,14 @@ func TestDeleteShouldFailOnNot2XX(t *testing.T) { httpmock.RegisterMatcherResponderWithQuery( "DELETE", - "http://baseUrl/public/v1/api/application/yo", + "http://baseUrl/public/self_serve/v1/api/application/yo", nil, httpmock.HeaderIs("Authorization", "Bearer "+token), responder, ) - err = client.Delete("Application", "yo") + app := client.GetKinds()["Application"] + err = client.Delete(&app, []string{}, "yo") if err == nil { t.Fail() } diff --git a/cmd/apply.go b/cmd/apply.go index f1b841e..4fe6ace 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -27,7 +27,7 @@ var applyCmd = &cobra.Command{ } var allSuccess = true for _, resource := range resources { - upsertResult, err := apiClient.Apply(&resource, *dryRun) + upsertResult, err := apiClient().Apply(&resource, *dryRun) if err != nil { fmt.Fprintf(os.Stderr, "Could not apply resource %s/%s: %s\n", resource.Kind, resource.Name, err) allSuccess = false diff --git a/cmd/delete.go b/cmd/delete.go index 94b40c7..d8d2d6c 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -2,8 +2,10 @@ package cmd import ( "fmt" + "github.com/conduktor/ctl/schema" "github.com/spf13/cobra" "os" + "strings" ) // applyCmd represents the apply command @@ -11,16 +13,41 @@ var deleteCmd = &cobra.Command{ Use: "delete", Short: "Delete resource of a given kind and name", Long: ``, - Args: cobra.ExactArgs(2), + Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - err := apiClient.Delete(args[0], args[1]) - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } + // Root command does nothing + cmd.Help() + os.Exit(1) }, } -func initDelete() { +func initDelete(kinds schema.KindCatalog) { rootCmd.AddCommand(deleteCmd) + + for name, kind := range kinds { + flags := kind.GetFlag() + parentFlagValue := make([]*string, len(flags)) + kindCmd := &cobra.Command{ + Use: fmt.Sprintf("%s [name]", name), + Short: "Delete resource of kind " + name, + Args: cobra.MatchAll(cobra.ExactArgs(1)), + Aliases: []string{strings.ToLower(name), strings.ToLower(name) + "s", name + "s"}, + Run: func(cmd *cobra.Command, args []string) { + parentValue := make([]string, len(parentFlagValue)) + for i, v := range parentFlagValue { + parentValue[i] = *v + } + err := apiClient().Delete(&kind, parentValue, args[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + }, + } + for i, flag := range kind.GetFlag() { + parentFlagValue[i] = kindCmd.Flags().String(flag, "", "Parent "+flag) + kindCmd.MarkFlagRequired(flag) + } + deleteCmd.AddCommand(kindCmd) + } } diff --git a/cmd/get.go b/cmd/get.go index d11e109..a6ce566 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -2,8 +2,10 @@ package cmd import ( "fmt" + "github.com/conduktor/ctl/schema" "github.com/spf13/cobra" "os" + "strings" ) var getCmd = &cobra.Command{ @@ -17,54 +19,28 @@ var getCmd = &cobra.Command{ }, } -var getCmdWhenNoSchema = &cobra.Command{ - Use: "get kind [name]", - Short: "Get resource of a given kind", - Long: `If name not provided it will list all resource. For example: -conduktor get application -will list all applications. Whereas: -conduktor get application myapp -will describe the application myapp`, - Args: cobra.MatchAll(cobra.MinimumNArgs(1), cobra.MaximumNArgs(2)), - Run: func(cmd *cobra.Command, args []string) { - var err error - if len(args) == 1 { - err = apiClient.Get(args[0]) - } else if len(args) == 2 { - err = apiClient.Describe(args[0], args[1]) - } - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } - }, -} - -func initGet() { - if schemaClient == nil { - rootCmd.AddCommand(getCmdWhenNoSchema) - return - } - tags, err := schemaClient.GetKind() - if err != nil { - fmt.Fprintf(os.Stderr, "Could not load kind from openapi: %s\n", err) - rootCmd.AddCommand(getCmdWhenNoSchema) - return - } +func initGet(kinds schema.KindCatalog) { rootCmd.AddCommand(getCmd) - for _, tag := range tags { - tagCmd := &cobra.Command{ - Use: fmt.Sprintf("%s [name]", tag), - Short: "Get resource of kind " + tag, - Args: cobra.MatchAll(cobra.MaximumNArgs(1)), - Long: `If name not provided it will list all resource`, + for name, kind := range kinds { + flags := kind.GetFlag() + parentFlagValue := make([]*string, len(flags)) + kindCmd := &cobra.Command{ + Use: fmt.Sprintf("%s [name]", name), + Short: "Get resource of kind " + name, + Args: cobra.MatchAll(cobra.MaximumNArgs(1)), + Long: `If name not provided it will list all resource`, + Aliases: []string{strings.ToLower(name), strings.ToLower(name) + "s", name + "s"}, Run: func(cmd *cobra.Command, args []string) { + parentValue := make([]string, len(parentFlagValue)) + for i, v := range parentFlagValue { + parentValue[i] = *v + } var err error if len(args) == 0 { - err = apiClient.Get(tag) + err = apiClient().Get(&kind, parentValue) } else if len(args) == 1 { - err = apiClient.Describe(tag, args[0]) + err = apiClient().Describe(&kind, parentValue, args[0]) } if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) @@ -72,6 +48,10 @@ func initGet() { } }, } - getCmd.AddCommand(tagCmd) + for i, flag := range kind.GetFlag() { + parentFlagValue[i] = kindCmd.Flags().String(flag, "", "Parent "+flag) + kindCmd.MarkFlagRequired(flag) + } + getCmd.AddCommand(kindCmd) } } diff --git a/cmd/mkKind.go b/cmd/mkKind.go new file mode 100644 index 0000000..90052dd --- /dev/null +++ b/cmd/mkKind.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "github.com/conduktor/ctl/schema" + "github.com/spf13/cobra" + "os" +) + +func initMkKind() { + 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", + Long: ``, + Args: cobra.RangeArgs(0, 1), + Hidden: true, + Run: func(cmd *cobra.Command, args []string) { + var kinds map[string]schema.Kind + if len(args) == 1 { + data, err := os.ReadFile(args[0]) + if err != nil { + panic(err) + } + schema, err := schema.New(data) + if err != nil { + panic(err) + } + kinds, err = schema.GetKinds(!*nonStrict) + if err != nil { + panic(err) + } + } else { + data, err := apiClient().GetOpenApi() + if err != nil { + panic(err) + } + schema, err := schema.New(data) + if err != nil { + panic(err) + } + kinds, err = schema.GetKinds(!*nonStrict) + if err != nil { + panic(err) + } + } + var payload []byte + var err error + if *prettyPrint { + payload, err = json.MarshalIndent(kinds, "", " ") + } else { + payload, err = json.Marshal(kinds) + } + if err != nil { + panic(err) + } + fmt.Print(string(payload)) + }, + } + rootCmd.AddCommand(makeKind) + + 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") +} diff --git a/cmd/printKind.go b/cmd/printKind.go new file mode 100644 index 0000000..c34962c --- /dev/null +++ b/cmd/printKind.go @@ -0,0 +1,38 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "github.com/conduktor/ctl/schema" + "github.com/spf13/cobra" +) + +func initPrintKind(kinds schema.KindCatalog) { + + var prettyPrint *bool + + var printKind = &cobra.Command{ + Use: "printKind", + Short: "Print kind catalog used", + Long: ``, + Args: cobra.NoArgs, + Hidden: true, + Run: func(cmd *cobra.Command, args []string) { + var payload []byte + var err error + if *prettyPrint { + payload, err = json.MarshalIndent(kinds, "", " ") + } else { + payload, err = json.Marshal(kinds) + } + if err != nil { + panic(err) + } + fmt.Print(string(payload)) + }, + } + + rootCmd.AddCommand(printKind) + + prettyPrint = printKind.Flags().BoolP("pretty", "p", false, "Pretty print the output") +} diff --git a/cmd/root.go b/cmd/root.go index 4eb0e76..8a47b10 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,3 @@ -/* -Copyright © 2024 NAME HERE -*/ package cmd import ( @@ -12,10 +9,16 @@ import ( ) var debug *bool -var key *string -var cert *string -var apiClient *client.Client -var schemaClient *schema.Schema = nil +var apiClient_ *client.Client +var apiClientError error + +func apiClient() *client.Client { + if apiClientError != nil { + fmt.Fprintf(os.Stderr, "Cannot create client: %s", apiClientError) + os.Exit(1) + } + return apiClient_ +} // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ @@ -26,7 +29,7 @@ You can also use the CDK_KEY,CDK_CERT instead of --key and --cert flags to use a If you have an untrusted certificate you can use the CDK_INSECURE=true variable to disable tls verification`, PersistentPreRun: func(cmd *cobra.Command, args []string) { if *debug { - apiClient.ActivateDebug() + apiClient().ActivateDebug() } }, Run: func(cmd *cobra.Command, args []string) { @@ -45,18 +48,17 @@ func Execute() { } func init() { - apiClient = client.MakeFromEnv() - openApi, err := apiClient.GetOpenApi() - if err == nil { - schemaClient, err = schema.New(openApi) - } - if err != nil { - fmt.Fprintf(os.Stderr, "Could not load server openapi: %s\n", err) + apiClient_, apiClientError = client.MakeFromEnv() + kinds := schema.KindCatalog{} + if apiClientError == nil { + kinds = apiClient_.GetKinds() + } else { + kinds = schema.DefaultKind() } debug = rootCmd.PersistentFlags().BoolP("verbose", "v", false, "show more information for debugging") - key = rootCmd.PersistentFlags().String("key", "", "set pem key for certificate authentication (useful for teleport)") - cert = rootCmd.PersistentFlags().String("cert", "", "set pem cert for certificate authentication (useful for teleport)") - initGet() - initDelete() + initGet(kinds) + initDelete(kinds) initApply() + initMkKind() + initPrintKind(kinds) } diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index e91f66b..287ce24 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: conduktor: build: diff --git a/docker/initializer.json b/docker/initializer.json index 29ef260..77d036a 100644 --- a/docker/initializer.json +++ b/docker/initializer.json @@ -2,7 +2,7 @@ { "httpRequest": { "method": "Put", - "path": "/public/v1/Topic", + "path": "/public/kafka/v2/cluster/my-cluster/topic", "headers": { "Authorization": "Bearer yo" } @@ -18,7 +18,7 @@ { "httpRequest": { "method": "Get", - "path": "/public/v1/Topic", + "path": "/public/kafka/v2/cluster/my-cluster/topic", "headers": { "Authorization": "Bearer yo" } @@ -34,7 +34,7 @@ { "httpRequest": { "method": "Get", - "path": "/public/v1/Topic/yolo", + "path": "/public/kafka/v2/cluster/my-cluster/topic/yolo", "headers": { "Authorization": "Bearer yo" } @@ -50,7 +50,7 @@ { "httpRequest": { "method": "Delete", - "path": "/public/v1/Topic/yolo", + "path": "/public/kafka/v2/cluster/my-cluster/topic/yolo", "headers": { "Authorization": "Bearer yo" } diff --git a/docker/test_resource.yml b/docker/test_resource.yml index 56d5811..8d5b075 100644 --- a/docker/test_resource.yml +++ b/docker/test_resource.yml @@ -1,9 +1,10 @@ # topics.yml --- -apiVersion: v1 +apiVersion: v2 kind: Topic metadata: name: abcd.topic + cluster: my-cluster spec: replicationFactor: 1 partitions: 3 @@ -12,10 +13,11 @@ spec: cleanup.policy: delete retention.ms: 604800000 --- -apiVersion: v1 +apiVersion: v2 kind: Topic metadata: name: abcd.myTopicWrong + cluster: my-cluster spec: replicationFactor: 1 partitions: 3 diff --git a/go.mod b/go.mod index cc9fe67..115c99a 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/conduktor/ctl go 1.22.0 require ( + github.com/davecgh/go-spew v1.1.1 github.com/ghodss/yaml v1.0.0 github.com/go-resty/resty/v2 v2.11.0 github.com/jarcoal/httpmock v1.3.1 diff --git a/resource/resource.go b/resource/resource.go index 28d9dbe..e108607 100644 --- a/resource/resource.go +++ b/resource/resource.go @@ -14,24 +14,25 @@ import ( ) type Resource struct { - Json []byte - Kind string - Name string - Version string + Json []byte + Kind string + Name string + Version string + Metadata map[string]interface{} `json:"-"` } func (r Resource) String() string { return fmt.Sprintf(`version: %s, kind: %s, name: %s, json: '%s'`, r.Version, r.Kind, r.Name, string(r.Json)) } -type yamlRoot struct { - Version string - Kind string - Metadata metadata +func (r Resource) StringFromMetadata(key string) (string, error) { + return extractKeyFromMetadataMap(r.Metadata, key) } -type metadata struct { - Name string +type yamlRoot struct { + ApiVersion string + Kind string + Metadata map[string]interface{} } func FromFile(path string) ([]Resource, error) { @@ -87,17 +88,33 @@ func FromByte(data []byte) ([]Resource, error) { return results, nil } +func extractKeyFromMetadataMap(m map[string]interface{}, key string) (string, error) { + if val, ok := m[key]; ok { + if str, ok := val.(string); ok { + return str, nil + } + return "", fmt.Errorf("key %s in metadata is not a string", key) + } + return "", fmt.Errorf("key %s not found in metadata", key) + +} + func yamlByteToResource(data []byte) (Resource, error) { jsonByte, err := yamlJson.YAMLToJSON(data) if err != nil { - return Resource{}, nil + return Resource{}, err } var yamlRoot yamlRoot err = json.Unmarshal(jsonByte, &yamlRoot) if err != nil { - return Resource{}, nil + return Resource{}, err + } + + name, err := extractKeyFromMetadataMap(yamlRoot.Metadata, "name") + if err != nil { + return Resource{}, err } - return Resource{Json: jsonByte, Kind: yamlRoot.Kind, Name: yamlRoot.Metadata.Name, Version: yamlRoot.Version}, nil + return Resource{Json: jsonByte, Kind: yamlRoot.Kind, Name: name, Version: yamlRoot.ApiVersion, Metadata: yamlRoot.Metadata}, nil } diff --git a/resource/resource_test.go b/resource/resource_test.go index 92332d0..3b97093 100644 --- a/resource/resource_test.go +++ b/resource/resource_test.go @@ -1,6 +1,7 @@ package resource import ( + "github.com/davecgh/go-spew/spew" "testing" ) @@ -26,20 +27,21 @@ func TestFromByteForOneResourceWithValidResource(t *testing.T) { yamlByte := []byte(` # comment --- -version: v1 +apiVersion: v1 kind: Topic metadata: name: abc.myTopic spec: replicationFactor: 1 --- -version: v2 +apiVersion: v2 kind: ConsumerGroup metadata: name: cg1 `) results, err := FromByte(yamlByte) + spew.Dump(results) if err != nil { t.Error(err) } @@ -48,17 +50,19 @@ metadata: } checkResource(t, results[0], Resource{ - Version: "v1", - Kind: "Topic", - Name: "abc.myTopic", - Json: []byte(`{"kind":"Topic","metadata":{"name":"abc.myTopic"},"spec":{"replicationFactor":1},"version":"v1"}`), + Version: "v1", + Kind: "Topic", + Name: "abc.myTopic", + Metadata: map[string]interface{}{"name": "abc.myTopic"}, + Json: []byte(`{"apiVersion":"v1","kind":"Topic","metadata":{"name":"abc.myTopic"},"spec":{"replicationFactor":1}}`), }) checkResource(t, results[1], Resource{ - Version: "v2", - Kind: "ConsumerGroup", - Name: "cg1", - Json: []byte(`{"kind":"ConsumerGroup","metadata":{"name":"cg1"},"version":"v2"}`), + Version: "v2", + Kind: "ConsumerGroup", + Name: "cg1", + Metadata: map[string]interface{}{"name": "cg1"}, + Json: []byte(`{"apiVersion":"v2","kind":"ConsumerGroup","metadata":{"name":"cg1"}}`), }) } @@ -72,30 +76,34 @@ func TestFromFolder(t *testing.T) { } checkResource(t, resources[0], Resource{ - Version: "v1", - Kind: "a", - Name: "a", - Json: []byte(`{"kind":"a","metadata":{"name":"a"},"spec":{"data":"data"},"version":"v1"}`), + Version: "v1", + Kind: "a", + Name: "a", + Metadata: map[string]interface{}{"name": "a"}, + Json: []byte(`{"apiVersion":"v1","kind":"a","metadata":{"name":"a"},"spec":{"data":"data"}}`), }) checkResource(t, resources[1], Resource{ - Version: "v1", - Kind: "a", - Name: "b", - Json: []byte(`{"kind":"a","metadata":{"name":"b"},"spec":{"data":"data2"},"version":"v1"}`), + Version: "v1", + Kind: "a", + Name: "b", + Metadata: map[string]interface{}{"name": "b"}, + Json: []byte(`{"apiVersion":"v1","kind":"a","metadata":{"name":"b"},"spec":{"data":"data2"}}`), }) checkResource(t, resources[2], Resource{ - Version: "v1", - Kind: "b", - Name: "a", - Json: []byte(`{"kind":"b","metadata":{"name":"a"},"spec":{"data":"yo"},"version":"v1"}`), + Version: "v1", + Kind: "b", + Name: "a", + Metadata: map[string]interface{}{"name": "a"}, + Json: []byte(`{"apiVersion":"v1","kind":"b","metadata":{"name":"a"},"spec":{"data":"yo"}}`), }) checkResource(t, resources[3], Resource{ - Version: "v1", - Kind: "b", - Name: "b", - Json: []byte(`{"kind":"b","metadata":{"name":"b"},"spec":{"data":"lo"},"version":"v1"}`), + Version: "v1", + Kind: "b", + Name: "b", + Metadata: map[string]interface{}{"name": "b"}, + Json: []byte(`{"apiVersion":"v1","kind":"b","metadata":{"name":"b"},"spec":{"data":"lo"}}`), }) } diff --git a/resource/yamls/a.yml b/resource/yamls/a.yml index 9cf0209..a675168 100644 --- a/resource/yamls/a.yml +++ b/resource/yamls/a.yml @@ -1,12 +1,12 @@ --- -version: v1 +apiVersion: v1 kind: a metadata: name: a spec: data: data --- -version: v1 +apiVersion: v1 kind: a metadata: name: b diff --git a/resource/yamls/b.yaml b/resource/yamls/b.yaml index c638556..7a6657e 100644 --- a/resource/yamls/b.yaml +++ b/resource/yamls/b.yaml @@ -1,12 +1,12 @@ --- -version: v1 +apiVersion: v1 kind: b metadata: name: a spec: data: yo --- -version: v1 +apiVersion: v1 kind: b metadata: name: b diff --git a/schema/default-schema.json b/schema/default-schema.json new file mode 100644 index 0000000..26c75f9 --- /dev/null +++ b/schema/default-schema.json @@ -0,0 +1 @@ +{"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[]}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[]}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[]}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"]}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[]}}}} \ No newline at end of file diff --git a/schema/docs.yaml b/schema/docs.yaml new file mode 100644 index 0000000..732359b --- /dev/null +++ b/schema/docs.yaml @@ -0,0 +1,9507 @@ +openapi: 3.0.3 +info: + title: Conduktor API + version: v2 + summary: The API to interact with Conduktor Console programmatically + contact: + email: contact@conduktor.io + url: https://docs.conduktor.io + x-logo: + url: https://avatars.githubusercontent.com/u/60062294?s=200&v=4 + backgroundColor: '#FFFFFF' + altText: Conduktor logo +tags: +- name: Introduction + description: | + The Conduktor REST API 's aim is to help you automate the way your Kafka resources are handled by your teams. + + Get started with Conduktor [self-hosted](https://docs.conduktor.io/platform/installation/get-started/docker/) today. Setup takes only a few minutes. +- name: Authentication + description: | + Authentication to the API requires a token set in the **authorization** header. + + To get a token and use it you must go through the following steps: + + * Log in to Conduktor Console and go to the **Settings** page. + + * Click on the **API Keys** tab. + + * Click on the **Create API Key** button. + + * Give your key a name and click on the **Generate Key** button. + + * Copy the key and store it in a safe place. You will not be able to see it again. + + * Use the key in the **authorization** header of your requests. + + Example: + + ```shell + API_KEY="your_api_key" + curl -X GET "https://your.conduktor.host/public/v1/clusters" -H "accept: application/json" -H "authorization: Bearer $API_KEY" + ``` +- name: Kinds + description: |+ + ### Definition + + Kinds the resource types of the Conduktor platform. They follow a set of conventions inspired by K8S that improve the experience and the consistency of the tool chain for the users. + It is important to understand that this standardization is made with the goal of a global __Conduktor automation experience__ (including not only API, but also CLI, files resources definition, devops, scripting, UI) and should result in a __better governance__ of your Kafka resources. + + ### Conduktor Kinds + + The following kinds are available in the Conduktor API: + * `Topic` + * `Application` + * `ApplicationInstance` + * `ApplicationInstancePermission` + * `TopicPolicy` + + ### Properties + Each kind has the following groups of properties: + * `kind`: the kind of the resource (e.g. `Topic`, `Application`...). This field is mandatory, immutable, and case sensitive. + * `version`: the version of the kind that the resource was created with. The version is inherited from the [api group](#tag/Api-Groups) of the kind. Breaking changes to the kind schema will result in a new version. + * `metadata` - common metadata for any kinds. + * `name`: the unique identifier for the resource. It is unique __in the scope of the kind__, not universally. `name` can have different formats depending on the kind. For example clusters names must follow this pattern `^[0-9a-z\\-\\_]+$$` although other kinds can have different patterns. + * `labels`: a set of key-value pairs that can be by the used to organize and categorize resources in a custom way. + * `spec` - the specific fields of each kind. + + + Example: + ```json + { + "metadata":{ + "name":"my-topic", + "cluster":"my-cluster", + "labels": { + "env": "prod", + "team": "infra" + } + }, + "spec":{ + "partitions":1, + "replicationFactor":1, + "configs":{ + } + }, + "apiVersion":"kafka/v2", + "kind":"Topic" + } + ``` + + +- 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. + Kinds of a same group can be nested paths in the API, for example, the `clusters` group can have a `connectors` kind + nested in it. + + ### Conduktor Api Groups + + The following groups are available in the Conduktor API: + + * `console` : Manage the metadata concerning the connection and the information of the Kafka clusters that you have + access to. + * `iam`: Define the users, groups, and permissions of your Conduktor platform. + * `self-serve`: Empower teams to govern their Kafka applications. + * `kafka`: Endpoints to interact with your Kafka clusters. + * `gateway`: Manage the virtual clusters, interceptors, and topic mappings of your Conduktor Gateway. + + | Api Group | Kinds | + |--------------|----------------------------------------------------------------------------------------------------------| + | `console` | `clusters`, `certificates` | + | `iam` | `users`, `groups`, `permissions` | + | `self-serve` | `application`, `application-instance`, `application-instance-permission`, `topic-policy` | + | `kafka` | `topic`, `consumergroup`, `service-accounts`, `ksqlDBs` | + | `gateway` | `interceptors` | + + + + +- 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. + + + 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 + * The `name` field is mandatory in the request body for updates. If not matching an existing resource, a 404 Not Found is returned. + * The `name` field is omitted in the request body for creations. + * 201 Created is returned for creations, 200 OK for updates. + * `DELETE /{api-group}/{version}/{kind}/{name}` to delete a resource + * `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. + + __Nested paths__: + When a kind is nested in another kind, the parent kind is used in the endpoint path. + For example, the `topic` kind is nested in the `cluster` group, so the endpoints for connectors are: + * `GET /kafka/v2/cluster/{name}/topic` + * `GET /kafka/v2/cluster/{name}/topic/{name}` + * `PUT /kafka/v2/cluster/{name}/topic` + * `DELETE /kafka/v2/cluster/{name}/topic/{name}` +- name: cli_application_self-serve_v1 + x-displayName: application +- name: cli_application-instance_self-serve_v1 + x-displayName: application-instance +- name: cli_application-instance-permission_self-serve_v1 + x-displayName: application-instance-permission +- name: cli_topic-policy_self-serve_v1 + x-displayName: topic-policy +- name: cli_topic_kafka_v2 + x-displayName: topic +paths: + /public/v1/groups: + get: + tags: + - groups + description: Return all groups of an organization + operationId: List all groups + responses: + '200': + description: The list of groups + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PublicGroupResponse' + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/groups' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - groups + description: Create a new group in the organization + operationId: Create a group + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PublicCreateGroupRequest' + example: + name: Data engineering + description: Data department. + groupId: data-engineering + externalGroups: + - data + - dataeng + required: true + responses: + '201': + description: '' + '400': + description: 'Invalid value for: body, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/groups' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"Data engineering","description":"Data department.","groupId":"data-engineering","externalGroups":["data","dataeng"]}' \ + --location \ + --max-redirs 32 + /public/v1/groups/{groupId}: + get: + tags: + - groups + description: Return a group by id with its users + operationId: Get a group + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: The group matching the given slug + content: + application/json: + schema: + $ref: '#/components/schemas/PublicGroupResponse' + '400': + description: 'Invalid value for: path parameter groupId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this slug + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this slug + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/groups/data-engineering' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - groups + description: Create or update a group in the organization + operationId: Create or update a group + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateGroupRequest' + example: + name: Data engineering + description: Data department. + externalGroups: + - data + - dataeng + required: true + responses: + '200': + description: '' + '400': + description: 'Invalid value for: path parameter groupId, Invalid value for: + body, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/groups/data-engineering' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"Data engineering","description":"Data department.","externalGroups":["data","dataeng"]}' \ + --location \ + --max-redirs 32 + delete: + tags: + - groups + description: Delete a group from the organization + operationId: Delete a Group + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '204': + description: The group was deleted + '400': + description: 'Invalid value for: path parameter groupId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: The searched entity was not found + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: The searched entity was not found + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/groups/data-engineering' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/groups/{groupId}/users/{userId}: + put: + tags: + - groups + description: Add a user to a group + operationId: Add User To Group + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + - name: userId + in: path + required: true + schema: + type: integer + format: int32 + responses: + '200': + description: '' + '400': + description: 'Invalid value for: path parameter groupId, Invalid value for: + path parameter userId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/users/42' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - groups + description: Remove a user from a group + operationId: Remove User To Group + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + - name: userId + in: path + required: true + schema: + type: integer + format: int32 + responses: + '200': + description: '' + '400': + description: 'Invalid value for: path parameter groupId, Invalid value for: + path parameter userId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/users/42' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/groups/{groupId}/permissions: + get: + tags: + - groups + description: Get group's permissions + operationId: Get permissions + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + '400': + description: 'Invalid value for: path parameter groupId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this email + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - groups + description: Set permissions to group + operationId: Set permissions + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this slug + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this slug + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + delete: + tags: + - groups + description: Delete group's permissions + operationId: Delete permissions + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this slug + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this slug + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + patch: + tags: + - groups + description: Add permissions to group + operationId: Add permissions + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this email + '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 + Curl + source: |- + curl \ + --request PATCH \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + /public/v1/groups/{groupId}/permissions/all: + delete: + tags: + - groups + description: Delete all user's permissions + operationId: Delete all permissions + parameters: + - name: groupId + in: path + description: id of the group + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No group found with this slug + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No group found with this slug + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/groups/data-engineering/permissions/all' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}: + get: + tags: + - clusters + description: Get cluster from its technical id + operationId: Get a cluster + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: The cluster + content: + application/json: + schema: + $ref: '#/components/schemas/PublicSharedClusterResponse' + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - clusters + description: |2 + + Create or update a cluster inside the organization + The technical is mandatory. if it matches an existing cluster, it will be updated, otherwise it will be created. + The slugs of the kafka connects must be unique within the cluster. + operationId: Create or update a cluster + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + description: The cluster to create or update + content: + application/json: + schema: + $ref: '#/components/schemas/UpsertSharedClusterRequest' + examples: + Simple Kafka cluster: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + ignoreUntrustedCertificate: false + Simple Kafka cluster with UI config: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + color: '#000000' + icon: icon + ignoreUntrustedCertificate: false + Kafka cluster with properties: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + properties: |2 + + security.protocol=SSL + ssl.truststore.location=/etc/kafka/secrets/kafka.truststore.jks + ssl.truststore.password=conduktor + ssl.keystore.location=/etc/kafka/secrets/kafka.keystore.jks + ssl.keystore.password=conduktor + ignoreUntrustedCertificate: false + Kafka cluster with a Schema Registry: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + schemaRegistry: + url: https://schema-registry:8081 + security: + key: key + certificateChain: certificateChain + type: SSLAuth + properties: |2 + + schema.registry.ssl.truststore.location=/etc/kafka/secrets/kafka.truststore.jks + schema.registry.ssl.truststore.password=conduktor + schema.registry.ssl.keystore.location=/etc/kafka/secrets/kafka.keystore.jks + schema.registry.ssl.keystore.password=conduktor + ignoreUntrustedCertificate: false + type: ConfluentLikeSchemaRegistryRequest + ignoreUntrustedCertificate: false + Kafka cluster with Kafka Connect: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + kafkaConnects: + - url: http://kafka-connect:8083 + slug: kafka-connect + name: kafka-connect + security: + key: key + certificateChain: certificateChain + type: KafkaConnectSSLAuth + headers: |2 + + "transforms": "insertAppIdHeader", + "transforms.insertAppIdHeader.type": "org.apache.kafka.connect.transforms.InsertHeader", + "transforms.insertAppIdHeader.header": "app.id", + "transforms.insertAppIdHeader.value.literal": "best-app-ever" + ignoreUntrustedCertificate: false + ignoreUntrustedCertificate: false + Kafka cluster with ksqlDB: + value: + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + ignoreUntrustedCertificate: false + ksqlDBs: + - url: http://ksqlDB:8088 + slug: ksqlDB + name: ksqlDB + security: + key: key + certificateChain: certificateChain + type: KsqlDBSSLAuth + headers: '' + ignoreUntrustedCertificate: false + required: true + responses: + '200': + description: The created or updated cluster + content: + application/json: + schema: + $ref: '#/components/schemas/PublicSharedClusterResponse' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"My Kafka cluster","bootstrapServers":"broker1:9092, broker2:9092","properties":"\nsecurity.protocol=SSL\nssl.truststore.location=/etc/kafka/secrets/kafka.truststore.jks\nssl.truststore.password=conduktor\nssl.keystore.location=/etc/kafka/secrets/kafka.keystore.jks\nssl.keystore.password=conduktor\n","color":null,"icon":null,"schemaRegistry":null,"kafkaConnects":null,"ignoreUntrustedCertificate":false,"amazonSecurity":null,"kafkaFlavor":null,"ksqlDBs":null}' \ + --location \ + --max-redirs 32 + delete: + tags: + - clusters + operationId: Delete a cluster + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '204': + description: The cluster has been deleted + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters: + get: + tags: + - clusters + description: Get all clusters of the organization + operationId: List all clusters + responses: + '200': + description: The list of the clusters of the organization + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PublicSharedClusterResponse' + example: + - technicalId: silent-hill + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + kafkaConnects: [] + ignoreUntrustedCertificate: false + createdAt: '1970-01-01T00:00:00Z' + updatedAt: '1970-01-01T00:00:00Z' + ksqlDBs: [] + - technicalId: silent-hill + name: My Kafka cluster + bootstrapServers: broker1:9092, broker2:9092 + properties: |2 + + security.protocol=SSL + ssl.truststore.location=/etc/kafka/secrets/kafka.truststore.jks + ssl.truststore.password=conduktor + ssl.keystore.location=/etc/kafka/secrets/kafka.keystore.jks + ssl.keystore.password=conduktor + kafkaConnects: [] + ignoreUntrustedCertificate: false + createdAt: '1970-01-01T00:00:00Z' + updatedAt: '1970-01-01T00:00:00Z' + ksqlDBs: [] + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/certificates: + get: + tags: + - certificates + description: List the certificates of the organization + operationId: List certificates + responses: + '200': + description: The list of certificates of the organization + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DecodedCertificate' + example: + - id: 1 + version: 1 + serialNumber: 123 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + - id: 2 + version: 1 + serialNumber: 456 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/certificates' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - certificates + description: Add one or several certificates from a text input to the organization + operationId: Add a certificate + requestBody: + description: |2 + + The certificate(s) as a String to add to the organization. + * The input field must match the following regex pattern (cf. example): -----BEGIN CERTIFICATE-----(?:[\\s\\S]*?)-----END CERTIFICATE----- + * The input field must contain a valid x509 certificate (PEM or CRT formats are supported) + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCertificateRequest' + example: + input: |- + -----BEGIN CERTIFICATE----- + MIIDRjCCAi6gAwIBAgIQbgEc+n3F+Gqe8YQqls+DRDANBgkqhkiG9w0BAQsFADAX + MRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcNMjIxMDI0MTk1OTUyWhcNMzIxMDIx + MTk1OTUyWjAeMRwwGgYDVQQDDBNUZXN0IFN1Ym9yZGluYXRlIENBMIIBIjANBgkq + hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4XNztsNyAaewOH9QkrpQWkT78FYg7Ke + j/C2vfzwVb8d/IVP6L8bKIA5/lGlQb5fWEB0AQnlRYVxQyVkycRGpPN3mAzfsD0g + v786pDxxkKAeXMFup+Pc6vRDA+kJ6ok6JcrjhJr+9mBrRCVP6hlUswlQnR2fiYGG + Z4A0VYQu9u2gPwsIBuTBNI9vH6+cKdjdWZIJ4+XJNJ8ohbr8URDa7g3pEIHr71kk + L5mabsB4KLPm0l3W6mu6QTYXn51NAvTMtDx9XCEThNqLammls0xio9Qpp7gxI1QY + huKwNkSz2a50HbhR2kbjSlUw+ugqHBLajB9RwhRtJJT4oF7/V1ZOzQIDAQABo4GG + MIGDMB8GA1UdIwQYMBaAFDpynTg8PcVyv8i1s4qxgQlIT1EhMBIGA1UdEwEB/wQI + MAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA4GA1UdDwEB + /wQEAwIBBjAdBgNVHQ4EFgQUbFpG1G+/QTgbgEa8nRc75m1b2TwwDQYJKoZIhvcN + AQELBQADggEBAEfcOpW/VZjlYdClTBVDi8bpMfs3AN+gFouetPMddEXJPJ6xm7My + a5+rmXdLX+l5ThsNkFQ5+UOXu7PBtpgQfn7W1q2el2oDgg2uc0I0f4WFlMyM1N9z + YkN80/7S5g3n2bbkAWjhyx2b/zh73ChM/rbLGKlsjz+mRIJzI7DXcEwVNJjRMUtG + xxp9PBMZ7uZyoyHru592oaX9Ehm6UDpBDUia8POTENzEz0+9msv0mWbYCzOBKupc + mnd4jMMbT8MSlANCmqPV8VjbnBKT+lVL7nXSqrxlZ6jb8ZA5I9lHK7XS1sQab574 + UC7flGdjN3Ml05raSgAz3mh7qGhv8iQDMbo= + -----END CERTIFICATE----- + required: true + responses: + '201': + description: The certificate(s) added to the organization + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DecodedCertificate' + example: + - id: 1 + version: 1 + serialNumber: 123 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + - id: 2 + version: 1 + serialNumber: 456 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + '400': + description: |2 + + The Json is invalid or the certificate input does not contain a (or several) valid certificate(s): + * The input field must match the following pattern: -----BEGIN CERTIFICATE-----(?:[\\s\\S]*?)-----END CERTIFICATE----- + * The input field must contain a valid x509 certificate (PEM or CRT formats are supported) + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: |2 + + The Json is invalid or the certificate input does not contain a (or several) valid certificate(s): + * The input field must match the following pattern: -----BEGIN CERTIFICATE-----(?:[\\s\\S]*?)-----END CERTIFICATE----- + * The input field must contain a valid x509 certificate (PEM or CRT formats are supported) + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/certificates' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"input":"-----BEGIN CERTIFICATE-----\nMIIDRjCCAi6gAwIBAgIQbgEc+n3F+Gqe8YQqls+DRDANBgkqhkiG9w0BAQsFADAX\nMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcNMjIxMDI0MTk1OTUyWhcNMzIxMDIx\nMTk1OTUyWjAeMRwwGgYDVQQDDBNUZXN0IFN1Ym9yZGluYXRlIENBMIIBIjANBgkq\nhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4XNztsNyAaewOH9QkrpQWkT78FYg7Ke\nj/C2vfzwVb8d/IVP6L8bKIA5/lGlQb5fWEB0AQnlRYVxQyVkycRGpPN3mAzfsD0g\nv786pDxxkKAeXMFup+Pc6vRDA+kJ6ok6JcrjhJr+9mBrRCVP6hlUswlQnR2fiYGG\nZ4A0VYQu9u2gPwsIBuTBNI9vH6+cKdjdWZIJ4+XJNJ8ohbr8URDa7g3pEIHr71kk\nL5mabsB4KLPm0l3W6mu6QTYXn51NAvTMtDx9XCEThNqLammls0xio9Qpp7gxI1QY\nhuKwNkSz2a50HbhR2kbjSlUw+ugqHBLajB9RwhRtJJT4oF7/V1ZOzQIDAQABo4GG\nMIGDMB8GA1UdIwQYMBaAFDpynTg8PcVyv8i1s4qxgQlIT1EhMBIGA1UdEwEB/wQI\nMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA4GA1UdDwEB\n/wQEAwIBBjAdBgNVHQ4EFgQUbFpG1G+/QTgbgEa8nRc75m1b2TwwDQYJKoZIhvcN\nAQELBQADggEBAEfcOpW/VZjlYdClTBVDi8bpMfs3AN+gFouetPMddEXJPJ6xm7My\na5+rmXdLX+l5ThsNkFQ5+UOXu7PBtpgQfn7W1q2el2oDgg2uc0I0f4WFlMyM1N9z\nYkN80/7S5g3n2bbkAWjhyx2b/zh73ChM/rbLGKlsjz+mRIJzI7DXcEwVNJjRMUtG\nxxp9PBMZ7uZyoyHru592oaX9Ehm6UDpBDUia8POTENzEz0+9msv0mWbYCzOBKupc\nmnd4jMMbT8MSlANCmqPV8VjbnBKT+lVL7nXSqrxlZ6jb8ZA5I9lHK7XS1sQab574\nUC7flGdjN3Ml05raSgAz3mh7qGhv8iQDMbo=\n-----END CERTIFICATE-----"}' \ + --location \ + --max-redirs 32 + delete: + tags: + - certificates + description: Delete multiple certificates from the organization + operationId: Delete certificates + parameters: + - name: ids + in: query + description: The ids of the certificates to delete + required: true + schema: + type: array + items: + type: integer + format: int32 + minItems: 1 + example: + - 1 + - 2 + - 3 + responses: + '200': + description: The list of certificate ids effectively deleted + content: + application/json: + schema: + type: array + items: + type: integer + format: int32 + example: + - 1 + - 2 + - 3 + '400': + description: The ids query parameter is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The ids query parameter is invalid + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/certificates?ids=1&ids=2&ids=3' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/certificates/file: + post: + tags: + - certificates + description: Import certificates in the organization from a file (.crt, .pem. + or .jks) + operationId: Upload a certificate + requestBody: + description: |2 + + The certificate(s) as a file to add to the organization and the password if the file is in the JKS format. + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateCertificateFromFileRequest' + required: true + responses: + '201': + description: The certificate(s) added to the organization + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DecodedCertificate' + example: + - id: 1 + version: 1 + serialNumber: 123 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + - id: 2 + version: 1 + serialNumber: 456 + issuerDN: CN=Test Root CA + subjectDN: CN=Test Subordinate CA + notBefore: 1672531200000 + notAfter: 1704067200000 + '400': + description: |2 + + The input file is invalid for one of the following reasons: + * The content is not a valid x509 certificate (PEM, CRT or JKS formats are supported) + * If the file is in the JKS format the password field is mandatory and a valid password must be provided + * The file exceeds the maximum size allowed (50MB) + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: |2 + + The input file is invalid for one of the following reasons: + * The content is not a valid x509 certificate (PEM, CRT or JKS formats are supported) + * If the file is in the JKS format the password field is mandatory and a valid password must be provided + * The file exceeds the maximum size allowed (50MB) + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/certificates/file' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: multipart/form-data' \ + --form 'file=@keystore.jks' \ + --form 'jksPassword=password' \ + --location \ + --max-redirs 32 + /public/v1/certificates/{certificateId}: + delete: + tags: + - certificates + description: Delete a certificate from the organization + operationId: Delete a certificate + parameters: + - name: certificateId + in: path + description: The id of the certificate to delete + required: true + schema: + type: integer + format: int32 + responses: + '204': + description: The certificate has been deleted + '400': + description: 'Invalid value for: path parameter certificateId, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/certificates/42' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/certificates/tls-test: + post: + tags: + - certificates + description: Test a tcp target with the organization's certificates (Kafka uses + the TLS/TCP protocol) + operationId: TLS check + requestBody: + description: ' The connection (host, port) to test with the organization''s + certificates' + content: + application/json: + schema: + $ref: '#/components/schemas/TlsTestRequest' + example: + host: www.google.com + port: 443 + required: true + responses: + '200': + description: The result of the TLS check + content: + application/json: + schema: + $ref: '#/components/schemas/TlsTestResponse' + examples: + The server is authenticated: + value: + status: checked_certificate + The server could NOT be authenticated: + value: + status: unchecked_certificate + The server is unsecure (not using TLS): + value: + status: tls_not_supported + The given url and port could not be reached (timeout 5 seconds): + value: + status: unreachable_target + The server is not authenticated (unexpected response): + value: + status: unexpected_status + '400': + description: The input is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The input is invalid + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/certificates/tls-test' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"host":"www.google.com","port":443}' \ + --location \ + --max-redirs 32 + /public/v1/users: + get: + tags: + - users + operationId: Get the list of users + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PublicWithAllDetailsAndGroup' + example: + - userId: john.doe@conduktor.io + firstName: John + lastName: Doe + fullName: John Doe + pictureUrl: https://www.gravatar.com/avatar/123 + phoneNumber: '+33612345678' + country: France + platformRole: admin + groups: + - name: Admin + groupId: admin + - userId: jane.doe@conduktor.io + firstName: Jane + lastName: Doe + fullName: John Doe + pictureUrl: https://www.gravatar.com/avatar/123 + phoneNumber: '+33612345678' + country: France + platformRole: member + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/users' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - users + description: Create or update a user in the organization + operationId: Update a user + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserRequest' + example: + lastName: Doe + firstName: John + email: john.doe@conduktor.io + required: true + responses: + '200': + description: The user was created or updated + '400': + description: 'Invalid value for: body, Invalid value' + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/users' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"lastName":"Doe","firstName":"John","email":"john.doe@conduktor.io"}' \ + --location \ + --max-redirs 32 + /public/v1/users/{email}: + get: + tags: + - users + description: Get a user by email + operationId: Get user + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + responses: + '200': + description: The user found + content: + application/json: + schema: + $ref: '#/components/schemas/PublicWithAllDetailsAndGroup' + example: + userId: john.doe@conduktor.io + firstName: John + lastName: Doe + fullName: John Doe + pictureUrl: https://www.gravatar.com/avatar/123 + phoneNumber: '+33612345678' + country: France + platformRole: admin + groups: + - name: Admin + groupId: admin + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - users + description: Removes a user from the organization + operationId: Delete a user + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + responses: + '204': + description: The user was deleted + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this id + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this id + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/users/{email}/permissions: + get: + tags: + - users + description: Get user's permissions + operationId: Get permissions + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/UserPermissions' + example: + user: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + groups: + '42': + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicRead + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - users + description: Set permissions to user + operationId: Set permissions + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + delete: + tags: + - users + description: Delete user's permissions + operationId: Delete permissions + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + patch: + tags: + - users + description: Add permissions to user + operationId: Add permissions + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + example: + - resourceType: Topic + clusterId: my-cluster + topicPattern: finance-* + permissions: + - topicCreate + - topicDelete + required: false + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request PATCH \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io/permissions' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '[{"resourceType":"Topic","clusterId":"my-cluster","topicPattern":"finance-*","permissions":["topicCreate","topicDelete"]}]' \ + --location \ + --max-redirs 32 + /public/v1/users/{email}/permissions/all: + delete: + tags: + - users + description: Delete all user's permissions + operationId: Delete all permissions + parameters: + - name: email + in: path + description: Email address of user + required: true + schema: + type: string + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '404': + description: No user found with this email + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No user found with this email + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/users/john.doe@conduktor.io/permissions/all' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application/{application name}: + get: + tags: + - cli_application_self-serve_v1 + operationId: Get Application by name + parameters: + - name: application name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application/my-application' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - cli_application_self-serve_v1 + operationId: Delete a Application + parameters: + - name: application name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/self-serve/v1/application/my-application' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application: + get: + tags: + - cli_application_self-serve_v1 + operationId: List Application resources + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application with this name exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application with this name 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_application_self-serve_v1 + operationId: Create or update a Application + parameters: + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationApplyResult' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/self-serve/v1/application?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-application"},"spec":{"title":"My Application","description":null,"owner":"me"},"apiVersion":"v1","kind":"Application"}' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application-instance/{application-instance name}: + get: + tags: + - cli_application-instance_self-serve_v1 + operationId: Get ApplicationInstance by name + parameters: + - name: application-instance name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstanceResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance/my-application-instance' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - cli_application-instance_self-serve_v1 + operationId: Delete a ApplicationInstance + parameters: + - name: application-instance name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance/my-application-instance' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application-instance: + get: + tags: + - cli_application-instance_self-serve_v1 + operationId: List ApplicationInstance resources + parameters: + - name: application + in: query + description: Filter by application name + required: false + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationInstanceResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance with this name exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance with this name 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_application-instance_self-serve_v1 + operationId: Create or update a ApplicationInstance + parameters: + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstanceResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstanceApplyResult' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-app-instance-prod","application":"my-app"},"spec":{"cluster":"prod-cluster","topicPolicyRef":null,"resources":[],"serviceAccount":null},"apiVersion":"v1","kind":"ApplicationInstance"}' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application-instance-permission/{application-instance-permission name}: + get: + tags: + - cli_application-instance-permission_self-serve_v1 + operationId: Get ApplicationInstancePermission by name + parameters: + - name: application-instance-permission name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstancePermissionResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance-permission with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance-permission with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance-permission/my-application-instance-permission' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - cli_application-instance-permission_self-serve_v1 + operationId: Delete a ApplicationInstancePermission + parameters: + - name: application-instance-permission name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance-permission with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance-permission with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance-permission/my-application-instance-permission' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/application-instance-permission: + get: + tags: + - cli_application-instance-permission_self-serve_v1 + operationId: List ApplicationInstancePermission resources + parameters: + - name: filterByApplication + in: query + description: Filter by application + required: false + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + - name: filterByApplicationInstance + in: query + description: Filter by application instance + required: false + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + - name: filterByGrantedTo + in: query + description: Filter by granted to + required: false + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationInstancePermissionResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance-permission with this name exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance-permission with this name 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance-permission' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_application-instance-permission_self-serve_v1 + operationId: Create or update a ApplicationInstancePermission + parameters: + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstancePermissionResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInstancePermissionApplyResult' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No application-instance-permission with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No application-instance-permission with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/self-serve/v1/application-instance-permission?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"application":"test","appInstance":"test","name":"test"},"spec":{"resource":{"type":"TOPIC","name":"test","patternType":"LITERAL"},"permission":"READ","grantedTo":"test"},"apiVersion":"v1","kind":"ApplicationInstancePermission"}' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/topic-policy/{topic-policy name}: + get: + tags: + - cli_topic-policy_self-serve_v1 + operationId: Get TopicPolicy by name + parameters: + - name: topic-policy name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicPolicyResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic-policy with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic-policy with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/topic-policy/my-topic-policy' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - cli_topic-policy_self-serve_v1 + operationId: Delete a TopicPolicy + parameters: + - name: topic-policy name + in: path + required: true + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic-policy with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic-policy with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/self-serve/v1/topic-policy/my-topic-policy' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/self-serve/v1/topic-policy: + get: + tags: + - cli_topic-policy_self-serve_v1 + operationId: List TopicPolicy resources + parameters: + - name: app-instance + in: query + description: Filter by application instance name + required: false + schema: + type: string + pattern: ^[0-9a-z\_-]+$ + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicPolicyResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic-policy with this name exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic-policy with this name 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/self-serve/v1/topic-policy' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_topic-policy_self-serve_v1 + operationId: Create or update a TopicPolicy + parameters: + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicPolicyResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicPolicyApplyResult' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic-policy with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic-policy with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/self-serve/v1/topic-policy?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-app-instance-prod"},"spec":{"policies":{"my-policy":{"constraint":"OneOf","required":true,"values":["value1","value2"]}}},"apiVersion":"v1","kind":"TopicPolicy"}' \ + --location \ + --max-redirs 32 + /public/kafka/v2/cluster/{cluster}/topic/{topic name}: + get: + tags: + - cli_topic_kafka_v2 + operationId: Get Topic by name + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: topic name + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/kafka/v2/cluster/my-cluster/topic/my-topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - cli_topic_kafka_v2 + operationId: Delete a Topic + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: topic name + in: path + required: true + schema: + type: string + responses: + '200': + 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/kafka/v2/cluster/my-cluster/topic/my-topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/kafka/v2/cluster/{cluster}/topic: + get: + tags: + - cli_topic_kafka_v2 + operationId: List Topic resources + parameters: + - name: cluster + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicResource' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic with this name exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic with this name 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/kafka/v2/cluster/my-cluster/topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_topic_kafka_v2 + operationId: Create or update a Topic + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicApplyResult' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No topic with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No topic with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/kafka/v2/cluster/my-cluster/topic?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-topic","cluster":"my-cluster"},"spec":{"partitions":1,"replicationFactor":1,"configs":{}},"apiVersion":"v1","kind":"Topic"}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts: + get: + tags: + - service-accounts + operationId: Get service accounts + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All service accounts created on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AclPrincipal' + uniqueItems: true + example: + - type: User + name: Gertrude + - type: Group + name: Data + '400': + description: Security disabled on this kafka cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: Security disabled on this kafka cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - service-accounts + operationId: Put acl for a given service account + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AllAclForPrincipal' + example: + aclPrincipal: + type: User + name: Gertrude + acls: + - pattern: + resourceType: Topic + name: topicB + patternType: Literal + host: '*' + operationStates: + Describe: Allow + required: true + responses: + '200': + description: '' + '400': + description: Security disabled on this kafka cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: Security disabled on this kafka cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.create, + kafka.clusters.acl.delete" to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.create, + kafka.clusters.acl.delete" to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"aclPrincipal":{"type":"User","name":"Gertrude"},"acls":[{"pattern":{"resourceType":"Topic","name":"topicB","patternType":"Literal"},"host":"*","operationStates":{"Describe":"Allow"}}]}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-confluent: + get: + tags: + - service-accounts + operationId: Get Confluent service accounts + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All service accounts created on a confluent cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAccount' + uniqueItems: true + example: + - resourceId: sa-pg7y0o + internalId: 675350 + serviceName: my application + description: my business application + '400': + description: This cluster isn't a confluent cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't a confluent cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '429': + description: rate limit exceeded on Confluent API + content: + application/json: + schema: + $ref: '#/components/schemas/TooManyRequest' + example: + title: rate limit exceeded on Confluent API + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-confluent' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - service-accounts + operationId: Create Confluent service accounts + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + description: New Confluent service account. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateServiceAccount' + example: + name: prod-service-account + description: my service account. + required: true + responses: + '201': + description: Create a service accounts. + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAccount' + example: + resourceId: sa-pg7y0o + internalId: 675350 + serviceName: my application + description: my business application + '400': + description: This cluster isn't a confluent cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't a confluent cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '429': + description: rate limit exceeded on Confluent API + content: + application/json: + schema: + $ref: '#/components/schemas/TooManyRequest' + example: + title: rate limit exceeded on Confluent API + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-confluent' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"prod-service-account","description":"my service account."}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-confluent/{confluentResourceId}/api-keys: + get: + tags: + - service-accounts + operationId: Get Confluent api keys + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: confluentResourceId + in: path + description: Confluent service Account's id + required: true + schema: + type: string + responses: + '200': + description: All confluent's api keys related to a service account. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApiKey' + uniqueItems: true + example: + - key: VJF6UG6VSXYIGY32 + description: my api key. + createdAt: -1000000000-01-01T00:00:00Z + secret: R15hoiDIq8Nxu/lY4mPO3DwAVIfU5W7OI+efsB607mLgHTnVW5XJGVqX2ysDx987 + '400': + description: This cluster isn't a confluent cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't a confluent cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '429': + description: rate limit exceeded on Confluent API + content: + application/json: + schema: + $ref: '#/components/schemas/TooManyRequest' + example: + title: rate limit exceeded on Confluent API + '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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-confluent/sa-pg7y0y/api-keys' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - service-accounts + operationId: Create Confluent api keys + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: confluentResourceId + in: path + description: Confluent service Account's id + required: true + schema: + type: string + requestBody: + description: New Confluent API key. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateApiKey' + example: + name: key + description: my api key. + required: true + responses: + '201': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ApiKey' + example: + key: VJF6UG6VSXYIGY32 + description: my api key. + createdAt: -1000000000-01-01T00:00:00Z + secret: R15hoiDIq8Nxu/lY4mPO3DwAVIfU5W7OI+efsB607mLgHTnVW5XJGVqX2ysDx987 + '400': + description: This cluster isn't a confluent cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't a confluent cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '429': + description: rate limit exceeded on Confluent API + content: + application/json: + schema: + $ref: '#/components/schemas/TooManyRequest' + example: + title: rate limit exceeded on Confluent API + '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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-confluent/sa-pg7y0y/api-keys' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"key","description":"my api key."}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-aiven: + get: + tags: + - service-accounts + operationId: Get Aiven service accounts + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All service accounts created on an Aiven cluster. + content: + application/json: + schema: + type: array + items: + type: string + uniqueItems: true + example: + - example-account + '400': + description: This cluster isn't an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't an Aiven cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-aiven' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - service-accounts + operationId: Create an Aiven service accounts + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AivenServiceAccountCreateRequest' + required: true + responses: + '201': + description: Create a service account on an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/AivenServiceAccountCreateResponse' + '400': + description: This cluster isn't an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't an Aiven cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.create" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-aiven' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"username":"my-service-account"}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-confluent/{confluentResourceId}/api-keys/{confluentApiKeyId}: + delete: + tags: + - service-accounts + operationId: Delete Confluent api keys + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: confluentResourceId + in: path + description: Confluent service Account's id + required: true + schema: + type: string + - name: confluentApiKeyId + in: path + description: Confluent API key's id + required: true + schema: + type: string + responses: + '204': + description: '' + '400': + description: This cluster isn't a confluent cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't a confluent cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.delete" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.delete" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '429': + description: rate limit exceeded on Confluent API + content: + application/json: + schema: + $ref: '#/components/schemas/TooManyRequest' + example: + title: rate limit exceeded on Confluent API + '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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-confluent/sa-pg7y0y/api-keys/VJF6UG6VSXYIGY32' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-aiven/{aivenSAUsername}: + delete: + tags: + - service-accounts + operationId: Delete an Aiven service account + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: aivenSAUsername + in: path + description: Aiven's service account username + required: true + schema: + type: string + responses: + '204': + description: '' + '400': + description: This cluster isn't an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't an Aiven cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.delete" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.delete" + to do this operation + '404': + description: No cluster with this technical id exist or no service account + with this username exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist or no service account + with this username 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-aiven/my-service-account' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts-aiven/{AivenSAUsernamePattern}/acl: + get: + tags: + - service-accounts + operationId: Get Aiven ACLs of a cluster + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: AivenSAUsernamePattern + in: path + description: Aiven service account username pattern + required: true + schema: + type: string + responses: + '200': + description: All ACLs created on an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/AivenListAclResponse' + example: + acls: + - id: acl453f874ec16 + permission: read + topic: topicA + username: bob + - id: acl453f874ec17 + permission: read + topic: topicB + username: bob + schemaRegistryAcls: + - id: acl453f874ec16 + permission: read + resource: 'Config:' + username: bob + - id: acl453f874ec17 + permission: write + resource: 'Subject: topicA-value' + username: bob + '400': + description: This cluster isn't an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't an Aiven cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-aiven/my-service-account/acl' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - service-accounts + operationId: Create (or update) acls for a given Aiven service account + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: AivenSAUsernamePattern + in: path + description: Aiven service account username pattern + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AivenAclsCreateRequest' + example: + acls: + - permission: read + topic: topicA + - permission: write + topic: topicB-* + schemaRegistryAcls: + - permission: schema_registry_read + resource: 'Config:' + - permission: schema_registry_write + resource: Subject:topicA-value + required: true + responses: + '200': + description: '' + '400': + description: This cluster isn't an Aiven cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: This cluster isn't an Aiven cluster. + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.create, + kafka.clusters.acl.delete" to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.create, + kafka.clusters.acl.delete" to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts-aiven/my-username/acl' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"acls":[{"permission":"read","topic":"topicA"},{"permission":"write","topic":"topicB-*"}],"schemaRegistryAcls":[{"permission":"schema_registry_read","resource":"Config:"},{"permission":"schema_registry_write","resource":"Subject:topicA-value"}]}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/service-accounts/{aclPrincipal}: + get: + tags: + - service-accounts + operationId: Get acls for a given service account + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: aclPrincipal + in: path + description: Kafka ACL principal + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AclBinding' + uniqueItems: true + example: + - pattern: + resourceType: Topic + name: topicB + patternType: Literal + entry: + principal: + type: User + name: Gertrude + host: '*' + operation: Read + permissionType: Allow + '400': + description: Invalid value + content: + text/plain: + schema: + type: string + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.clusters.acl.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/service-accounts/User:bob' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/interceptors: + get: + tags: + - interceptors + operationId: Get interceptors + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All interceptors created on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Interceptor' + uniqueItems: true + example: + - name: myEncryptionInterceptor + pluginClass: io.conduktor.gateway.interceptor.EncryptPlugin + priority: 50 + config: + topic: topicName + - name: myInjectHeaderInterceptor + pluginClass: io.conduktor.gateway.interceptor.DynamicHeaderInjectionPlugin + priority: 51 + config: + topic: topicName + - name: myInjectHeaderInterceptor + pluginClass: io.conduktor.gateway.interceptor.DynamicHeaderInjectionPlugin + priority: 52 + config: + topic: topicName + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/interceptors' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - interceptors + operationId: Create an Interceptor + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + description: The interceptor to create. + content: + application/json: + schema: + $ref: '#/components/schemas/Interceptor' + example: + name: myEncryptionInterceptor + pluginClass: io.conduktor.gateway.interceptor.EncryptPlugin + priority: 50 + config: + topic: topicName + required: true + responses: + '201': + description: '' + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id exist + '409': + description: The interceptor already exist + content: + application/json: + schema: + $ref: '#/components/schemas/Conflict' + example: + title: The interceptor 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/interceptors' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"name":"myEncryptionInterceptor","pluginClass":"io.conduktor.gateway.interceptor.EncryptPlugin","priority":50,"config":{"topic":"topicName"}}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/plugins: + get: + tags: + - interceptors + operationId: Get plugins + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All plugins available on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Plugin' + uniqueItems: true + example: + - plugin: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin + pluginId: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin + tags: + parent: Console + description: Validate your application behaves correctly when broker + errors occur. + license: enterprise + version: 1.0.1-SNAPSHOT + title: Broker errors + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/plugins' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/plugins/{pluginId}: + get: + tags: + - interceptors + operationId: Get a plugin + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: pluginId + in: path + required: true + schema: + type: string + responses: + '200': + description: Get a specific plugin available on the cluster. + content: + application/json: + schema: + $ref: '#/components/schemas/PluginWithReadme' + example: + plugin: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin + pluginId: io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin + tags: + parent: Console + description: Validate your application behaves correctly when broker + errors occur. + license: enterprise + version: 1.0.1-SNAPSHOT + title: Broker errors + readme: "---\nversion: 1.0.1-SNAPSHOT\ntitle: Broker errors\ndescription:\ + \ Validate your application behaves correctly when broker errors\ + \ occur.\nparent: chaos\nlicense: enterprise\n---\n\n## What is\ + \ Broken broker chaos?\n\nThis interceptor inject intermittent errors\ + \ in client connections to brokers that are consistent with broker\ + \ side issues. \n\nThis only works on Produce requests and Fetch\ + \ requests.\n\n## Configuration\n\n| config | type | description\ + \ \ + \ \ + \ |\n|:--------------|------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n\ + | rateInPercent | int | The percentage of requests that will result\ + \ in a broker not available response \ + \ \ + \ |\n| errorMap | Map | Map of ApiKeys and Error you\ + \ want to response, not required.Default errorMap when errorMap\ + \ is not configured:FETCH: UNKNOWN_SERVER_ERRORPRODUCE: CORRUPT_MESSAGE\ + \ |\n\n## Possible Error for Api Key\n\n### [FETCH](https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/requests/FetchResponse.java#L48-L65):\n\ + \n- OFFSET_OUT_OF_RANGE\n- TOPIC_AUTHORIZATION_FAILED\n- REPLICA_NOT_AVAILABLE\n\ + - NOT_LEADER_OR_FOLLOWER\n- FENCED_LEADER_EPOCH\n- UNKNOWN_LEADER_EPOCH\n\ + - UNKNOWN_TOPIC_OR_PARTITION\n- KAFKA_STORAGE_ERROR\n- UNSUPPORTED_COMPRESSION_TYPE\n\ + - CORRUPT_MESSAGE\n- UNKNOWN_TOPIC_ID\n- FETCH_SESSION_TOPIC_ID_ERROR,\n\ + - INCONSISTENT_TOPIC_ID,\n- UNKNOWN_SERVER_ERROR\n\n### [PRODUCE](https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/requests/ProduceResponse.java#L39-L53):\n\ + \n- CORRUPT_MESSAGE,\n- UNKNOWN_TOPIC_OR_PARTITION,\n- NOT_LEADER_OR_FOLLOWER,\n\ + - INVALID_TOPIC_EXCEPTION,\n- RECORD_LIST_TOO_LARGE,\n- NOT_ENOUGH_REPLICAS,\n\ + - NOT_ENOUGH_REPLICAS_AFTER_APPEND,\n- INVALID_REQUIRED_ACKS,\n\ + - TOPIC_AUTHORIZATION_FAILED,\n- UNSUPPORTED_FOR_MESSAGE_FORMAT,\n\ + - INVALID_PRODUCER_EPOCH,\n- CLUSTER_AUTHORIZATION_FAILED,\n- TRANSACTIONAL_ID_AUTHORIZATION_FAILED,\n\ + - INVALID_RECORD\n\n## Example\n\n```yaml\n name: myBrokenBrokerChaosInterceptor\n\ + \ pluginClass: io.conduktor.gateway.interceptor.BrokenBrokerChaosPlugin\n\ + \ priority: 100\n config:\n - key: rateInPercent\n \ + \ value: 100\n - key: errorMap\n value:\n \ + \ FETCH: UNKNOWN_SERVER_ERROR\n PRODUCE: CORRUPT_MESSAGE\n\ + ```" + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/plugins/io.conduktor.gateway.interceptor.chaos.SimulateSlowProducersConsumersPlugin' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/interceptors/{interceptorName}: + put: + tags: + - interceptors + operationId: Update an Interceptor + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: interceptorName + in: path + required: true + schema: + type: string + requestBody: + description: The interceptor to update. + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateInterceptor' + example: + pluginClass: io.conduktor.gateway.interceptor.EncryptPlugin + priority: 50 + config: + topic: topicName + required: true + responses: + '204': + description: '' + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/interceptors/name' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"pluginClass":"io.conduktor.gateway.interceptor.EncryptPlugin","priority":50,"config":{"topic":"topicName"}}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/interceptors/{technicalId}: + delete: + tags: + - interceptors + operationId: Delete a plugin + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: technicalId + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + '400': + description: The cluster is not a valid gateway cluster + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The cluster is not a valid gateway cluster + '401': + description: The user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/interceptors/name' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/topics: + post: + tags: + - topic + operationId: List topic on a kafka cluster + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicListRequest' + example: + page: 1 + itemsPerPage: 20 + filter: + - contains: opi + type: TopicNameFilter + - oneOf: + - compact + type: CleanupPolicyFilter + - type: HideInternal + sort: ByMessageCount + descSort: true + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/Page_TopicResponse' + example: + data: + - name: topic + type: NotIndexedTopic + - name: topic + replicationFactor: 3 + partitionCount: 3 + recordCount: 191829 + topicSize: 42390 + cleanupPolicy: compact + retentionInSize: -1 + retentionInMs: -1 + minIsr: 1 + tags: + - id: f9ae435d-ac85-4d9f-ae0b-e1eb3ee0bf28 + name: a_tag + color: '#008000' + lastActivityAt: '2021-03-18T14:00:00Z' + produceRate: 0 + type: IndexedTopic + page: 1 + totalPages: 1 + perPage: 10 + totalElements: 1 + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.topics.read" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.topics.read" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/topics' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"page":1,"itemsPerPage":20,"filter":[{"contains":"opi","type":"TopicNameFilter"},{"oneOf":["compact"],"type":"CleanupPolicyFilter"},{"type":"HideInternal"}],"sort":"ByMessageCount","descSort":true}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/consumergroups: + post: + tags: + - consumergroup + operationId: List consumer group + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConsumerGroupRequest' + example: + page: 1 + itemsPerPage: 20 + filter: + - contains: opi + type: OnConsumerGroupName + - oneOf: + - Dead + type: OnState + sort: ByMaxLagTimeInSeconds + descSort: true + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/Page_ConsumerGroupResponse' + example: + data: + - name: cg1 + state: Dead + members: 1 + overallLag: 542 + topics: + - topic1 + maxLagTimeInSeconds: 100 + type: IndexedConsumerGroup + page: 1 + totalPages: 1 + perPage: 20 + totalElements: 1 + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have the required permission(s) "kafka.groups.describe" + to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have the required permission(s) "kafka.groups.describe" + to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/consumergroups' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"page":1,"itemsPerPage":20,"filter":[{"contains":"opi","type":"OnConsumerGroupName"},{"oneOf":["Dead"],"type":"OnState"}],"sort":"ByMaxLagTimeInSeconds","descSort":true}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/queries: + get: + tags: + - ksqlDBs + operationId: List queries + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + responses: + '200': + description: All queries available on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Query' + uniqueItems: true + example: + - queryString: "CREATE TABLE WIKIPEDIA_COUNT_GT_1 WITH (KAFKA_TOPIC='WIKIPEDIA_COUNT_GT_1',\ + \ KEY_FORMAT='JSON', PARTITIONS=2, REPLICAS=2) AS SELECT\n WIKIPEDIA.USER\ + \ USER,\n WIKIPEDIA.META->URI URI,\n COUNT(*) COUNT\nFROM WIKIPEDIA\ + \ WIKIPEDIA\nWINDOW TUMBLING ( SIZE 300 SECONDS ) \nWHERE (WIKIPEDIA.META->DOMAIN\ + \ = 'commons.wikimedia.org')\nGROUP BY WIKIPEDIA.USER, WIKIPEDIA.META->URI\n\ + HAVING (COUNT(*) > 1)\nEMIT CHANGES;" + sinks: + - WIKIPEDIA_COUNT_GT_1 + sinkKafkaTopics: + - WIKIPEDIA_COUNT_GT_1 + id: CTAS_WIKIPEDIA_COUNT_GT_1_7 + statusCount: + RUNNING: 1 + ERROR: 0 + TERMINATED: 0 + SUCCESS: 0 + queryType: PERSISTENT + state: RUNNING + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/server/queries' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + post: + tags: + - ksqlDBs + operationId: Execute a query + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + requestBody: + description: example + content: + application/json: + schema: + $ref: '#/components/schemas/KsqlDBQuery' + example: + ksql: SELECT * FROM WIKIPEDIA EMIT CHANGES; + properties: + ksql.streams.auto.offset.reset: earliest + required: true + responses: + '200': + description: The result of the query. + content: + application/json: + schema: + $ref: '#/components/schemas/List_String' + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/queries' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"ksql":"SELECT * FROM WIKIPEDIA EMIT CHANGES;","properties":{"ksql.streams.auto.offset.reset":"earliest"}}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/tables: + get: + tags: + - ksqlDBs + operationId: List tables + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + responses: + '200': + description: All tables available on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Table' + uniqueItems: true + example: + - name: table1 + topic: topic1 + keyFormat: JSON + valueFormat: JSON + reads: 3 + writes: 1 + isWindowed: false + - name: table2 + topic: topic2 + keyFormat: JSON + valueFormat: JSON + reads: 5 + writes: 1 + isWindowed: 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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/server/tables' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/describe/{sourceName}: + get: + tags: + - ksqlDBs + operationId: Describe source + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + - name: sourceName + in: path + required: true + schema: + type: string + responses: + '200': + description: The description of the source. (stream or table) + content: + application/json: + schema: + $ref: '#/components/schemas/SourceDescription' + example: + name: WIKIPEDIA_COUNT_GT_1 + windowType: TUMBLING + topic: WIKIPEDIA_COUNT_GT_1 + type: TABLE + keyFormat: JSON + valueFormat: JSON + sourceConstraints: + - TOPIC1 + - TOPIC2 + statement: CREATE STREAM WIKIPEDIA (BOT BOOLEAN, COMMENT STRING, ID + BIGINT, LENGTH STRUCT, LOG_ACTION STRING, + LOG_ACTION_COMMENT STRING, LOG_ID BIGINT, LOG_TYPE STRING, META + STRUCT, MINOR BOOLEAN, `NAMESPACE` BIGINT, + PARSEDCOMMENT STRING, PATROLLED BOOLEAN, REVISION STRUCT, SERVER_NAME STRING, SERVER_SCRIPT_PATH STRING, SERVER_URL + STRING, TIMESTAMP BIGINT, TITLE STRING, TYPE STRING, USER STRING, + WIKI STRING) WITH (KAFKA_TOPIC='wikipedia.parsed', KEY_FORMAT='KAFKA', + VALUE_FORMAT='AVRO'); + statistics: + consumer-message-per-sec: 0.0 + consumer-total-messages: 0.0 + consumer-total-bytes: 0.0 + last-message: 1.696268412825E12 + readQueriesCount: 2 + writeQueriesCount: 10 + fields: + - name: BOT + type: BOOLEAN + - name: COMMENT + type: STRING + - name: ID + type: BIGINT + - name: LENGTH + type: STRUCT + fields: + - name: NEW + type: BIGINT + - name: OLD + type: BIGINT + - name: LOG_ACTION + type: STRING + - name: LOG_ACTION_COMMENT + type: STRING + - name: LOG_ID + type: BIGINT + - name: LOG_TYPE + type: STRING + - name: META + type: STRUCT + fields: + - name: DOMAIN + type: STRING + - name: DT + type: TIMESTAMP + - name: ID + type: STRING + - name: REQUEST_ID + type: STRING + - name: STREAM + type: STRING + - name: URI + type: STRING + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/describe/sourceName' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/explain/{query}: + get: + tags: + - ksqlDBs + operationId: Explain a query + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + - name: query + in: path + required: true + schema: + type: string + responses: + '200': + description: The description of a query. + content: + application/json: + schema: + $ref: '#/components/schemas/ExplainQuery' + example: + statementText: |- + CREATE STREAM WIKIPEDIANOBOT WITH (KAFKA_TOPIC='WIKIPEDIANOBOT', PARTITIONS=2, REPLICAS=2) AS SELECT + *, + (WIKIPEDIA.LENGTH->NEW - WIKIPEDIA.LENGTH->OLD) BYTECHANGE + FROM WIKIPEDIA WIKIPEDIA + WHERE ((((WIKIPEDIA.BOT = false) AND (WIKIPEDIA.LENGTH IS NOT NULL)) AND (WIKIPEDIA.LENGTH->NEW IS NOT NULL)) AND (WIKIPEDIA.LENGTH->OLD IS NOT NULL)) + EMIT CHANGES; + sources: + - WIKIPEDIA + sinks: + - WIKIPEDIANOBOT + topology: |+ + Topologies: + Sub-topology: 0 + Source: KSTREAM-SOURCE-0000000000 (topics: [wikipedia.parsed]) + --> KSTREAM-TRANSFORMVALUES-0000000001 + Processor: KSTREAM-TRANSFORMVALUES-0000000001 (stores: []) + --> WhereFilter + <-- KSTREAM-SOURCE-0000000000 + Processor: WhereFilter (stores: []) + --> Project + <-- KSTREAM-TRANSFORMVALUES-0000000001 + Processor: Project (stores: []) + --> KSTREAM-SINK-0000000004 + <-- WhereFilter + Sink: KSTREAM-SINK-0000000004 (topic: WIKIPEDIANOBOT) + <-- Project + + executionPlan: " > [ SINK ] | Schema: BOT BOOLEAN, COMMENT STRING,\ + \ ID BIGINT, LENGTH STRUCT, LOG_ACTION STRING,\ + \ LOG_ACTION_COMMENT STRING, LOG_ID BIGINT, LOG_TYPE STRING, META\ + \ STRUCT, MINOR BOOLEAN, `NAMESPACE` BIGINT,\ + \ PARSEDCOMMENT STRING, PATROLLED BOOLEAN, REVISION STRUCT, SERVER_NAME STRING, SERVER_SCRIPT_PATH STRING, SERVER_URL\ + \ STRING, TIMESTAMP BIGINT, TITLE STRING, TYPE STRING, USER STRING,\ + \ WIKI STRING, BYTECHANGE BIGINT | Logger: CSAS_WIKIPEDIANOBOT_3.WIKIPEDIANOBOT\n\ + \t\t > [ PROJECT ] | Schema: BOT BOOLEAN, COMMENT STRING, ID BIGINT,\ + \ LENGTH STRUCT, LOG_ACTION STRING, LOG_ACTION_COMMENT\ + \ STRING, LOG_ID BIGINT, LOG_TYPE STRING, META STRUCT, MINOR BOOLEAN, `NAMESPACE` BIGINT, PARSEDCOMMENT STRING,\ + \ PATROLLED BOOLEAN, REVISION STRUCT, SERVER_NAME\ + \ STRING, SERVER_SCRIPT_PATH STRING, SERVER_URL STRING, TIMESTAMP\ + \ BIGINT, TITLE STRING, TYPE STRING, USER STRING, WIKI STRING, BYTECHANGE\ + \ BIGINT | Logger: CSAS_WIKIPEDIANOBOT_3.Project\n\t\t\t\t > [ FILTER\ + \ ] | Schema: BOT BOOLEAN, COMMENT STRING, ID BIGINT, LENGTH STRUCT, LOG_ACTION STRING, LOG_ACTION_COMMENT STRING,\ + \ LOG_ID BIGINT, LOG_TYPE STRING, META STRUCT, MINOR BOOLEAN, `NAMESPACE` BIGINT, PARSEDCOMMENT STRING,\ + \ PATROLLED BOOLEAN, REVISION STRUCT, SERVER_NAME\ + \ STRING, SERVER_SCRIPT_PATH STRING, SERVER_URL STRING, TIMESTAMP\ + \ BIGINT, TITLE STRING, TYPE STRING, USER STRING, WIKI STRING, ROWTIME\ + \ BIGINT, ROWPARTITION INTEGER, ROWOFFSET BIGINT | Logger: CSAS_WIKIPEDIANOBOT_3.WhereFilter\n\ + \t\t\t\t\t\t > [ SOURCE ] | Schema: BOT BOOLEAN, COMMENT STRING,\ + \ ID BIGINT, LENGTH STRUCT, LOG_ACTION STRING,\ + \ LOG_ACTION_COMMENT STRING, LOG_ID BIGINT, LOG_TYPE STRING, META\ + \ STRUCT, MINOR BOOLEAN, `NAMESPACE` BIGINT,\ + \ PARSEDCOMMENT STRING, PATROLLED BOOLEAN, REVISION STRUCT, SERVER_NAME STRING, SERVER_SCRIPT_PATH STRING, SERVER_URL\ + \ STRING, TIMESTAMP BIGINT, TITLE STRING, TYPE STRING, USER STRING,\ + \ WIKI STRING, ROWTIME BIGINT, ROWPARTITION INTEGER, ROWOFFSET BIGINT\ + \ | Logger: CSAS_WIKIPEDIANOBOT_3.KsqlTopic.Source\n" + state: RUNNING + fields: + - name: BOT + type: BOOLEAN + - name: COMMENT + type: STRING + - name: ID + type: BIGINT + - name: LENGTH + type: STRUCT + fields: + - name: NEW + type: BIGINT + - name: OLD + type: BIGINT + - name: LOG_ACTION + type: STRING + - name: LOG_ACTION_COMMENT + type: STRING + - name: LOG_ID + type: BIGINT + - name: LOG_TYPE + type: STRING + - name: META + type: STRUCT + fields: + - name: DOMAIN + type: STRING + - name: DT + type: TIMESTAMP + - name: ID + type: STRING + - name: REQUEST_ID + type: STRING + - name: STREAM + type: STRING + - name: URI + type: STRING + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/explain/queryName' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/tables/{sourceName}: + delete: + tags: + - ksqlDBs + operationId: Delete a table + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + - name: sourceName + in: path + required: true + schema: + type: string + responses: + '200': + description: The table has been dropped. + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/tables/WIKIPEDIA' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/streams/{sourceName}: + delete: + tags: + - ksqlDBs + operationId: Delete a stream + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + - name: sourceName + in: path + required: true + schema: + type: string + responses: + '200': + description: The stream has been dropped. + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/streams/WIKIPEDIA' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/queries/{queryId}: + delete: + tags: + - ksqlDBs + operationId: Terminate a query + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + - name: queryId + in: path + required: true + schema: + type: string + responses: + '200': + description: The query has been terminated. + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/queries/transient_WIKIPEDIA_8560267961308778116' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}/statements: + post: + tags: + - ksqlDBs + operationId: Execute a statement + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + requestBody: + description: example + content: + application/json: + schema: + $ref: '#/components/schemas/KsqlDBStatement' + example: + ksql: LIST TABLES; + required: true + responses: + '200': + description: The statement has been executed. + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request POST \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/ksqldbSlug/statements' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"ksql":"LIST TABLES;"}' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs: + get: + tags: + - ksqlDBs + operationId: List server infos + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + responses: + '200': + description: All server infos available on the cluster. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/KsqlServerInfo' + uniqueItems: true + example: + - name: my name + slug: my-name + version: 7.2.1 + tableCount: 1 + streamCount: 10 + queryCount: 3 + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/clusters/{technicalId}/ksqldbs/{ksqlDBSlug}: + get: + tags: + - ksqlDBs + operationId: Get server infos of a specific ksqldb server + parameters: + - name: technicalId + in: path + description: Technical id of the cluster + required: true + schema: + type: string + - name: ksqlDBSlug + in: path + required: true + schema: + type: string + responses: + '200': + description: server infos for a specific ksqldb server. + content: + application/json: + schema: + $ref: '#/components/schemas/KsqlServerInfo' + example: + name: my name + slug: my-name + version: 7.2.1 + tableCount: 1 + streamCount: 10 + queryCount: 3 + '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 user is not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + example: + title: The user is not authenticated + '403': + description: The user doesn't have sufficient privilege to do this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Forbidden' + example: + title: The user doesn't have sufficient privilege to do this operation + '404': + description: No cluster with this technical id exist + content: + application/json: + schema: + $ref: '#/components/schemas/NotFound' + example: + title: No cluster with this technical id 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 + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/clusters/my-cluster/ksqldbs/server' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 +components: + schemas: + AccessControlEntry: + title: AccessControlEntry + required: + - principal + - host + - operation + - permissionType + type: object + properties: + principal: + $ref: '#/components/schemas/AclPrincipal' + host: + type: string + operation: + $ref: '#/components/schemas/AclOperationForAccessControlEntry' + permissionType: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + AclBinding: + title: AclBinding + required: + - pattern + - entry + type: object + properties: + pattern: + $ref: '#/components/schemas/ResourcePattern' + entry: + $ref: '#/components/schemas/AccessControlEntry' + AclForResourceAndHost: + title: AclForResourceAndHost + required: + - pattern + - host + - operationStates + type: object + properties: + pattern: + $ref: '#/components/schemas/ResourcePattern' + host: + type: string + operationStates: + $ref: '#/components/schemas/OperationStates' + AclOperationForAccessControlEntry: + title: AclOperationForAccessControlEntry + type: string + enum: + - Unknown + - All + - Read + - Write + - Create + - Delete + - Alter + - Describe + - ClusterAction + - DescribeConfigs + - AlterConfigs + - IdempotentWrite + - CreateTokens + - DescribeTokens + AclPermissionTypeForAccessControlEntry: + title: AclPermissionTypeForAccessControlEntry + type: string + enum: + - Unknown + - Deny + - Allow + AclPrincipal: + title: AclPrincipal + required: + - type + - name + type: object + properties: + type: + type: string + name: + type: string + Aiven: + title: Aiven + required: + - apiToken + - project + - serviceName + - type + type: object + properties: + apiToken: + type: string + project: + type: string + serviceName: + type: string + type: + type: string + AivenAcl: + title: AivenAcl + required: + - id + - permission + - topic + - username + type: object + properties: + id: + type: string + permission: + type: string + topic: + type: string + username: + type: string + AivenAclCreatePayload: + title: AivenAclCreatePayload + required: + - permission + - topic + type: object + properties: + permission: + $ref: '#/components/schemas/AivenAclPermission' + topic: + type: string + AivenAclPermission: + title: AivenAclPermission + type: string + enum: + - read + - write + - readwrite + - admin + AivenAclsCreateRequest: + title: AivenAclsCreateRequest + type: object + properties: + acls: + type: array + items: + $ref: '#/components/schemas/AivenAclCreatePayload' + uniqueItems: true + schemaRegistryAcls: + type: array + items: + $ref: '#/components/schemas/AivenSRAclCreatePayload' + uniqueItems: true + AivenListAclResponse: + title: AivenListAclResponse + type: object + properties: + acls: + type: array + items: + $ref: '#/components/schemas/AivenAcl' + uniqueItems: true + schemaRegistryAcls: + type: array + items: + $ref: '#/components/schemas/AivenSchemaRegistryAcl' + uniqueItems: true + AivenSRAclCreatePayload: + title: AivenSRAclCreatePayload + required: + - permission + - resource + type: object + properties: + permission: + $ref: '#/components/schemas/AivenSchemaRegistryAclPermission' + resource: + type: string + AivenSchemaRegistryAcl: + title: AivenSchemaRegistryAcl + required: + - id + - permission + - resource + - username + type: object + properties: + id: + type: string + permission: + type: string + resource: + type: string + username: + type: string + AivenSchemaRegistryAclPermission: + title: AivenSchemaRegistryAclPermission + type: string + enum: + - schema_registry_read + - schema_registry_write + AivenServiceAccountCreateRequest: + title: AivenServiceAccountCreateRequest + required: + - username + type: object + properties: + username: + type: string + AivenServiceAccountCreateResponse: + title: AivenServiceAccountCreateResponse + required: + - access_cert + - access_key + - password + - type + - username + type: object + properties: + access_cert: + type: string + access_key: + type: string + password: + type: string + type: + type: string + username: + type: string + AllAclForPrincipal: + title: AllAclForPrincipal + required: + - aclPrincipal + type: object + properties: + aclPrincipal: + $ref: '#/components/schemas/AclPrincipal' + acls: + type: array + items: + $ref: '#/components/schemas/AclForResourceAndHost' + AmazonSecurity: + title: AmazonSecurity + oneOf: + - $ref: '#/components/schemas/Credentials' + - $ref: '#/components/schemas/FromContext' + - $ref: '#/components/schemas/FromRole' + - $ref: '#/components/schemas/IAMAnywhere' + discriminator: + propertyName: type + mapping: + Credentials: '#/components/schemas/Credentials' + FromContext: '#/components/schemas/FromContext' + FromRole: '#/components/schemas/FromRole' + IAMAnywhere: '#/components/schemas/IAMAnywhere' + ApiKey: + title: ApiKey + required: + - key + - description + - createdAt + - secret + type: object + properties: + key: + type: string + description: + type: string + createdAt: + type: string + format: date-time + secret: + type: string + ApplicationApplyResult: + title: ApplicationApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/ApplicationResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + ApplicationInstanceApplyResult: + title: ApplicationInstanceApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/ApplicationInstanceResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + ApplicationInstanceKind: + title: ApplicationInstanceKind + type: string + enum: + - ApplicationInstance + ApplicationInstanceMetadata: + title: ApplicationInstanceMetadata + required: + - name + - application + type: object + properties: + name: + type: string + pattern: ^[0-9a-z\_-]+$ + application: + type: string + pattern: ^[0-9a-z\_-]+$ + ApplicationInstancePermissionApplyResult: + title: ApplicationInstancePermissionApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/ApplicationInstancePermissionResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + ApplicationInstancePermissionKind: + title: ApplicationInstancePermissionKind + type: string + enum: + - ApplicationInstancePermission + ApplicationInstancePermissionMetadata: + title: ApplicationInstancePermissionMetadata + required: + - application + - appInstance + - name + type: object + properties: + application: + type: string + pattern: ^[0-9a-z\_-]+$ + appInstance: + type: string + pattern: ^[0-9a-z\_-]+$ + name: + type: string + pattern: ^[0-9a-z\_-]+$ + ApplicationInstancePermissionResource: + title: ApplicationInstancePermissionResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/ApplicationInstancePermissionMetadata' + spec: + $ref: '#/components/schemas/ApplicationInstancePermissionSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/ApplicationInstancePermissionKind' + ApplicationInstancePermissionSpec: + title: ApplicationInstancePermissionSpec + required: + - resource + - permission + - grantedTo + type: object + properties: + resource: + $ref: '#/components/schemas/Resource' + permission: + $ref: '#/components/schemas/ResourcePermission' + grantedTo: + type: string + pattern: ^[0-9a-z\_-]+$ + ApplicationInstanceResource: + title: ApplicationInstanceResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/ApplicationInstanceMetadata' + spec: + $ref: '#/components/schemas/ApplicationInstanceSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/ApplicationInstanceKind' + ApplicationInstanceSpec: + title: ApplicationInstanceSpec + required: + - cluster + type: object + properties: + cluster: + type: string + topicPolicyRef: + type: array + items: + type: string + pattern: ^[0-9a-z\_-]+$ + uniqueItems: true + resources: + type: array + items: + $ref: '#/components/schemas/Resource' + uniqueItems: true + serviceAccount: + type: string + ApplicationKind: + title: ApplicationKind + type: string + enum: + - Application + ApplicationMetadata: + title: ApplicationMetadata + required: + - name + type: object + properties: + name: + type: string + pattern: ^[0-9a-z\_-]+$ + ApplicationPolicyMetadata: + title: ApplicationPolicyMetadata + required: + - name + type: object + properties: + name: + type: string + pattern: ^[0-9a-z\_-]+$ + ApplicationPolicySpec: + title: ApplicationPolicySpec + required: + - policies + type: object + properties: + policies: + $ref: '#/components/schemas/Map_PolicyConstraintDto' + ApplicationResource: + title: ApplicationResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/ApplicationMetadata' + spec: + $ref: '#/components/schemas/ApplicationSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/ApplicationKind' + ApplicationSpec: + title: ApplicationSpec + required: + - title + - owner + type: object + properties: + title: + type: string + description: + type: string + owner: + type: string + BadRequest: + title: BadRequest + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + BasicAuth: + title: BasicAuth + required: + - username + - password + - type + type: object + properties: + username: + type: string + minLength: 1 + password: + type: string + type: + type: string + BearerToken: + title: BearerToken + required: + - token + - type + type: object + properties: + token: + type: string + minLength: 1 + type: + type: string + CheckedCertificate: + title: CheckedCertificate + type: object + CleanupPolicy: + title: CleanupPolicy + type: string + enum: + - delete + - compact + - compact,delete + CleanupPolicyFilter: + title: CleanupPolicyFilter + required: + - type + type: object + properties: + oneOf: + type: array + items: + $ref: '#/components/schemas/CleanupPolicy' + type: + type: string + Cluster: + title: Cluster + required: + - clusterId + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + permissions: + type: array + items: + type: string + enum: + - clusterViewBroker + - clusterEditSRCompatibility + - clusterEditBroker + - clusterViewACL + - clusterManageACL + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + Conflict: + title: Conflict + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + Confluent: + title: Confluent + required: + - key + - secret + - confluentEnvironmentId + - confluentClusterId + - type + type: object + properties: + key: + type: string + secret: + type: string + confluentEnvironmentId: + type: string + confluentClusterId: + type: string + type: + type: string + ConfluentLikeSchemaRegistryRequest: + title: ConfluentLikeSchemaRegistryRequest + required: + - url + - type + type: object + properties: + url: + type: string + security: + $ref: '#/components/schemas/ConfluentLikeSchemaRegistrySecurity' + properties: + type: string + ignoreUntrustedCertificate: + type: boolean + type: + type: string + ConfluentLikeSchemaRegistryResponse: + title: ConfluentLikeSchemaRegistryResponse + required: + - id + - url + - security + - ignoreUntrustedCertificate + - type + type: object + properties: + id: + type: string + format: uuid + url: + type: string + security: + $ref: '#/components/schemas/ConfluentLikeSchemaRegistrySecurity' + properties: + type: string + ignoreUntrustedCertificate: + type: boolean + serverCa: + type: array + items: + type: string + type: + type: string + ConfluentLikeSchemaRegistrySecurity: + title: ConfluentLikeSchemaRegistrySecurity + oneOf: + - $ref: '#/components/schemas/BasicAuth' + - $ref: '#/components/schemas/BearerToken' + - $ref: '#/components/schemas/NoSecurity' + - $ref: '#/components/schemas/SSLAuth' + discriminator: + propertyName: type + mapping: + BasicAuth: '#/components/schemas/BasicAuth' + BearerToken: '#/components/schemas/BearerToken' + NoSecurity: '#/components/schemas/NoSecurity' + SSLAuth: '#/components/schemas/SSLAuth' + ConstraintKind: + title: ConstraintKind + type: string + enum: + - Match + - NoneOf + - OneOf + - Range + ConsumerGroup: + title: ConsumerGroup + required: + - clusterId + - consumerGroupPattern + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + consumerGroupPattern: + type: string + permissions: + type: array + items: + type: string + enum: + - consumerGroupCreate + - consumerGroupReset + - consumerGroupDelete + - consumerGroupView + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + ConsumerGroupFilter: + title: ConsumerGroupFilter + oneOf: + - $ref: '#/components/schemas/OnConsumerGroupName' + - $ref: '#/components/schemas/OnState' + discriminator: + propertyName: type + mapping: + OnConsumerGroupName: '#/components/schemas/OnConsumerGroupName' + OnState: '#/components/schemas/OnState' + ConsumerGroupRequest: + title: ConsumerGroupRequest + required: + - page + - itemsPerPage + - sort + type: object + properties: + page: + type: integer + format: int32 + itemsPerPage: + type: integer + format: int32 + filter: + type: array + items: + $ref: '#/components/schemas/ConsumerGroupFilter' + uniqueItems: true + sort: + $ref: '#/components/schemas/ConsumerGroupSort' + descSort: + type: boolean + ConsumerGroupResponse: + title: ConsumerGroupResponse + oneOf: + - $ref: '#/components/schemas/IndexedConsumerGroup' + - $ref: '#/components/schemas/NotIndexedConsumerGroup' + discriminator: + propertyName: type + mapping: + IndexedConsumerGroup: '#/components/schemas/IndexedConsumerGroup' + NotIndexedConsumerGroup: '#/components/schemas/NotIndexedConsumerGroup' + ConsumerGroupSort: + title: ConsumerGroupSort + type: string + enum: + - ByName + - ByState + - ByOverallLag + - ByMaxLagTimeInSeconds + - ByMembers + ConsumerGroupState: + title: ConsumerGroupState + type: string + enum: + - Unknown + - PreparingRebalance + - CompletingRebalance + - Stable + - Dead + - Empty + CreateApiKey: + title: CreateApiKey + required: + - name + - description + type: object + properties: + name: + type: string + description: + type: string + CreateCertificateFromFileRequest: + title: CreateCertificateFromFileRequest + required: + - file + type: object + properties: + file: + type: string + format: binary + jksPassword: + type: string + CreateCertificateRequest: + title: CreateCertificateRequest + required: + - input + type: object + properties: + input: + type: string + CreateServiceAccount: + title: CreateServiceAccount + required: + - name + - description + type: object + properties: + name: + type: string + pattern: ^[0-9a-zA-Z_\-]+$ + description: + type: string + Credentials: + title: Credentials + required: + - accessKeyId + - secretKey + - type + type: object + properties: + accessKeyId: + type: string + minLength: 1 + secretKey: + type: string + minLength: 1 + type: + type: string + DecodedCertificate: + title: DecodedCertificate + required: + - id + - version + - serialNumber + - issuerDN + - subjectDN + - notBefore + - notAfter + type: object + properties: + id: + type: integer + format: int32 + version: + type: integer + format: int32 + serialNumber: + type: integer + issuerDN: + type: string + subjectDN: + type: string + notBefore: + type: string + format: date-time + notAfter: + type: string + format: date-time + ExplainQuery: + title: ExplainQuery + required: + - statementText + - topology + - executionPlan + - state + type: object + properties: + statementText: + type: string + sources: + type: array + items: + type: string + sinks: + type: array + items: + type: string + topology: + type: string + executionPlan: + type: string + state: + type: string + windowType: + type: string + fields: + type: array + items: + $ref: '#/components/schemas/Field' + Field: + title: Field + required: + - name + - type + type: object + properties: + name: + type: string + type: + type: string + fields: + type: array + items: + $ref: '#/components/schemas/Field' + Forbidden: + title: Forbidden + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + FromContext: + title: FromContext + required: + - type + type: object + properties: + profile: + type: string + minLength: 1 + type: + type: string + FromRole: + title: FromRole + required: + - role + - type + type: object + properties: + role: + type: string + minLength: 1 + type: + type: string + Gateway: + title: Gateway + required: + - url + - user + - password + - virtualCluster + - type + type: object + properties: + url: + type: string + user: + type: string + password: + type: string + virtualCluster: + type: string + type: + type: string + GlueSchemaRegistryRequest: + title: GlueSchemaRegistryRequest + required: + - region + - security + - type + type: object + properties: + registryName: + type: string + minLength: 1 + region: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/AmazonSecurity' + type: + type: string + GlueSchemaRegistryResponse: + title: GlueSchemaRegistryResponse + required: + - id + - region + - security + - type + type: object + properties: + id: + type: string + format: uuid + registryName: + type: string + minLength: 1 + region: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/AmazonSecurity' + type: + type: string + HideInternal: + title: HideInternal + required: + - type + type: object + properties: + type: + type: string + HideStream: + title: HideStream + required: + - type + type: object + properties: + type: + type: string + IAMAnywhere: + title: IAMAnywhere + required: + - trustAnchorArn + - profileArn + - roleArn + - certificate + - privateKey + - type + type: object + properties: + trustAnchorArn: + type: string + minLength: 1 + profileArn: + type: string + minLength: 1 + roleArn: + type: string + minLength: 1 + certificate: + type: string + minLength: 1 + privateKey: + type: string + minLength: 1 + type: + type: string + IndexedConsumerGroup: + title: IndexedConsumerGroup + required: + - name + - state + - members + - type + type: object + properties: + name: + type: string + state: + $ref: '#/components/schemas/ConsumerGroupState' + members: + type: integer + format: int32 + overallLag: + type: integer + format: int64 + topics: + type: array + items: + type: string + uniqueItems: true + maxLagTimeInSeconds: + type: integer + format: int64 + type: + type: string + IndexedTopic: + title: IndexedTopic + required: + - name + - replicationFactor + - partitionCount + - recordCount + - produceRate + - type + type: object + properties: + name: + type: string + replicationFactor: + type: integer + format: int32 + partitionCount: + type: integer + format: int32 + recordCount: + type: integer + format: int64 + topicSize: + type: integer + cleanupPolicy: + $ref: '#/components/schemas/CleanupPolicy' + retentionInSize: + type: integer + format: int64 + retentionInMs: + type: integer + format: int64 + minIsr: + type: integer + format: int32 + tags: + type: array + items: + $ref: '#/components/schemas/TagInfo' + uniqueItems: true + lastActivityAt: + type: string + format: date-time + produceRate: + type: integer + format: int32 + type: + type: string + Interceptor: + title: Interceptor + required: + - name + - pluginClass + - priority + - config + type: object + properties: + name: + type: string + pluginClass: + type: string + priority: + type: integer + format: int32 + config: {} + KafkaConnect: + title: KafkaConnect + required: + - clusterId + - connectClusterId + - connectorNamePattern + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + connectClusterId: + type: string + pattern: ^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}|\*)$ + connectorNamePattern: + type: string + permissions: + type: array + items: + type: string + enum: + - kafkaConnectorViewConfig + - kafkaConnectorStatus + - kafkaConnectorEditConfig + - kafkaConnectorDelete + - kafkaConnectorUpdate + - kafkaConnectorCreate + - kafkaConnectPauseResume + - kafkaConnectRestart + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + KafkaConnectBasicAuth: + title: KafkaConnectBasicAuth + required: + - username + - password + - type + type: object + properties: + username: + type: string + minLength: 1 + password: + type: string + type: + type: string + KafkaConnectBearerToken: + title: KafkaConnectBearerToken + required: + - token + - type + type: object + properties: + token: + type: string + minLength: 1 + type: + type: string + KafkaConnectNoSecurity: + title: KafkaConnectNoSecurity + required: + - type + type: object + properties: + type: + type: string + KafkaConnectSSLAuth: + title: KafkaConnectSSLAuth + required: + - key + - certificateChain + - type + type: object + properties: + key: + type: string + minLength: 1 + certificateChain: + type: string + minLength: 1 + type: + type: string + KafkaConnectSecurity: + title: KafkaConnectSecurity + oneOf: + - $ref: '#/components/schemas/KafkaConnectBasicAuth' + - $ref: '#/components/schemas/KafkaConnectBearerToken' + - $ref: '#/components/schemas/KafkaConnectNoSecurity' + - $ref: '#/components/schemas/KafkaConnectSSLAuth' + discriminator: + propertyName: type + mapping: + KafkaConnectBasicAuth: '#/components/schemas/KafkaConnectBasicAuth' + KafkaConnectBearerToken: '#/components/schemas/KafkaConnectBearerToken' + KafkaConnectNoSecurity: '#/components/schemas/KafkaConnectNoSecurity' + KafkaConnectSSLAuth: '#/components/schemas/KafkaConnectSSLAuth' + KafkaConnectUpsert: + title: KafkaConnectUpsert + required: + - url + - name + type: object + properties: + url: + type: string + slug: + type: string + minLength: 1 + name: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/KafkaConnectSecurity' + headers: + type: string + ignoreUntrustedCertificate: + type: boolean + KafkaConnectWithId: + title: KafkaConnectWithId + required: + - id + - slug + - url + - name + - security + - ignoreUntrustedCertificate + type: object + properties: + id: + type: string + format: uuid + slug: + type: string + minLength: 1 + url: + type: string + name: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/KafkaConnectSecurity' + headers: + type: string + ignoreUntrustedCertificate: + type: boolean + KafkaFlavor: + title: KafkaFlavor + oneOf: + - $ref: '#/components/schemas/Aiven' + - $ref: '#/components/schemas/Confluent' + - $ref: '#/components/schemas/Gateway' + discriminator: + propertyName: type + mapping: + Aiven: '#/components/schemas/Aiven' + Confluent: '#/components/schemas/Confluent' + Gateway: '#/components/schemas/Gateway' + KsqlDB: + title: KsqlDB + required: + - clusterId + - ksqlDBServerSlug + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + ksqlDBServerSlug: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + permissions: + type: array + items: + type: string + enum: + - ksqldbAccess + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + KsqlDBBasicAuth: + title: KsqlDBBasicAuth + required: + - username + - password + - type + type: object + properties: + username: + type: string + minLength: 1 + password: + type: string + type: + type: string + KsqlDBBearerToken: + title: KsqlDBBearerToken + required: + - token + - type + type: object + properties: + token: + type: string + minLength: 1 + type: + type: string + KsqlDBNoSecurity: + title: KsqlDBNoSecurity + required: + - type + type: object + properties: + type: + type: string + KsqlDBQuery: + title: KsqlDBQuery + required: + - ksql + type: object + properties: + ksql: + type: string + properties: + $ref: '#/components/schemas/Map_String' + KsqlDBSSLAuth: + title: KsqlDBSSLAuth + required: + - key + - certificateChain + - type + type: object + properties: + key: + type: string + minLength: 1 + certificateChain: + type: string + minLength: 1 + type: + type: string + KsqlDBSecurity: + title: KsqlDBSecurity + oneOf: + - $ref: '#/components/schemas/KsqlDBBasicAuth' + - $ref: '#/components/schemas/KsqlDBBearerToken' + - $ref: '#/components/schemas/KsqlDBNoSecurity' + - $ref: '#/components/schemas/KsqlDBSSLAuth' + discriminator: + propertyName: type + mapping: + KsqlDBBasicAuth: '#/components/schemas/KsqlDBBasicAuth' + KsqlDBBearerToken: '#/components/schemas/KsqlDBBearerToken' + KsqlDBNoSecurity: '#/components/schemas/KsqlDBNoSecurity' + KsqlDBSSLAuth: '#/components/schemas/KsqlDBSSLAuth' + KsqlDBStatement: + title: KsqlDBStatement + required: + - ksql + type: object + properties: + ksql: + type: string + KsqlDBUpsert: + title: KsqlDBUpsert + required: + - url + - name + type: object + properties: + url: + type: string + slug: + type: string + minLength: 1 + name: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/KsqlDBSecurity' + headers: + type: string + ignoreUntrustedCertificate: + type: boolean + KsqlDBWithId: + title: KsqlDBWithId + required: + - id + - slug + - url + - name + - security + - ignoreUntrustedCertificate + type: object + properties: + id: + type: string + format: uuid + slug: + type: string + minLength: 1 + url: + type: string + name: + type: string + minLength: 1 + security: + $ref: '#/components/schemas/KsqlDBSecurity' + headers: + type: string + ignoreUntrustedCertificate: + type: boolean + KsqlServerInfo: + title: KsqlServerInfo + required: + - name + - slug + type: object + properties: + name: + type: string + slug: + type: string + version: + type: string + tableCount: + type: integer + format: int32 + streamCount: + type: integer + format: int32 + queryCount: + type: integer + format: int32 + error: + type: string + List_String: + title: List_String + oneOf: + - $ref: '#/components/schemas/Nil' + - type: array + items: + type: string + Map_Double: + title: Map_Double + type: object + additionalProperties: + type: number + format: double + Map_Int: + title: Map_Int + type: object + additionalProperties: + type: integer + format: int32 + Map_PolicyConstraintDto: + title: Map_PolicyConstraintDto + type: object + additionalProperties: + $ref: '#/components/schemas/PolicyConstraintDto' + Map_String: + title: Map_String + type: object + additionalProperties: + type: string + Map_Type_List_ResourcePermissions: + title: Map_Type_List_ResourcePermissions + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + Map_Type_Type: + title: Map_Type_Type + type: object + additionalProperties: + type: string + Match: + title: Match + required: + - constraint + - required + - pattern + type: object + properties: + constraint: + $ref: '#/components/schemas/ConstraintKind' + required: + type: boolean + pattern: + type: string + Nil: + title: Nil + type: object + NoSecurity: + title: NoSecurity + required: + - type + type: object + properties: + type: + type: string + NoneOf: + title: NoneOf + required: + - constraint + - required + type: object + properties: + constraint: + $ref: '#/components/schemas/ConstraintKind' + required: + type: boolean + values: + type: array + items: + type: string + NotFound: + title: NotFound + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + NotIndexedConsumerGroup: + title: NotIndexedConsumerGroup + required: + - name + - type + type: object + properties: + name: + type: string + type: + type: string + NotIndexedTopic: + title: NotIndexedTopic + required: + - name + - type + type: object + properties: + name: + type: string + type: + type: string + OnConsumerGroupName: + title: OnConsumerGroupName + required: + - contains + - type + type: object + properties: + contains: + type: string + type: + type: string + OnState: + title: OnState + required: + - type + type: object + properties: + oneOf: + type: array + items: + $ref: '#/components/schemas/ConsumerGroupState' + type: + type: string + OneOf: + title: OneOf + required: + - constraint + - required + type: object + properties: + constraint: + $ref: '#/components/schemas/ConstraintKind' + required: + type: boolean + values: + type: array + items: + type: string + OperationStates: + title: OperationStates + type: object + properties: + Unknown: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + All: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Read: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Write: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Create: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Delete: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Alter: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Describe: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + ClusterAction: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + DescribeConfigs: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + AlterConfigs: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + IdempotentWrite: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + CreateTokens: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + DescribeTokens: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + additionalProperties: + $ref: '#/components/schemas/AclPermissionTypeForAccessControlEntry' + Page_ConsumerGroupResponse: + title: Page_ConsumerGroupResponse + required: + - page + - totalPages + - perPage + - totalElements + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/ConsumerGroupResponse' + page: + type: integer + format: int32 + totalPages: + type: integer + format: int32 + perPage: + type: integer + format: int32 + totalElements: + type: integer + format: int64 + Page_TopicResponse: + title: Page_TopicResponse + required: + - page + - totalPages + - perPage + - totalElements + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/TopicResponse' + page: + type: integer + format: int32 + totalPages: + type: integer + format: int32 + perPage: + type: integer + format: int32 + totalElements: + type: integer + format: int64 + PatternTypeForResourcePattern: + title: PatternTypeForResourcePattern + type: string + enum: + - Literal + - Prefixed + - Unknown + Platform: + title: Platform + required: + - resourceType + type: object + properties: + permissions: + type: array + items: + type: string + enum: + - auditLogView + - taasView + - taasManage + - certificateManage + - userManage + - clusterConnectionsManage + - notificationChannelManage + - datamaskingView + - testingView + - datamaskingManage + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + Plugin: + title: Plugin + required: + - plugin + - pluginId + - tags + type: object + properties: + plugin: + type: string + pluginId: + type: string + tags: + $ref: '#/components/schemas/Map_String' + PluginWithReadme: + title: PluginWithReadme + required: + - plugin + - pluginId + - tags + - readme + type: object + properties: + plugin: + type: string + pluginId: + type: string + tags: + $ref: '#/components/schemas/Map_String' + readme: + type: string + PolicyConstraintDto: + title: PolicyConstraintDto + oneOf: + - $ref: '#/components/schemas/Match' + - $ref: '#/components/schemas/NoneOf' + - $ref: '#/components/schemas/OneOf' + - $ref: '#/components/schemas/Range' + discriminator: + propertyName: constraint + mapping: + Match: '#/components/schemas/Match' + NoneOf: '#/components/schemas/NoneOf' + OneOf: '#/components/schemas/OneOf' + Range: '#/components/schemas/Range' + PublicCreateGroupRequest: + title: PublicCreateGroupRequest + required: + - name + - groupId + type: object + properties: + name: + type: string + description: + type: string + groupId: + type: string + pattern: ^[0-9a-z\_-]+$ + externalGroups: + type: array + items: + type: string + PublicGroupOfUser: + title: PublicGroupOfUser + required: + - name + - groupId + type: object + properties: + name: + type: string + groupId: + type: string + pattern: ^[0-9a-z\_-]+$ + PublicGroupResponse: + title: PublicGroupResponse + required: + - groupId + - name + - isAdmin + type: object + properties: + groupId: + type: string + pattern: ^[0-9a-z\_-]+$ + name: + type: string + description: + type: string + users: + type: array + items: + $ref: '#/components/schemas/PublicUserOfGroup' + externalGroups: + type: array + items: + type: string + isAdmin: + type: boolean + PublicSharedClusterResponse: + title: PublicSharedClusterResponse + required: + - technicalId + - name + - bootstrapServers + - ignoreUntrustedCertificate + - createdAt + - updatedAt + type: object + properties: + technicalId: + type: string + name: + type: string + minLength: 1 + bootstrapServers: + type: string + zookeeperServer: + type: string + properties: + type: string + color: + type: string + icon: + type: string + minLength: 1 + schemaRegistry: + $ref: '#/components/schemas/SharedSchemaRegistryResponseV2' + kafkaConnects: + type: array + items: + $ref: '#/components/schemas/KafkaConnectWithId' + uniqueItems: true + ignoreUntrustedCertificate: + type: boolean + accessCert: + type: string + accessKey: + type: string + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + amazonSecurity: + $ref: '#/components/schemas/AmazonSecurity' + kafkaFlavor: + $ref: '#/components/schemas/KafkaFlavor' + ksqlDBs: + type: array + items: + $ref: '#/components/schemas/KsqlDBWithId' + uniqueItems: true + PublicUserOfGroup: + title: PublicUserOfGroup + required: + - email + - externalMapping + type: object + properties: + email: + type: string + externalMapping: + type: boolean + PublicWithAllDetailsAndGroup: + title: PublicWithAllDetailsAndGroup + required: + - userId + - fullName + type: object + properties: + userId: + type: string + firstName: + type: string + lastName: + type: string + fullName: + type: string + pictureUrl: + type: string + phoneNumber: + type: string + country: + type: string + platformRole: + type: string + groups: + type: array + items: + $ref: '#/components/schemas/PublicGroupOfUser' + uniqueItems: true + Query: + title: Query + required: + - queryString + - id + - statusCount + - queryType + - state + type: object + properties: + queryString: + type: string + sinks: + type: array + items: + type: string + sinkKafkaTopics: + type: array + items: + type: string + id: + type: string + statusCount: + $ref: '#/components/schemas/Map_Int' + queryType: + type: string + state: + type: string + Range: + title: Range + required: + - constraint + - required + - min + - max + type: object + properties: + constraint: + $ref: '#/components/schemas/ConstraintKind' + required: + type: boolean + min: + type: integer + format: int64 + max: + type: integer + format: int64 + Resource: + title: Resource + required: + - type + - name + - patternType + type: object + properties: + type: + $ref: '#/components/schemas/ResourceType' + name: + type: string + patternType: + $ref: '#/components/schemas/ResourcePatternType' + ResourcePattern: + title: ResourcePattern + required: + - resourceType + - name + - patternType + type: object + properties: + resourceType: + $ref: '#/components/schemas/ResourceTypeForResourcePattern' + name: + type: string + patternType: + $ref: '#/components/schemas/PatternTypeForResourcePattern' + ResourcePatternType: + title: ResourcePatternType + type: string + enum: + - LITERAL + - PREFIXED + ResourcePermission: + title: ResourcePermission + type: string + enum: + - READ + - WRITE + ResourcePermissions: + title: ResourcePermissions + oneOf: + - $ref: '#/components/schemas/Cluster' + - $ref: '#/components/schemas/ConsumerGroup' + - $ref: '#/components/schemas/KafkaConnect' + - $ref: '#/components/schemas/KsqlDB' + - $ref: '#/components/schemas/Platform' + - $ref: '#/components/schemas/Subject' + - $ref: '#/components/schemas/Topic' + discriminator: + propertyName: resourceType + ResourceType: + title: ResourceType + type: string + enum: + - TOPIC + - GROUP + - SUBJECT + ResourceTypeForResourcePattern: + title: ResourceTypeForResourcePattern + type: string + enum: + - Unknown + - Topic + - Group + - Cluster + - TransactionalId + - DelegationToken + - User + SSLAuth: + title: SSLAuth + required: + - key + - certificateChain + - type + type: object + properties: + key: + type: string + minLength: 1 + certificateChain: + type: string + minLength: 1 + type: + type: string + SchemaRegistryRequest: + title: SchemaRegistryRequest + oneOf: + - $ref: '#/components/schemas/ConfluentLikeSchemaRegistryRequest' + - $ref: '#/components/schemas/GlueSchemaRegistryRequest' + discriminator: + propertyName: type + mapping: + ConfluentLikeSchemaRegistryRequest: '#/components/schemas/ConfluentLikeSchemaRegistryRequest' + GlueSchemaRegistryRequest: '#/components/schemas/GlueSchemaRegistryRequest' + ServerError: + title: ServerError + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + ServiceAccount: + title: ServiceAccount + required: + - resourceId + - internalId + - serviceName + - description + type: object + properties: + resourceId: + type: string + internalId: + type: integer + format: int32 + serviceName: + type: string + description: + type: string + SharedSchemaRegistryResponseV2: + title: SharedSchemaRegistryResponseV2 + oneOf: + - $ref: '#/components/schemas/ConfluentLikeSchemaRegistryResponse' + - $ref: '#/components/schemas/GlueSchemaRegistryResponse' + discriminator: + propertyName: type + mapping: + ConfluentLikeSchemaRegistryResponse: '#/components/schemas/ConfluentLikeSchemaRegistryResponse' + GlueSchemaRegistryResponse: '#/components/schemas/GlueSchemaRegistryResponse' + SourceDescription: + title: SourceDescription + required: + - name + - topic + - type + - keyFormat + - valueFormat + - statement + - statistics + - readQueriesCount + - writeQueriesCount + type: object + properties: + name: + type: string + windowType: + type: string + topic: + type: string + type: + type: string + keyFormat: + type: string + valueFormat: + type: string + sourceConstraints: + type: array + items: + type: string + statement: + type: string + statistics: + $ref: '#/components/schemas/Map_Double' + readQueriesCount: + type: integer + format: int32 + writeQueriesCount: + type: integer + format: int32 + fields: + type: array + items: + $ref: '#/components/schemas/Field' + Subject: + title: Subject + required: + - clusterId + - subjectPattern + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + subjectPattern: + type: string + permissions: + type: array + items: + type: string + enum: + - subjectCreateUpdate + - subjectDelete + - subjectEditCompatibility + - subjectView + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + Table: + title: Table + required: + - name + - topic + - keyFormat + - valueFormat + - reads + - writes + - isWindowed + type: object + properties: + name: + type: string + topic: + type: string + keyFormat: + type: string + valueFormat: + type: string + reads: + type: integer + format: int32 + writes: + type: integer + format: int32 + isWindowed: + type: boolean + TagInfo: + title: TagInfo + required: + - id + - name + - color + type: object + properties: + id: + type: string + format: uuid + name: + type: string + color: + type: string + TagsFilter: + title: TagsFilter + required: + - type + type: object + properties: + atLeast: + type: array + items: + type: string + type: + type: string + TlsNotSupported: + title: TlsNotSupported + type: object + TlsStatus: + title: TlsStatus + oneOf: + - $ref: '#/components/schemas/CheckedCertificate' + - $ref: '#/components/schemas/TlsNotSupported' + - $ref: '#/components/schemas/UncheckedCertificate' + - $ref: '#/components/schemas/UnexpectedStatus' + - $ref: '#/components/schemas/UnreachableTarget' + TlsTestRequest: + title: TlsTestRequest + required: + - host + - port + type: object + properties: + host: + type: string + port: + type: integer + format: int32 + TlsTestResponse: + title: TlsTestResponse + required: + - status + type: object + properties: + status: + $ref: '#/components/schemas/TlsStatus' + TooManyRequest: + title: TooManyRequest + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + Topic: + title: Topic + required: + - clusterId + - topicPattern + - resourceType + type: object + properties: + clusterId: + type: string + pattern: ^([0-9a-z\-]+|\*)$ + topicPattern: + type: string + permissions: + type: array + items: + type: string + enum: + - topicViewConfig + - topicEmpty + - topicConsume + - topicProduce + - topicEditConfig + - topicCreate + - topicAddPartition + - topicDelete + uniqueItems: true + resourceType: + type: string + enum: + - Platform + - Cluster + - Topic + - ConsumerGroup + - KafkaConnect + - Subject + - KsqlDB + TopicApplyResult: + title: TopicApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/TopicResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + TopicKind: + title: TopicKind + type: string + enum: + - Topic + TopicListFilter: + title: TopicListFilter + oneOf: + - $ref: '#/components/schemas/CleanupPolicyFilter' + - $ref: '#/components/schemas/HideInternal' + - $ref: '#/components/schemas/HideStream' + - $ref: '#/components/schemas/TagsFilter' + - $ref: '#/components/schemas/TopicNameFilter' + discriminator: + propertyName: type + mapping: + CleanupPolicyFilter: '#/components/schemas/CleanupPolicyFilter' + HideInternal: '#/components/schemas/HideInternal' + HideStream: '#/components/schemas/HideStream' + TagsFilter: '#/components/schemas/TagsFilter' + TopicNameFilter: '#/components/schemas/TopicNameFilter' + TopicListRequest: + title: TopicListRequest + required: + - page + - itemsPerPage + - sort + type: object + properties: + page: + type: integer + format: int32 + itemsPerPage: + type: integer + format: int32 + filter: + type: array + items: + $ref: '#/components/schemas/TopicListFilter' + uniqueItems: true + sort: + $ref: '#/components/schemas/TopicListSort' + descSort: + type: boolean + TopicListSort: + title: TopicListSort + type: string + enum: + - ByName + - ByReplicationFactor + - ByNumPartition + - ByMessageCount + - ByTopicSizeByte + - ByCleanupPolicy + - ByRetentionTimes + - ByMinIsr + - ByLastActivityAt + TopicMetadata: + title: TopicMetadata + required: + - name + - cluster + type: object + properties: + name: + type: string + cluster: + type: string + TopicNameFilter: + title: TopicNameFilter + required: + - contains + - type + type: object + properties: + contains: + type: string + type: + type: string + TopicPolicyApplyResult: + title: TopicPolicyApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/TopicPolicyResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + TopicPolicyKind: + title: TopicPolicyKind + type: string + enum: + - TopicPolicy + TopicPolicyResource: + title: TopicPolicyResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/ApplicationPolicyMetadata' + spec: + $ref: '#/components/schemas/ApplicationPolicySpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicPolicyKind' + TopicResource: + title: TopicResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/TopicMetadata' + spec: + $ref: '#/components/schemas/TopicSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicKind' + TopicResponse: + title: TopicResponse + oneOf: + - $ref: '#/components/schemas/IndexedTopic' + - $ref: '#/components/schemas/NotIndexedTopic' + discriminator: + propertyName: type + mapping: + IndexedTopic: '#/components/schemas/IndexedTopic' + NotIndexedTopic: '#/components/schemas/NotIndexedTopic' + TopicSpec: + title: TopicSpec + required: + - partitions + - replicationFactor + - configs + type: object + properties: + partitions: + type: integer + format: int32 + replicationFactor: + type: integer + format: int32 + configs: + $ref: '#/components/schemas/Map_Type_Type' + Unauthorized: + title: Unauthorized + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + UncheckedCertificate: + title: UncheckedCertificate + type: object + UnexpectedStatus: + title: UnexpectedStatus + type: object + UnreachableTarget: + title: UnreachableTarget + type: object + UpdateGroupRequest: + title: UpdateGroupRequest + required: + - name + type: object + properties: + name: + type: string + description: + type: string + externalGroups: + type: array + items: + type: string + UpdateInterceptor: + title: UpdateInterceptor + required: + - pluginClass + - priority + - config + type: object + properties: + pluginClass: + type: string + priority: + type: integer + format: int32 + config: {} + UpdateUserRequest: + title: UpdateUserRequest + required: + - email + type: object + properties: + lastName: + type: string + firstName: + type: string + email: + type: string + UpsertResult: + title: UpsertResult + type: string + enum: + - Created + - Updated + - NotChanged + UpsertSharedClusterRequest: + title: UpsertSharedClusterRequest + required: + - name + - bootstrapServers + type: object + properties: + name: + type: string + minLength: 1 + bootstrapServers: + type: string + properties: + type: string + color: + type: string + icon: + type: string + minLength: 1 + schemaRegistry: + $ref: '#/components/schemas/SchemaRegistryRequest' + kafkaConnects: + type: array + items: + $ref: '#/components/schemas/KafkaConnectUpsert' + uniqueItems: true + ignoreUntrustedCertificate: + type: boolean + amazonSecurity: + $ref: '#/components/schemas/AmazonSecurity' + kafkaFlavor: + $ref: '#/components/schemas/KafkaFlavor' + ksqlDBs: + type: array + items: + $ref: '#/components/schemas/KsqlDBUpsert' + uniqueItems: true + UserPermissions: + title: UserPermissions + required: + - groups + type: object + properties: + user: + type: array + items: + $ref: '#/components/schemas/ResourcePermissions' + groups: + $ref: '#/components/schemas/Map_Type_List_ResourcePermissions' + Version: + title: Version + type: string + enum: + - v1 + securitySchemes: + httpAuth: + type: http + scheme: bearer +x-tagGroups: +- name: 🐺 Conduktor API + tags: + - Introduction + - Authentication + - Kinds + - Api Groups + - Versioning + - Conventions +- name: '👥 iam/v1 ' + tags: + - users + - groups + - permissions +- name: 🏆 console/v1 + tags: + - clusters + - certificates +- name: 🔥 kafka/v1 + tags: + - topic + - consumergroup + - connector + - acls + - service-accounts + - ksqlDBs +- name: 🔥 kafka/v2 + tags: + - cli_topic_kafka_v2 +- name: '🚀 self-serve/v1 ' + tags: + - cli_application_self-serve_v1 + - cli_application-instance_self-serve_v1 + - cli_application-instance-permission_self-serve_v1 + - cli_topic-policy_self-serve_v1 +- name: 🌉 gateway/v1 + tags: + - interceptors diff --git a/schema/kind.go b/schema/kind.go new file mode 100644 index 0000000..51d3076 --- /dev/null +++ b/schema/kind.go @@ -0,0 +1,138 @@ +package schema + +import ( + _ "embed" + "encoding/json" + "fmt" + "github.com/conduktor/ctl/resource" + "os" + "regexp" + "strconv" + "strings" +) + +type KindVersion struct { + ListPath string + Name string + ParentPathParam []string +} + +type Kind struct { + Versions map[int]KindVersion +} + +type KindCatalog = map[string]Kind + +//go:embed default-schema.json +var defaultByteSchema []byte + +func DefaultKind() KindCatalog { + var result KindCatalog + err := json.Unmarshal(defaultByteSchema, &result) + if err != nil { + panic(err) + } + return result +} + +func NewKind(version int, kindVersion *KindVersion) Kind { + return Kind{ + Versions: map[int]KindVersion{version: *kindVersion}, + } +} + +func extractVersionFromApiVersion(apiVersion string) int { + // we extract the number after v in a apiVersion + // e.g. v1 1 + // e.g. v42-> 42 + + re := regexp.MustCompile(`v(\d+)`) + matches := re.FindStringSubmatch(apiVersion) + + if len(matches) < 2 { + fmt.Fprintf(os.Stderr, "Invalid api version format \"%s\", could not extract version\n", apiVersion) + os.Exit(1) + } + + version, err := strconv.Atoi(matches[1]) + if err != nil { + panic(fmt.Sprintf("Invalid version number in apiVersion: %s", matches[1])) + } + + return version +} + +func (kind *Kind) AddVersion(version int, kindVersion *KindVersion) error { + name := kind.GetName() + if name != kindVersion.Name { + return fmt.Errorf("Adding kind version of kind %s to different kind %s", kindVersion.Name, name) + } + kind.Versions[version] = *kindVersion + return nil +} + +func (kind *Kind) GetFlag() []string { + kindVersion := kind.GetLatestKindVersion() + result := make([]string, len(kindVersion.ParentPathParam)) + for i, param := range kindVersion.ParentPathParam { + result[i] = param + } + return result +} + +func (kind *Kind) MaxVersion() int { + maxVersion := -1 + for version := range kind.Versions { + if version > maxVersion { + maxVersion = version + } + } + return maxVersion +} + +func (kind *Kind) GetLatestKindVersion() *KindVersion { + kindVersion, ok := kind.Versions[kind.MaxVersion()] + if !ok { + panic("Max numVersion on kind return a numVersion that does not exist") + } + return &kindVersion +} + +func (Kind *Kind) GetName() string { + for _, kindVersion := range Kind.Versions { + return kindVersion.Name + } + panic("No kindVersion in kind") //should never happen +} + +func (kind *Kind) ListPath(parentPathValues []string) string { + kindVersion := kind.GetLatestKindVersion() + if len(parentPathValues) != len(kindVersion.ParentPathParam) { + panic(fmt.Sprintf("For kind %s expected %d parent apiVersion values, got %d", kindVersion.Name, len(kindVersion.ParentPathParam), len(parentPathValues))) + } + path := kindVersion.ListPath + for i, pathValue := range parentPathValues { + path = strings.Replace(path, fmt.Sprintf("{%s}", kindVersion.ParentPathParam[i]), pathValue, 1) + } + return path +} + +func (kind *Kind) DescribePath(parentPathValues []string, name string) string { + return kind.ListPath(parentPathValues) + "/" + name +} + +func (kind *Kind) ApplyPath(resource *resource.Resource) (string, error) { + kindVersion, ok := kind.Versions[extractVersionFromApiVersion(resource.Version)] + if !ok { + return "", fmt.Errorf("Could not find version %s for kind %s", resource.Version, resource.Kind) + } + parentPathValues := make([]string, len(kindVersion.ParentPathParam)) + var err error + for i, param := range kindVersion.ParentPathParam { + parentPathValues[i], err = resource.StringFromMetadata(param) + if err != nil { + return "", err + } + } + return kind.ListPath(parentPathValues), nil +} diff --git a/schema/kind_test.go b/schema/kind_test.go new file mode 100644 index 0000000..19820f2 --- /dev/null +++ b/schema/kind_test.go @@ -0,0 +1,88 @@ +package schema + +import ( + "testing" +) + +func TestKindGetFlag(t *testing.T) { + t.Run("converts parent parameters to flags", func(t *testing.T) { + + kind := Kind{ + Versions: map[int]KindVersion{ + 1: { + ParentPathParam: []string{"param-1", "param-2", "param-3"}, + }, + }, + } + + got := kind.GetFlag() + want := []string{"param-1", "param-2", "param-3"} + + if len(got) != len(want) { + t.Fatalf("got %d flags, want %d", len(got), len(want)) + } + + for i, flag := range got { + if flag != want[i] { + t.Errorf("got flag %q at index %d, want %q", flag, i, want[i]) + } + } + }) +} + +func TestKindGetFlagWhenNoFlag(t *testing.T) { + t.Run("converts parent parameters to flags", func(t *testing.T) { + kind := Kind{ + Versions: map[int]KindVersion{ + 1: { + ParentPathParam: []string{}, + }, + }, + } + + got := kind.GetFlag() + + if len(got) != 0 { + t.Fatalf("got %d flags, want %d", len(got), 0) + } + }) +} + +func TestKindListPath(t *testing.T) { + t.Run("replaces parent parameters in ListPath", func(t *testing.T) { + kind := Kind{ + Versions: map[int]KindVersion{ + 1: { + ListPath: "/ListPath/{param-1}/{param-2}", + ParentPathParam: []string{"param-1", "param-2"}, + }, + }, + } + + got := kind.ListPath([]string{"value1", "value2"}) + want := "/ListPath/value1/value2" + + if got != want { + t.Errorf("got ListPath %q, want %q", got, want) + } + }) + + t.Run("panics when parent paths and parameters length mismatch", func(t *testing.T) { + kind := Kind{ + Versions: map[int]KindVersion{ + 1: { + ListPath: "/ListPath/{param1}/{param2}", + ParentPathParam: []string{"param1", "param2"}, + }, + }, + } + + defer func() { + if r := recover(); r == nil { + t.Errorf("The code did not panic") + } + }() + + kind.ListPath([]string{"value1"}) + }) +} diff --git a/schema/missing_field_in_metadata.yaml b/schema/missing_field_in_metadata.yaml new file mode 100644 index 0000000..dadb106 --- /dev/null +++ b/schema/missing_field_in_metadata.yaml @@ -0,0 +1,216 @@ +openapi: 3.0.3 +info: + title: Conduktor Public API + version: 0.0.1-SNAPSHOT + summary: The public API to interact with Conduktor platform. + contact: + email: contact@conduktor.io + url: https://docs.conduktor.io +tags: +- name: Introduction + description: |- + Conduktor enables you to accelerate time-to-market and boost the productivity of teams interacting with Kafka through a centralized interface. All Kafka providers are supported including Confluent, AWS MSK, Aiven and open-source Apache Kafka. + + Get started with Conduktor [self-hosted](https://docs.conduktor.io/platform/installation/get-started/docker/) today. Setup takes only a few minutes. +- name: Description + description: |- + The Conduktor REST API can be used to manage your Conduktor organizations Users, Groups and their associated Permissions. Additionally, it can be used to interact with Kafka resources that are added to your organization such as Clusters and Certificates. + + The APIs have predictable resource-oriented URLs. All requests and responses are in JSON and should have their `content-type` header set to `application/json` +- name: Authentication + description: Authentication to the API requires a token set in the **authorization** + header. This token can be generated from within the Admin > API Keys section of + your Conduktor deployment. +paths: + /public/v1/cluster/{cluster}/sa/{sa}/topic: + get: + tags: + - topic + - cli_topic_kafka_v1 + operationId: listTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicResource' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_topic_kafka_v1 + operationId: applyTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicApplyResult' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-topic","cluster":"my-cluster"},"spec":{"partitions":1,"replicationFactor":1,"configs":{}},"apiVersion":"v1","kind":"Topic"}' \ + --location \ + --max-redirs 32 +components: + schemas: + BadRequest: + title: BadRequest + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + TopicResource: + title: TopicResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/TopicMetadata' + spec: + $ref: '#/components/schemas/TopicSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicKind' + TopicMetadata: + title: TopicMetadata + required: + - name + - cluster + type: object + properties: + name: + type: string + cluster: + type: string + TopicSpec: + title: TopicSpec + required: + - partitions + - replicationFactor + - configs + type: object + properties: + partitions: + type: integer + format: int32 + replicationFactor: + type: integer + format: int32 + configs: + $ref: '#/components/schemas/Map_Type_Type' + Map_Type_Type: + title: Map_Type_Type + type: object + additionalProperties: + type: string + Version: + title: Version + type: string + enum: + - v1 + - v2 + TopicKind: + title: TopicKind + type: string + enum: + - Topic + TopicApplyResult: + title: TopicApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/TopicResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + UpsertResult: + title: UpsertResult + type: string + enum: + - Created + - Updated + - NotChanged diff --git a/schema/multiple_version.yaml b/schema/multiple_version.yaml new file mode 100644 index 0000000..c9fe827 --- /dev/null +++ b/schema/multiple_version.yaml @@ -0,0 +1,419 @@ +openapi: 3.0.3 +info: + title: Conduktor Public API + version: 0.0.1-SNAPSHOT + summary: The public API to interact with Conduktor platform. + contact: + email: contact@conduktor.io + url: https://docs.conduktor.io +tags: +- name: Introduction + description: |- + Conduktor enables you to accelerate time-to-market and boost the productivity of teams interacting with Kafka through a centralized interface. All Kafka providers are supported including Confluent, AWS MSK, Aiven and open-source Apache Kafka. + + Get started with Conduktor [self-hosted](https://docs.conduktor.io/platform/installation/get-started/docker/) today. Setup takes only a few minutes. +- name: Description + description: |- + The Conduktor REST API can be used to manage your Conduktor organizations Users, Groups and their associated Permissions. Additionally, it can be used to interact with Kafka resources that are added to your organization such as Clusters and Certificates. + + The APIs have predictable resource-oriented URLs. All requests and responses are in JSON and should have their `content-type` header set to `application/json` +- name: Authentication + description: Authentication to the API requires a token set in the **authorization** + header. This token can be generated from within the Admin > API Keys section of + your Conduktor deployment. +paths: + /public/v2/cluster/{cluster}/sa/{sa}/topic: + get: + tags: + - topic + - cli_topic_kafka_v2 + operationId: listTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicResourceV2' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_topic_kafka_v2 + operationId: applyTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResourceV2' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicApplyResult' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-topic","cluster":"my-cluster"},"spec":{"partitions":1,"replicationFactor":1,"configs":{}},"apiVersion":"v1","kind":"Topic"}' \ + --location \ + --max-redirs 32 + /public/v1/cluster/{cluster}/topic/{topic name}: + get: + tags: + - topic + - cli_topic_kafka_v1 + operationId: getTopicByNameSelfServe + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: topic name + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic/my-topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + delete: + tags: + - topic + - cli_topic_kafka_v1 + operationId: deleteTopicSelfServe + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: topic name + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request DELETE \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic/my-topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + /public/v1/cluster/{cluster}/topic: + get: + tags: + - topic + - cli_topic_kafka_v1 + operationId: listTopicSelfServe + parameters: + - name: cluster + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicResource' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - topic + - cli_topic_kafka_v1 + operationId: applyTopicSelfServe + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicApplyResult' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-topic","cluster":"my-cluster"},"spec":{"partitions":1,"replicationFactor":1,"configs":{}},"apiVersion":"v1","kind":"Topic"}' \ + --location \ + --max-redirs 32 +components: + schemas: + BadRequest: + title: BadRequest + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + TopicResource: + title: TopicResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/TopicMetadata' + spec: + $ref: '#/components/schemas/TopicSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicKind' + TopicResourceV2: + title: TopicResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/TopicMetadataV2' + spec: + $ref: '#/components/schemas/TopicSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicKind' + TopicMetadata: + title: TopicMetadata + required: + - name + - cluster + type: object + properties: + name: + type: string + cluster: + type: string + TopicMetadataV2: + title: TopicMetadata + required: + - name + - cluster + - sa + type: object + properties: + name: + type: string + cluster: + type: string + sa: + type: string + TopicSpec: + title: TopicSpec + required: + - partitions + - replicationFactor + - configs + type: object + properties: + partitions: + type: integer + format: int32 + replicationFactor: + type: integer + format: int32 + configs: + $ref: '#/components/schemas/Map_Type_Type' + Map_Type_Type: + title: Map_Type_Type + type: object + additionalProperties: + type: string + Version: + title: Version + type: string + enum: + - v1 + - v2 + TopicKind: + title: TopicKind + type: string + enum: + - Topic + TopicApplyResult: + title: TopicApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/TopicResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + UpsertResult: + title: UpsertResult + type: string + enum: + - Created + - Updated + - NotChanged diff --git a/schema/not_required_field_in_metadata.yaml b/schema/not_required_field_in_metadata.yaml new file mode 100644 index 0000000..c0618d0 --- /dev/null +++ b/schema/not_required_field_in_metadata.yaml @@ -0,0 +1,218 @@ +openapi: 3.0.3 +info: + title: Conduktor Public API + version: 0.0.1-SNAPSHOT + summary: The public API to interact with Conduktor platform. + contact: + email: contact@conduktor.io + url: https://docs.conduktor.io +tags: +- name: Introduction + description: |- + Conduktor enables you to accelerate time-to-market and boost the productivity of teams interacting with Kafka through a centralized interface. All Kafka providers are supported including Confluent, AWS MSK, Aiven and open-source Apache Kafka. + + Get started with Conduktor [self-hosted](https://docs.conduktor.io/platform/installation/get-started/docker/) today. Setup takes only a few minutes. +- name: Description + description: |- + The Conduktor REST API can be used to manage your Conduktor organizations Users, Groups and their associated Permissions. Additionally, it can be used to interact with Kafka resources that are added to your organization such as Clusters and Certificates. + + The APIs have predictable resource-oriented URLs. All requests and responses are in JSON and should have their `content-type` header set to `application/json` +- name: Authentication + description: Authentication to the API requires a token set in the **authorization** + header. This token can be generated from within the Admin > API Keys section of + your Conduktor deployment. +paths: + /public/v1/cluster/{cluster}/sa/{sa}/topic: + get: + tags: + - topic + - cli_topic_kafka_v1 + operationId: listTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TopicResource' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request GET \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic' \ + --header 'Authorization: Bearer $BEARER' \ + --location \ + --max-redirs 32 + put: + tags: + - cli_topic_kafka_v1 + operationId: applyTopicSelfServe2 + parameters: + - name: cluster + in: path + required: true + schema: + type: string + - name: sa + in: path + required: true + schema: + type: string + - name: dryMode + in: query + required: false + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TopicResource' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/TopicApplyResult' + '400': + description: The request is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + example: + title: The request is not valid + security: + - httpAuth: [] + x-codeSamples: + - lang: Shell + Curl + source: |- + curl \ + --request PUT \ + --url 'http://localhost:8080/public/v1/cluster/my-cluster/topic?dryMode=false' \ + --header 'Authorization: Bearer $BEARER' \ + --header 'Content-Type: application/json' \ + --data-raw '{"metadata":{"name":"my-topic","cluster":"my-cluster"},"spec":{"partitions":1,"replicationFactor":1,"configs":{}},"apiVersion":"v1","kind":"Topic"}' \ + --location \ + --max-redirs 32 +components: + schemas: + BadRequest: + title: BadRequest + required: + - title + type: object + properties: + title: + type: string + msg: + type: string + cause: + type: string + TopicResource: + title: TopicResource + required: + - metadata + - spec + - apiVersion + - kind + type: object + properties: + metadata: + $ref: '#/components/schemas/TopicMetadata' + spec: + $ref: '#/components/schemas/TopicSpec' + apiVersion: + $ref: '#/components/schemas/Version' + kind: + $ref: '#/components/schemas/TopicKind' + TopicMetadata: + title: TopicMetadata + required: + - name + - cluster + type: object + properties: + name: + type: string + cluster: + type: string + sa: + type: string + TopicSpec: + title: TopicSpec + required: + - partitions + - replicationFactor + - configs + type: object + properties: + partitions: + type: integer + format: int32 + replicationFactor: + type: integer + format: int32 + configs: + $ref: '#/components/schemas/Map_Type_Type' + Map_Type_Type: + title: Map_Type_Type + type: object + additionalProperties: + type: string + Version: + title: Version + type: string + enum: + - v1 + - v2 + TopicKind: + title: TopicKind + type: string + enum: + - Topic + TopicApplyResult: + title: TopicApplyResult + required: + - resource + - upsertResult + type: object + properties: + resource: + $ref: '#/components/schemas/TopicResource' + upsertResult: + $ref: '#/components/schemas/UpsertResult' + UpsertResult: + title: UpsertResult + type: string + enum: + - Created + - Updated + - NotChanged diff --git a/schema/schema.go b/schema/schema.go index abab414..2b4f814 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -1,10 +1,13 @@ package schema import ( + "fmt" "github.com/conduktor/ctl/utils" "github.com/pb33f/libopenapi" v3high "github.com/pb33f/libopenapi/datamodel/high/v3" - "golang.org/x/exp/slices" + "regexp" + "slices" + "strconv" "strings" ) @@ -27,19 +30,111 @@ func New(schema []byte) (*Schema, error) { }, nil } -func (s *Schema) GetKind() ([]string, error) { - result := make([]string, 0) +func (s *Schema) GetKinds(strict bool) (map[string]Kind, error) { + result := make(map[string]Kind, 0) for path := s.doc.Model.Paths.PathItems.First(); path != nil; path = path.Next() { - if path.Value().Get != nil { - for _, tag := range path.Value().Get.Tags { - if strings.HasPrefix(tag, "self-serve-") { - newTag := utils.KebabToUpperCamel(strings.TrimPrefix(tag, "self-serve-")) - if !slices.Contains(result, newTag) { - result = append(result, newTag) + put := path.Value().Put + if put != nil { + cliTag := findCliTag(path.Value().Put.Tags) + if cliTag != "" { + tagParsed, err := parseTag(cliTag) + if err != nil { + return nil, err + } + newKind, err := buildKindVersion(path.Key(), tagParsed.kind, put, strict) + if err != nil { + return nil, err + } + prec, kindAlreadyFound := result[tagParsed.kind] + if kindAlreadyFound { + err = prec.AddVersion(tagParsed.version, newKind) + if err != nil { + return nil, err } + } else { + result[tagParsed.kind] = NewKind(tagParsed.version, newKind) } } } } return result, nil } + +func buildKindVersion(path, kind string, put *v3high.Operation, strict bool) (*KindVersion, error) { + newKind := &KindVersion{ + Name: kind, + ListPath: path, + ParentPathParam: make([]string, 0, len(put.Parameters)), + } + for _, parameter := range put.Parameters { + if parameter.In == "path" && *parameter.Required { + newKind.ParentPathParam = append(newKind.ParentPathParam, parameter.Name) + + } + } + if strict { + err := checkThatPathParamAreInSpec(newKind, put.RequestBody) + if err != nil { + return nil, err + } + } + return newKind, nil +} + +type tagParseResult struct { + kind string + version int +} + +func parseTag(tag string) (tagParseResult, error) { + // we extract kind and version from the tag + // e.g. cli_cluster_kafka_v1 -> kind: Cluster, version: 1 + // e.g. cli_topic-policy_self-serve_v2 -> kind: TopicPolicy, version: 2 + re := regexp.MustCompile(`cli_([^_]+)_[^_]+_v(\d+)`) + matches := re.FindStringSubmatch(tag) + + if len(matches) < 3 { + return tagParseResult{}, fmt.Errorf("Invalid tag format: %s", tag) + } + + kind := matches[1] + version, err := strconv.Atoi(matches[2]) + if err != nil { + return tagParseResult{}, fmt.Errorf("Invalid version number in tag: %s", matches[2]) + } + + return tagParseResult{kind: utils.KebabToUpperCamel(kind), version: version}, nil +} + +func checkThatPathParamAreInSpec(kind *KindVersion, requestBody *v3high.RequestBody) error { + jsonContent, ok := requestBody.Content.Get("application/json") + if !ok { + return fmt.Errorf("No application/json content for kind %s", kind.Name) + } + schema := jsonContent.Schema.Schema() + metadata, ok := schema.Properties.Get("metadata") + if !ok { + return fmt.Errorf("No metadata in schema for kind %s", kind.Name) + } + for _, parentPath := range kind.ParentPathParam { + schema := metadata.Schema() + _, ok := schema.Properties.Get(parentPath) + if !ok { + return fmt.Errorf("Parent path param %s not found in metadata for kind %s", parentPath, kind.Name) + } + if !slices.Contains(schema.Required, parentPath) { + return fmt.Errorf("Parent path param %s in metadata for kind %s not required", parentPath, kind.Name) + } + + } + return nil +} + +func findCliTag(tags []string) string { + for _, tag := range tags { + if strings.HasPrefix(tag, "cli_") { + return tag + } + } + return "" +} diff --git a/schema/schema_test.go b/schema/schema_test.go new file mode 100644 index 0000000..738f67f --- /dev/null +++ b/schema/schema_test.go @@ -0,0 +1,154 @@ +package schema + +import ( + "github.com/davecgh/go-spew/spew" + "os" + "reflect" + "strings" + "testing" +) + +func TestGetKindWithYamlFromConsolePlus(t *testing.T) { + t.Run("gets kinds from schema", func(t *testing.T) { + schemaContent, err := os.ReadFile("docs.yaml") + if err != nil { + t.Fatalf("failed reading file: %s", err) + } + + schema, err := New(schemaContent) + if err != nil { + t.Fatalf("failed creating new schema: %s", err) + } + + kinds, err := schema.GetKinds(true) + if err != nil { + t.Fatalf("failed getting kinds: %s", err) + } + + expected := KindCatalog{ + "Application": { + Versions: map[int]KindVersion{ + 1: { + Name: "Application", + ListPath: "/public/self-serve/v1/application", + ParentPathParam: make([]string, 0), + }, + }, + }, + "ApplicationInstance": { + Versions: map[int]KindVersion{ + 1: { + Name: "ApplicationInstance", + ListPath: "/public/self-serve/v1/application-instance", + ParentPathParam: make([]string, 0), + }, + }, + }, + "ApplicationInstancePermission": { + Versions: map[int]KindVersion{ + 1: { + Name: "ApplicationInstancePermission", + ListPath: "/public/self-serve/v1/application-instance-permission", + ParentPathParam: make([]string, 0), + }, + }, + }, + "TopicPolicy": { + Versions: map[int]KindVersion{ + 1: { + Name: "TopicPolicy", + ListPath: "/public/self-serve/v1/topic-policy", + ParentPathParam: make([]string, 0), + }, + }, + }, + "Topic": { + Versions: map[int]KindVersion{ + 2: { + Name: "Topic", + ListPath: "/public/kafka/v2/cluster/{cluster}/topic", + ParentPathParam: []string{"cluster"}, + }, + }, + }, + } + if !reflect.DeepEqual(kinds, expected) { + t.Error(spew.Printf("got kinds %v, want %v", kinds, expected)) + } + }) +} + +func TestGetKindWithMultipleVersion(t *testing.T) { + t.Run("gets kinds from schema", func(t *testing.T) { + schemaContent, err := os.ReadFile("multiple_version.yaml") + if err != nil { + t.Fatalf("failed reading file: %s", err) + } + + schema, err := New(schemaContent) + if err != nil { + t.Fatalf("failed creating new schema: %s", err) + } + + kinds, err := schema.GetKinds(true) + if err != nil { + t.Fatalf("failed getting kinds: %s", err) + } + + expected := KindCatalog{ + "Topic": { + Versions: map[int]KindVersion{ + 1: { + Name: "Topic", + ListPath: "/public/v1/cluster/{cluster}/topic", + ParentPathParam: []string{"cluster"}, + }, + 2: { + Name: "Topic", + ListPath: "/public/v2/cluster/{cluster}/sa/{sa}/topic", + ParentPathParam: []string{"cluster", "sa"}, + }, + }, + }, + } + if !reflect.DeepEqual(kinds, expected) { + t.Error(spew.Printf("got kinds %v, want %v", kinds, expected)) + } + }) +} +func TestKindWithMissingMetadataField(t *testing.T) { + t.Run("gets kinds from schema", func(t *testing.T) { + schemaContent, err := os.ReadFile("missing_field_in_metadata.yaml") + if err != nil { + t.Fatalf("failed reading file: %s", err) + } + + schema, err := New(schemaContent) + if err != nil { + t.Fatalf("failed creating new schema: %s", err) + } + + _, err = schema.GetKinds(true) + if !strings.Contains(err.Error(), "Parent path param sa not found in metadata for kind Topic") { + t.Fatalf("Not expected error: %s", err) + } + }) +} +func TestKindNotRequiredMetadataField(t *testing.T) { + t.Run("gets kinds from schema", func(t *testing.T) { + schemaContent, err := os.ReadFile("not_required_field_in_metadata.yaml") + if err != nil { + t.Fatalf("failed reading file: %s", err) + } + + schema, err := New(schemaContent) + if err != nil { + t.Fatalf("failed creating new schema: %s", err) + } + + _, err = schema.GetKinds(true) + if !strings.Contains(err.Error(), "Parent path param sa in metadata for kind Topic not required") { + t.Fatalf("Not expected error: %s", err) + } + }) +} diff --git a/test_final_exec.sh b/test_final_exec.sh index f4c312c..791253c 100755 --- a/test_final_exec.sh +++ b/test_final_exec.sh @@ -16,8 +16,8 @@ main() { docker compose -f docker/docker-compose.yml up -d mock sleep 1 docker compose -f docker/docker-compose.yml run conduktor apply -f /test_resource.yml - docker compose -f docker/docker-compose.yml run conduktor get Topic yolo - docker compose -f docker/docker-compose.yml run conduktor delete Topic yolo -v + docker compose -f docker/docker-compose.yml run conduktor get Topic yolo --cluster=my-cluster + docker compose -f docker/docker-compose.yml run conduktor delete Topic yolo -v --cluster=my-cluster } main "$@"