Skip to content

Commit

Permalink
Add template command
Browse files Browse the repository at this point in the history
  • Loading branch information
strokyl committed Dec 17, 2024
1 parent 4731bdc commit deb5fb8
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 5 deletions.
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
73 changes: 73 additions & 0 deletions cmd/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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 == "" {
println(kind.GetLatestKindVersion().GetApplyExample())
} else {
_, err := os.Stat(*file)
if err == nil {
fmt.Fprintf(os.Stderr, "File %s already exists\n", *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(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}}}}
2 changes: 1 addition & 1 deletion schema/console_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func TestGetKindWithYamlFromOldConsolePlusWithoutOrder(t *testing.T) {
},
}
if !reflect.DeepEqual(kinds, expected) {
t.Error(spew.Printf("got kinds %v, want %v", kinds, expected))
t.Error(spew.Printf("got kinds %v, want %v", kinds["Topic"], expected["Topic"]))
}
})
}
Expand Down
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

0 comments on commit deb5fb8

Please sign in to comment.