Skip to content

Commit

Permalink
ParseConfig should call the custom Validate method (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
hariso authored Jan 10, 2025
1 parent dd16e6e commit 2b0b3ff
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 50 deletions.
10 changes: 0 additions & 10 deletions acceptance_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -1153,11 +1153,6 @@ func configureSource(ctx context.Context, src Source, cfgMap config.Config, para
return fmt.Errorf("failed to parse configuration: %w", err)
}

err = cfg.Validate(ctx)
if err != nil {
return fmt.Errorf("configuration invalid: %w", err)
}

return nil
}

Expand All @@ -1173,10 +1168,5 @@ func configureDestination(ctx context.Context, dest Destination, cfgMap config.C
return fmt.Errorf("failed to parse configuration: %w", err)
}

err = cfg.Validate(ctx)
if err != nil {
return fmt.Errorf("configuration invalid: %w", err)
}

return nil
}
5 changes: 0 additions & 5 deletions destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,6 @@ func (a *destinationPluginAdapter) Configure(ctx context.Context, req pconnector
return pconnector.DestinationConfigureResponse{}, fmt.Errorf("failed to parse configuration: %w", err)
}

err = cfg.Validate(ctx)
if err != nil {
return pconnector.DestinationConfigureResponse{}, fmt.Errorf("configuration invalid: %w", err)
}

return pconnector.DestinationConfigureResponse{}, nil
}

Expand Down
12 changes: 4 additions & 8 deletions source.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ type Source interface {
// update anything that was initialized in LifecycleOnCreated, in case the
// configuration change affects it.
LifecycleOnUpdated(ctx context.Context, configBefore, configAfter config.Config) error
// LifecycleOnDeleted is called when the connector was deleted. It will be
// the only method that is called in that case. This method can be used to
// clean up anything that was initialized in LifecycleOnCreated.
// LifecycleOnDeleted is called when the connector was deleted.
// This method can be used to clean up anything that was initialized in LifecycleOnCreated.
// It will be the only method that is called in that case, i.e. Configure() and Open()
// won't be called. The implementation needs to manually parse the configuration if needed.
LifecycleOnDeleted(ctx context.Context, config config.Config) error

mustEmbedUnimplementedSource()
Expand Down Expand Up @@ -181,11 +182,6 @@ func (a *sourcePluginAdapter) Configure(ctx context.Context, req pconnector.Sour
return fmt.Errorf("failed to parse configuration: %w", err)
}

err = cfg.Validate(ctx)
if err != nil {
return fmt.Errorf("configuration invalid: %w", err)
}

return nil
})

Expand Down
14 changes: 12 additions & 2 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,18 @@ func parseConfig(
}

logger.Debug().Type("target", target).Msg("decoding configuration into the target object")
//nolint:wrapcheck // error is already wrapped by DecodeInto
return c.DecodeInto(target)
if err := c.DecodeInto(target); err != nil {
return err
}

if v, ok := target.(Validatable); ok {
err := v.Validate(ctx)
if err != nil {
return fmt.Errorf("config invalid: %w", err)
}
}

return err
}

func YAMLSpecification(rawYaml string) func() Specification {
Expand Down
58 changes: 58 additions & 0 deletions util_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright © 2022 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 sdk

import (
"context"
"fmt"
"time"

"github.com/conduitio/conduit-commons/config"
)

// ExampleUtil_ParseConfig shows the usage of Util.ParseConfig.
func ExampleUtil_ParseConfig() {
cfg := config.Config{
"foo": "bar ", // will be sanitized
// "bar" is missing, will be set to the default value
"nested.baz": "1m",
}

params := config.Parameters{
"foo": config.Parameter{Type: config.ParameterTypeString},
"bar": config.Parameter{
Type: config.ParameterTypeInt,
Default: "42",
},
"nested.baz": config.Parameter{Type: config.ParameterTypeDuration},
}

var target struct {
Foo string `json:"foo"`
Bar int `json:"bar"`
Nested struct {
Baz time.Duration `json:"baz"`
} `json:"nested"`
}

err := Util.ParseConfig(context.Background(), cfg, &target, params)
if err != nil {
panic(err)
}

fmt.Printf("%+v", target)

// Output: {Foo:bar Bar:42 Nested:{Baz:1m0s}}
}
49 changes: 24 additions & 25 deletions util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,42 @@ package sdk

import (
"context"
"fmt"
"errors"
"testing"
"time"

"github.com/conduitio/conduit-commons/config"
"github.com/matryer/is"
)

// ExampleUtil_ParseConfig shows the usage of Util.ParseConfig.
func ExampleUtil_ParseConfig() {
type testConfig struct {
Foo string `json:"foo"`
Bar int `json:"bar"`
Nested struct {
Baz time.Duration `json:"baz"`
} `json:"nested"`
err error
}

func (c *testConfig) Validate(context.Context) error {
return c.err
}

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

wantErr := errors.New("validation error")
cfg := config.Config{
"foo": "bar ", // will be sanitized
// "bar" is missing, will be set to the default value
"nested.baz": "1m",
"foo": "bar",
}

params := config.Parameters{
"foo": config.Parameter{Type: config.ParameterTypeString},
"bar": config.Parameter{
Type: config.ParameterTypeInt,
Default: "42",
},
"nested.baz": config.Parameter{Type: config.ParameterTypeDuration},
}

var target struct {
Foo string `json:"foo"`
Bar int `json:"bar"`
Nested struct {
Baz time.Duration `json:"baz"`
} `json:"nested"`
target := testConfig{
err: wantErr,
}

err := Util.ParseConfig(context.Background(), cfg, &target, params)
if err != nil {
panic(err)
}

fmt.Printf("%+v", target)

// Output: {Foo:bar Bar:42 Nested:{Baz:1m0s}}
is.True(errors.Is(err, wantErr))
}

0 comments on commit 2b0b3ff

Please sign in to comment.