Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add template command #76

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion client/console_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ func Make(apiParameter ApiParameter) (*Client, error) {

err := result.initKindFromApi()
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot access the Conduktor API: %s\nUsing offline defaults.\n", err)
if apiParameter.Debug {
fmt.Fprintf(os.Stderr, "Cannot access the Conduktor API: %s\nUsing offline defaults.\n", err)
}
result.kinds = schema.ConsoleDefaultKind()
}

Expand Down
4 changes: 3 additions & 1 deletion client/gateway_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ func MakeGateway(apiParameter GatewayApiParameter) (*GatewayClient, error) {

err := result.initKindFromApi()
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot access the Gateway Conduktor API: %s\nUsing offline defaults.\n", err)
if apiParameter.Debug {
fmt.Fprintf(os.Stderr, "Cannot access the Gateway Conduktor API: %s\nUsing offline defaults.\n", err)
}
result.kinds = schema.GatewayDefaultKind()
}

Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func init() {
debug = rootCmd.PersistentFlags().BoolP("verbose", "v", false, "show more information for debugging")
var permissive = rootCmd.PersistentFlags().Bool("permissive", false, "permissive mode, allow undefined environment variables")
initGet(kinds)
initTemplate(kinds)
initDelete(kinds, !*permissive)
initApply(kinds, !*permissive)
initConsoleMkKind()
Expand Down
75 changes: 75 additions & 0 deletions cmd/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package cmd

import (
"bufio"
"fmt"
"os"

"github.com/conduktor/ctl/schema"
"github.com/spf13/cobra"
)

var templateCmd = &cobra.Command{
Use: "template",
Short: "Get a yaml example for a given kind",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
// Root command does nothing
cmd.Help()
os.Exit(1)
},
}

func initTemplate(kinds schema.KindCatalog) {
rootCmd.AddCommand(templateCmd)
var file *string
file = templateCmd.PersistentFlags().StringP("output", "o", "", "Write example to file")

// Add all kinds to the 'template' command
for name, kind := range kinds {
kindCmd := &cobra.Command{
Use: name,
Short: "Get a yaml example for resource of kind " + name,
Args: cobra.NoArgs,
Long: `If name not provided it will list all resource`,
Aliases: buildAlias(name),
Run: func(cmd *cobra.Command, args []string) {
example := kind.GetLatestKindVersion().GetApplyExample()
if example == "" {
fmt.Fprintf(os.Stderr, "No template for kind %s\n", name)
os.Exit(1)
} else {
if file == nil || *file == "" {
fmt.Println("---")
fmt.Println(kind.GetLatestKindVersion().GetApplyExample())
} else {
_, err := os.Stat(*file)
if err == nil {
fmt.Fprintf(os.Stderr, "File %s already exists. You can use conduktor template %s >> %s to append to existing file\n", *file, name, *file)
os.Exit(2)
}
f, err := os.Create(*file)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating file %s: %s\n", *file, err)
os.Exit(3)
}
defer f.Close()
w := bufio.NewWriter(f)
_, err = w.WriteString("---\n")
_, err = w.WriteString(kind.GetLatestKindVersion().GetApplyExample())
if err != nil {
fmt.Fprintf(os.Stderr, "Error writting to file %s: %s\n", *file, err)
os.Exit(4)
}
err = w.Flush()
if err != nil {
fmt.Fprintf(os.Stderr, "Error writting to file %s: %s\n", *file, err)
os.Exit(5)
}
}
}
},
}
templateCmd.AddCommand(kindCmd)
}
}
2 changes: 1 addition & 1 deletion schema/console-default-schema.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"Alert":{"Versions":{"2":{"ListPath":"/public/monitoring/v2/cluster/{cluster}/alert","Name":"Alert","ParentPathParam":["cluster"],"ListQueryParamter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"}},"Order":15}}},"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ListQueryParamter":{},"Order":6}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ListQueryParamter":{},"Order":9}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ListQueryParamter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"Order":7}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ListQueryParamter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"Order":8}}},"Connector":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/connect/{connectCluster}/connector","Name":"Connector","ParentPathParam":["cluster","connectCluster"],"ListQueryParamter":{},"Order":13}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ListQueryParamter":{},"Order":1}}},"IndexedTopic":{"Versions":{"1":{"ListPath":"/public/sql/v1/cluster/{cluster}/indexed_topic","Name":"IndexedTopic","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":14}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ListQueryParamter":{},"Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":4}}},"ServiceAccount":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/cluster/{cluster}/service-account","Name":"ServiceAccount","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":10}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":12}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":11}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ListQueryParamter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"Order":5}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ListQueryParamter":{},"Order":0}}}}
{"Alert":{"Versions":{"2":{"ListPath":"/public/monitoring/v2/cluster/{cluster}/alert","Name":"Alert","ParentPathParam":["cluster"],"ListQueryParamter":{"alertType":{"FlagName":"alert-type","Required":false,"Type":"string"},"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"},"consumerGroup":{"FlagName":"consumer-group","Required":false,"Type":"string"},"topic":{"FlagName":"topic","Required":false,"Type":"string"}},"ApplyExample":"null\n","Order":15}}},"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ListQueryParamter":{},"ApplyExample":"null\n","Order":6}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ListQueryParamter":{},"ApplyExample":"null\n","Order":9}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ListQueryParamter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"ApplyExample":"null\n","Order":7}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ListQueryParamter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"ApplyExample":"null\n","Order":8}}},"Connector":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/connect/{connectCluster}/connector","Name":"Connector","ParentPathParam":["cluster","connectCluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":13}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ListQueryParamter":{},"ApplyExample":"null\n","Order":1}}},"IndexedTopic":{"Versions":{"1":{"ListPath":"/public/sql/v1/cluster/{cluster}/indexed_topic","Name":"IndexedTopic","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":14}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ListQueryParamter":{},"ApplyExample":"null\n","Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":4}}},"ServiceAccount":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/cluster/{cluster}/service-account","Name":"ServiceAccount","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":10}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":12}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ListQueryParamter":{},"ApplyExample":"null\n","Order":11}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ListQueryParamter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"ApplyExample":"null\n","Order":5}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ListQueryParamter":{},"ApplyExample":"null\n","Order":0}}}}
74 changes: 73 additions & 1 deletion schema/gateway_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,17 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
ParentPathParam: []string{},
ListQueryParameter: map[string]QueryParameterOption{},
GetAvailable: true,
Order: 7,
ApplyExample: `kind: VirtualCluster
apiVersion: gateway/v2
metadata:
name: vcluster1
spec:
aclEnabled: false
superUsers:
- username1
- username2
`,
Order: 7,
},
},
},
Expand Down Expand Up @@ -63,6 +73,14 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
},
GetAvailable: false,
Order: 8,
ApplyExample: `kind: AliasTopic
apiVersion: gateway/v2
metadata:
name: name1
vCluster: vCluster1
spec:
physicalName: physicalName1
`,
},
},
},
Expand Down Expand Up @@ -91,6 +109,20 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
},
GetAvailable: false,
Order: 9,
ApplyExample: `kind: ConcentrationRule
apiVersion: gateway/v2
metadata:
name: concentrationRule1
vCluster: vCluster1
spec:
pattern: topic.*
physicalTopics:
delete: topic
compact: compact_topic
deleteCompact: compact_delete_topic
autoManaged: false
offsetCorrectness: false
`,
},
},
},
Expand All @@ -100,6 +132,22 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
Name: "GatewayGroup",
ListPath: "/gateway/v2/group",
ParentPathParam: []string{},
ApplyExample: `kind: GatewayGroup
apiVersion: gateway/v2
metadata:
name: group1
spec:
members:
- vCluster: vCluster1
name: serviceAccount1
- vCluster: vCluster2
name: serviceAccount2
- vCluster: vCluster3
name: serviceAccount3
externalGroups:
- GROUP_READER
- GROUP_WRITER
`,
ListQueryParameter: map[string]QueryParameterOption{
"showDefaults": {
FlagName: "show-defaults",
Expand Down Expand Up @@ -142,6 +190,16 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
},
GetAvailable: false,
Order: 10,
ApplyExample: `kind: GatewayServiceAccount
apiVersion: gateway/v2
metadata:
name: user1
vCluster: vcluster1
spec:
type: EXTERNAL
externalNames:
- externalName
`,
},
},
},
Expand Down Expand Up @@ -178,6 +236,20 @@ func TestGetKindWithYamlFromGateway(t *testing.T) {
Type: "string",
},
},
ApplyExample: `kind: Interceptor
apiVersion: gateway/v2
metadata:
name: yellow_cars_filter
scope:
vCluster: vCluster1
spec:
comment: Filter yellow cars
pluginClass: io.conduktor.gateway.interceptor.VirtualSqlTopicPlugin
priority: 1
config:
virtualTopic: yellow_cars
statement: SELECT '$.type' as type, '$.price' as price FROM cars WHERE '$.color' = 'yellow'
`,
GetAvailable: false,
Order: 12,
},
Expand Down
11 changes: 11 additions & 0 deletions schema/kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type KindVersion interface {
GetParentPathParam() []string
GetOrder() int
GetListQueryParamter() map[string]QueryParameterOption
GetApplyExample() string
}

// two logics: uniformize flag name and kebab case
Expand All @@ -38,13 +39,18 @@ type ConsoleKindVersion struct {
Name string
ParentPathParam []string
ListQueryParamter map[string]QueryParameterOption
ApplyExample string
Order int `json:1000` //same value DefaultPriority
}

func (c *ConsoleKindVersion) GetListPath() string {
return c.ListPath
}

func (c *ConsoleKindVersion) GetApplyExample() string {
return c.ApplyExample
}

func (c *ConsoleKindVersion) GetName() string {
return c.Name
}
Expand Down Expand Up @@ -72,6 +78,7 @@ type GatewayKindVersion struct {
ParentPathParam []string
ListQueryParameter map[string]QueryParameterOption
GetAvailable bool
ApplyExample string
Order int `json:1000` //same value DefaultPriority
}

Expand All @@ -87,6 +94,10 @@ func (g *GatewayKindVersion) GetParentPathParam() []string {
return g.ParentPathParam
}

func (g *GatewayKindVersion) GetApplyExample() string {
return g.ApplyExample
}

func (g *GatewayKindVersion) GetOrder() int {
return g.Order
}
Expand Down
10 changes: 10 additions & 0 deletions schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/conduktor/ctl/utils"
"github.com/pb33f/libopenapi"
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
"gopkg.in/yaml.v3"
)

type Schema struct {
Expand Down Expand Up @@ -83,6 +84,7 @@ func buildConsoleKindVersion(s *Schema, path, kind string, order int, put *v3hig
newKind.ParentPathParam = append(newKind.ParentPathParam, putParameter.Name)

}

}
for _, getParameter := range get.Parameters {
if getParameter.In == "query" {
Expand All @@ -98,6 +100,13 @@ func buildConsoleKindVersion(s *Schema, path, kind string, order int, put *v3hig
}
}
}
schemaJson, ok := put.RequestBody.Content.Get("application/json")
if ok && schemaJson.Example != nil {
data, err := yaml.Marshal(schemaJson.Example)
if err == nil {
newKind.ApplyExample = string(data)
}
}
if strict {
err := checkThatPathParamAreInSpec(newKind, put.RequestBody)
if err != nil {
Expand Down Expand Up @@ -130,6 +139,7 @@ func buildGatewayKindVersion(s *Schema, path, kind string, order int, put *v3hig
ListPath: consoleKind.ListPath,
ParentPathParam: consoleKind.ParentPathParam,
ListQueryParameter: consoleKind.ListQueryParamter,
ApplyExample: consoleKind.ApplyExample,
GetAvailable: getAvailable,
Order: consoleKind.Order,
}, nil
Expand Down
Loading