Skip to content

Commit 48917b5

Browse files
authored
feat: add conduit config (#2033)
* start working on config command * start working on config command * config cmd works * implement config cmd * refactor * fix spelling * fix lint
1 parent 433f31c commit 48917b5

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

cmd/conduit/root/config.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright © 2024 Meroxa, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package root
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"reflect"
21+
22+
"github.com/conduitio/ecdysis"
23+
)
24+
25+
var (
26+
_ ecdysis.CommandWithExecute = (*ConfigCommand)(nil)
27+
_ ecdysis.CommandWithDocs = (*ConfigCommand)(nil)
28+
_ ecdysis.CommandWithFlags = (*ConfigCommand)(nil)
29+
_ ecdysis.CommandWithConfig = (*ConfigCommand)(nil)
30+
)
31+
32+
type ConfigCommand struct {
33+
rootCmd *RootCommand
34+
}
35+
36+
func (c *ConfigCommand) Config() ecdysis.Config {
37+
return c.rootCmd.Config()
38+
}
39+
40+
func (c *ConfigCommand) Flags() []ecdysis.Flag {
41+
return c.rootCmd.Flags()
42+
}
43+
44+
func (c *ConfigCommand) Docs() ecdysis.Docs {
45+
return ecdysis.Docs{
46+
Short: "Shows the configuration to be used when running Conduit.",
47+
Long: `Conduit will run based on the default configuration jointly with a provided configuration file (optional),
48+
the set environment variables, and the flags used. This command will show the configuration that will be used.`,
49+
}
50+
}
51+
52+
func printStruct(v reflect.Value, parentPath string) {
53+
if v.Kind() == reflect.Ptr {
54+
v = v.Elem()
55+
}
56+
57+
t := v.Type()
58+
for i := 0; i < v.NumField(); i++ {
59+
field := t.Field(i)
60+
fieldValue := v.Field(i)
61+
longName := field.Tag.Get("long")
62+
63+
fullPath := longName
64+
if parentPath != "" && longName != "" {
65+
fullPath = parentPath + "." + longName
66+
}
67+
68+
if fieldValue.Kind() == reflect.Struct ||
69+
(fieldValue.Kind() == reflect.Ptr && !fieldValue.IsNil() && fieldValue.Elem().Kind() == reflect.Struct) {
70+
printStruct(fieldValue, fullPath)
71+
continue
72+
}
73+
74+
if longName != "" {
75+
value := fmt.Sprintf("%v", fieldValue.Interface())
76+
if value != "" {
77+
fmt.Printf("%s: %s\n", fullPath, value)
78+
}
79+
}
80+
}
81+
}
82+
83+
func (c *ConfigCommand) Usage() string { return "config" }
84+
85+
func (c ConfigCommand) Execute(_ context.Context) error {
86+
printStruct(reflect.ValueOf(c.rootCmd.cfg), "")
87+
return nil
88+
}

cmd/conduit/root/config_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright © 2024 Meroxa, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package root
16+
17+
import (
18+
"bytes"
19+
"io"
20+
"os"
21+
"reflect"
22+
"strings"
23+
"testing"
24+
25+
"github.com/conduitio/conduit/pkg/conduit"
26+
"github.com/matryer/is"
27+
)
28+
29+
func TestPrintStructOutput(t *testing.T) {
30+
is := is.New(t)
31+
32+
cfg := conduit.DefaultConfig()
33+
34+
oldStdout := os.Stdout
35+
defer func() { os.Stdout = oldStdout }()
36+
37+
r, w, err := os.Pipe()
38+
is.NoErr(err)
39+
40+
os.Stdout = w
41+
t.Cleanup(func() { os.Stdout = oldStdout })
42+
43+
printStruct(reflect.ValueOf(cfg), "")
44+
45+
err = w.Close()
46+
is.NoErr(err)
47+
48+
var buf bytes.Buffer
49+
_, err = io.Copy(&buf, r)
50+
is.NoErr(err)
51+
52+
output := buf.String()
53+
54+
expectedLines := []string{
55+
"db.type: badger",
56+
"db.postgres.table: conduit_kv_store",
57+
"db.sqlite.table: conduit_kv_store",
58+
"api.enabled: true",
59+
"http.address: :8080",
60+
"grpc.address: :8084",
61+
"log.level: info",
62+
"log.format: cli",
63+
"pipelines.exit-on-degraded: false",
64+
"pipelines.error-recovery.min-delay: 1s",
65+
"pipelines.error-recovery.max-delay: 10m0s",
66+
"pipelines.error-recovery.backoff-factor: 2",
67+
"pipelines.error-recovery.max-retries: -1",
68+
"pipelines.error-recovery.max-retries-window: 5m0s",
69+
"schema-registry.type: builtin",
70+
"preview.pipeline-arch-v2: false",
71+
}
72+
73+
for _, line := range expectedLines {
74+
is.True(strings.Contains(output, line))
75+
}
76+
}

cmd/conduit/root/root.go

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ func (c *RootCommand) Docs() ecdysis.Docs {
113113

114114
func (c *RootCommand) SubCommands() []ecdysis.Command {
115115
return []ecdysis.Command{
116+
&ConfigCommand{
117+
rootCmd: c,
118+
},
116119
&InitCommand{cfg: &c.cfg},
117120
&pipelines.PipelinesCommand{},
118121
}

0 commit comments

Comments
 (0)