Skip to content

Commit

Permalink
feat: add conduit config (#2033)
Browse files Browse the repository at this point in the history
* start working on config command

* start working on config command

* config cmd works

* implement config cmd

* refactor

* fix spelling

* fix lint
  • Loading branch information
raulb authored Dec 19, 2024
1 parent 433f31c commit 48917b5
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
88 changes: 88 additions & 0 deletions cmd/conduit/root/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright © 2024 Meroxa, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package root

import (
"context"
"fmt"
"reflect"

"github.com/conduitio/ecdysis"
)

var (
_ ecdysis.CommandWithExecute = (*ConfigCommand)(nil)
_ ecdysis.CommandWithDocs = (*ConfigCommand)(nil)
_ ecdysis.CommandWithFlags = (*ConfigCommand)(nil)
_ ecdysis.CommandWithConfig = (*ConfigCommand)(nil)
)

type ConfigCommand struct {
rootCmd *RootCommand
}

func (c *ConfigCommand) Config() ecdysis.Config {
return c.rootCmd.Config()
}

func (c *ConfigCommand) Flags() []ecdysis.Flag {
return c.rootCmd.Flags()
}

func (c *ConfigCommand) Docs() ecdysis.Docs {
return ecdysis.Docs{
Short: "Shows the configuration to be used when running Conduit.",
Long: `Conduit will run based on the default configuration jointly with a provided configuration file (optional),
the set environment variables, and the flags used. This command will show the configuration that will be used.`,
}
}

func printStruct(v reflect.Value, parentPath string) {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}

t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
fieldValue := v.Field(i)
longName := field.Tag.Get("long")

fullPath := longName
if parentPath != "" && longName != "" {
fullPath = parentPath + "." + longName
}

if fieldValue.Kind() == reflect.Struct ||
(fieldValue.Kind() == reflect.Ptr && !fieldValue.IsNil() && fieldValue.Elem().Kind() == reflect.Struct) {
printStruct(fieldValue, fullPath)
continue
}

if longName != "" {
value := fmt.Sprintf("%v", fieldValue.Interface())
if value != "" {
fmt.Printf("%s: %s\n", fullPath, value)
}
}
}
}

func (c *ConfigCommand) Usage() string { return "config" }

func (c ConfigCommand) Execute(_ context.Context) error {
printStruct(reflect.ValueOf(c.rootCmd.cfg), "")
return nil
}
76 changes: 76 additions & 0 deletions cmd/conduit/root/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright © 2024 Meroxa, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package root

import (
"bytes"
"io"
"os"
"reflect"
"strings"
"testing"

"github.com/conduitio/conduit/pkg/conduit"
"github.com/matryer/is"
)

func TestPrintStructOutput(t *testing.T) {
is := is.New(t)

cfg := conduit.DefaultConfig()

oldStdout := os.Stdout
defer func() { os.Stdout = oldStdout }()

r, w, err := os.Pipe()
is.NoErr(err)

os.Stdout = w
t.Cleanup(func() { os.Stdout = oldStdout })

printStruct(reflect.ValueOf(cfg), "")

err = w.Close()
is.NoErr(err)

var buf bytes.Buffer
_, err = io.Copy(&buf, r)
is.NoErr(err)

output := buf.String()

expectedLines := []string{
"db.type: badger",
"db.postgres.table: conduit_kv_store",
"db.sqlite.table: conduit_kv_store",
"api.enabled: true",
"http.address: :8080",
"grpc.address: :8084",
"log.level: info",
"log.format: cli",
"pipelines.exit-on-degraded: false",
"pipelines.error-recovery.min-delay: 1s",
"pipelines.error-recovery.max-delay: 10m0s",
"pipelines.error-recovery.backoff-factor: 2",
"pipelines.error-recovery.max-retries: -1",
"pipelines.error-recovery.max-retries-window: 5m0s",
"schema-registry.type: builtin",
"preview.pipeline-arch-v2: false",
}

for _, line := range expectedLines {
is.True(strings.Contains(output, line))
}
}
3 changes: 3 additions & 0 deletions cmd/conduit/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ func (c *RootCommand) Docs() ecdysis.Docs {

func (c *RootCommand) SubCommands() []ecdysis.Command {
return []ecdysis.Command{
&ConfigCommand{
rootCmd: c,
},
&InitCommand{cfg: &c.cfg},
&pipelines.PipelinesCommand{},
}
Expand Down

0 comments on commit 48917b5

Please sign in to comment.