From fe1ffa356cfe29d7373bea73537a20789ef761e8 Mon Sep 17 00:00:00 2001 From: tanyamadaan Date: Sat, 22 Mar 2025 00:05:08 +0530 Subject: [PATCH] small fixes --- go.mod | 15 +- go.sum | 17 - pkg/plugin/definition/router.go | 24 - .../implementation/router/cmd/plugin.go | 31 -- .../implementation/router/cmd/plugin_test.go | 137 ------ pkg/plugin/implementation/router/router.go | 204 -------- .../implementation/router/router_test.go | 452 ------------------ .../router/testData/bap_caller.yaml | 25 - .../router/testData/bap_receiver.yaml | 20 - .../router/testData/bpp_caller.yaml | 23 - .../router/testData/bpp_receiver.yaml | 30 -- .../schemaValidator/cmd/plugin.go | 6 +- .../schemaValidator/cmd/plugin_test.go | 14 +- .../schemaValidator/schemaValidator.go | 7 +- .../schemaValidator/schemaValidator_test.go | 20 +- pkg/plugin/manager.go | 26 +- 16 files changed, 35 insertions(+), 1016 deletions(-) delete mode 100644 pkg/plugin/definition/router.go delete mode 100644 pkg/plugin/implementation/router/cmd/plugin.go delete mode 100644 pkg/plugin/implementation/router/cmd/plugin_test.go delete mode 100644 pkg/plugin/implementation/router/router.go delete mode 100644 pkg/plugin/implementation/router/router_test.go delete mode 100644 pkg/plugin/implementation/router/testData/bap_caller.yaml delete mode 100644 pkg/plugin/implementation/router/testData/bap_receiver.yaml delete mode 100644 pkg/plugin/implementation/router/testData/bpp_caller.yaml delete mode 100644 pkg/plugin/implementation/router/testData/bpp_receiver.yaml diff --git a/go.mod b/go.mod index c2692fb..91f393a 100644 --- a/go.mod +++ b/go.mod @@ -1,26 +1,15 @@ module github.com/beckn/beckn-onix -go 1.23.4 - -toolchain go1.23.7 +go 1.24.1 require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 golang.org/x/crypto v0.36.0 ) -require ( - github.com/kr/pretty v0.3.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect -) - require ( github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 golang.org/x/text v0.23.0 // indirect ) -require ( - golang.org/x/sys v0.31.0 // indirect - gopkg.in/yaml.v3 v3.0.1 -) +require golang.org/x/sys v0.31.0 // indirect diff --git a/go.sum b/go.sum index 896f459..50bb32e 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,5 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 h1:m1h+vudopHsI67FPT9MOncyndWhTcdUoBtI1R1uajGY= @@ -22,8 +10,3 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= \ No newline at end of file diff --git a/pkg/plugin/definition/router.go b/pkg/plugin/definition/router.go deleted file mode 100644 index b9f7e41..0000000 --- a/pkg/plugin/definition/router.go +++ /dev/null @@ -1,24 +0,0 @@ -package definition - -import ( - "context" - "net/url" -) - -// Route defines the structure for the Route returned -type Route struct { - RoutingType string // "url" or "msgq" - TopicID string // For message queues - TargetURL string // For API calls -} - -// RouterProvider initializes the a new Router instance with the given config -type RouterProvider interface { - New(ctx context.Context, config map[string]string) (Router, func() error, error) -} - -// Router defines the interface for routing requests -type Router interface { - // Route determines the routing destination based on the request context. - Route(ctx context.Context, url *url.URL, body []byte) (*Route, error) -} diff --git a/pkg/plugin/implementation/router/cmd/plugin.go b/pkg/plugin/implementation/router/cmd/plugin.go deleted file mode 100644 index f38ffa9..0000000 --- a/pkg/plugin/implementation/router/cmd/plugin.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "context" - "errors" - - definition "github.com/beckn/beckn-onix/pkg/plugin/definition" - router "github.com/beckn/beckn-onix/pkg/plugin/implementation/router" -) - -// RouterProvider provides instances of Router. -type RouterProvider struct{} - -// New initializes a new Router instance. -func (rp RouterProvider) New(ctx context.Context, config map[string]string) (definition.Router, func() error, error) { - if ctx == nil { - return nil, nil, errors.New("context cannot be nil") - } - - // Parse the routing_config key from the config map - routingConfig, ok := config["routingConfig"] - if !ok { - return nil, nil, errors.New("routingConfig is required in the configuration") - } - return router.New(ctx, &router.Config{ - RoutingConfig: routingConfig, - }) -} - -// Provider is the exported symbol that the plugin manager will look for. -var Provider definition.RouterProvider = RouterProvider{} diff --git a/pkg/plugin/implementation/router/cmd/plugin_test.go b/pkg/plugin/implementation/router/cmd/plugin_test.go deleted file mode 100644 index afa0c97..0000000 --- a/pkg/plugin/implementation/router/cmd/plugin_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package main - -import ( - "context" - "os" - "path/filepath" - "strings" - "testing" -) - -// setupTestConfig creates a temporary directory and writes a sample routing rules file. -func setupTestConfig(t *testing.T) string { - t.Helper() - - // Create a temporary directory for the routing rules - configDir, err := os.MkdirTemp("", "routingRules") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - - // Define sample routing rules - rulesContent := ` -routingRules: - - domain: "ONDC:TRV11" - version: "2.0.0" - routingType: "url" - target: - url: "https://services-backend/trv/v1" - endpoints: - - select - - init - - confirm - - status - - - domain: "ONDC:TRV11" - version: "2.0.0" - routingType: "msgq" - target: - topic_id: "trv_topic_id1" - endpoints: - - search -` - - // Write the routing rules to a file - rulesFilePath := filepath.Join(configDir, "routingRules.yaml") - if err := os.WriteFile(rulesFilePath, []byte(rulesContent), 0644); err != nil { - t.Fatalf("Failed to write routing rules file: %v", err) - } - - return rulesFilePath -} - -// TestRouterProviderSuccess tests the RouterProvider implementation for success cases. -func TestRouterProviderSuccess(t *testing.T) { - rulesFilePath := setupTestConfig(t) - defer os.RemoveAll(filepath.Dir(rulesFilePath)) - - // Define test cases - tests := []struct { - name string - ctx context.Context - config map[string]string - }{ - { - name: "Valid configuration", - ctx: context.Background(), - config: map[string]string{ - "routingConfig": rulesFilePath, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - provider := RouterProvider{} - router, _, err := provider.New(tt.ctx, tt.config) - - // Ensure no error occurred - if err != nil { - t.Errorf("unexpected error: %v", err) - return - } - - // Ensure the router and close function are not nil - if router == nil { - t.Error("expected a non-nil Router instance, got nil") - } - }) - } -} - -// TestRouterProviderFailure tests the RouterProvider implementation for failure cases. -func TestRouterProviderFailure(t *testing.T) { - rulesFilePath := setupTestConfig(t) - defer os.RemoveAll(filepath.Dir(rulesFilePath)) - - // Define test cases - tests := []struct { - name string - ctx context.Context - config map[string]string - expectedError string - }{ - { - name: "Empty routing config path", - ctx: context.Background(), - config: map[string]string{ - "routingConfig": "", - }, - expectedError: "failed to load routing rules: routingConfig path is empty", - }, - { - name: "Missing routing config key", - ctx: context.Background(), - config: map[string]string{}, - expectedError: "routingConfig is required in the configuration", - }, - { - name: "Nil context", - ctx: nil, - config: map[string]string{"routingConfig": rulesFilePath}, - expectedError: "context cannot be nil", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - provider := RouterProvider{} - _, _, err := provider.New(tt.ctx, tt.config) - - // Check for expected error - if err == nil || !strings.Contains(err.Error(), tt.expectedError) { - t.Errorf("expected error %q, got %v", tt.expectedError, err) - } - }) - } -} diff --git a/pkg/plugin/implementation/router/router.go b/pkg/plugin/implementation/router/router.go deleted file mode 100644 index 2649dbd..0000000 --- a/pkg/plugin/implementation/router/router.go +++ /dev/null @@ -1,204 +0,0 @@ -package router - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "os" - "path" - "strings" - - definition "github.com/beckn/beckn-onix/pkg/plugin/definition" - - "gopkg.in/yaml.v3" -) - -// Config holds the configuration for the Router plugin. -type Config struct { - RoutingConfig string `json:"routingConfig"` -} - -// RoutingConfig represents the structure of the routing configuration file. -type routingConfig struct { - RoutingRules []routingRule `yaml:"routingRules"` -} - -// Router implements Router interface -type Router struct { - config *Config - rules []routingRule -} - -// RoutingRule represents a single routing rule. -type routingRule struct { - Domain string `yaml:"domain"` - Version string `yaml:"version"` - RoutingType string `yaml:"routingType"` // "url", "msgq", "bpp", or "bap" - Target target `yaml:"target,omitempty"` - Endpoints []string `yaml:"endpoints"` -} - -// Target contains destination-specific details. -type target struct { - URL string `yaml:"url,omitempty"` // URL for "url" or gateway endpoint for "bpp"/"bap" - TopicID string `yaml:"topic_id,omitempty"` // For "msgq" type -} - -// New initializes a new Router instance with the provided configuration. -// It loads and validates the routing rules from the specified YAML file. -// Returns an error if the configuration is invalid or the rules cannot be loaded. -func New(ctx context.Context, config *Config) (*Router, func() error, error) { - // Check if config is nil - if config == nil { - return nil, nil, fmt.Errorf("config cannot be nil") - } - router := &Router{ - config: config, - } - - // Load rules at bootup - if err := router.loadRules(); err != nil { - return nil, nil, fmt.Errorf("failed to load routing rules: %w", err) - } - return router, nil, nil -} - -// LoadRules reads and parses routing rules from the YAML configuration file. -func (r *Router) loadRules() error { - if r.config.RoutingConfig == "" { - return fmt.Errorf("routingConfig path is empty") - } - data, err := os.ReadFile(r.config.RoutingConfig) - if err != nil { - return fmt.Errorf("error reading config file at %s: %w", r.config.RoutingConfig, err) - } - var config routingConfig - if err := yaml.Unmarshal(data, &config); err != nil { - return fmt.Errorf("error parsing YAML: %w", err) - } - - // Validate rules - if err := validateRules(config.RoutingRules); err != nil { - return fmt.Errorf("invalid routing rules: %w", err) - } - r.rules = config.RoutingRules - return nil -} - -// validateRules performs basic validation on the loaded routing rules. -func validateRules(rules []routingRule) error { - for _, rule := range rules { - // Ensure domain, version, and routingType are present - if rule.Domain == "" || rule.Version == "" || rule.RoutingType == "" { - return fmt.Errorf("invalid rule: domain, version, and routingType are required") - } - - // Validate based on routingType - switch rule.RoutingType { - case "url": - if rule.Target.URL == "" { - return fmt.Errorf("invalid rule: url is required for routingType 'url'") - } - if _, err := url.ParseRequestURI(rule.Target.URL); err != nil { - return fmt.Errorf("invalid URL in rule: %w", err) - } - case "msgq": - if rule.Target.TopicID == "" { - return fmt.Errorf("invalid rule: topicId is required for routingType 'msgq'") - } - case "bpp", "bap": - // No target validation needed for bpp/bap, as they use URIs from the request body - continue - default: - return fmt.Errorf("invalid rule: unknown routingType '%s'", rule.RoutingType) - } - } - return nil -} - -// Route determines the routing destination based on the request context. -func (r *Router) Route(ctx context.Context, url *url.URL, body []byte) (*definition.Route, error) { - - // Parse the body to extract domain and version - var requestBody struct { - Context struct { - Domain string `json:"domain"` - Version string `json:"version"` - BppURI string `json:"bpp_uri,omitempty"` - BapURI string `json:"bap_uri,omitempty"` - } `json:"context"` - } - if err := json.Unmarshal(body, &requestBody); err != nil { - return nil, fmt.Errorf("error parsing request body: %w", err) - } - - // Extract the endpoint from the URL - endpoint := path.Base(url.Path) - - // Collect all matching rules for the domain and version - matchingRules := r.getMatchingRules(requestBody.Context.Domain, requestBody.Context.Version) - - // If no matching rules are found, return an error - if len(matchingRules) == 0 { - return nil, fmt.Errorf("no matching routing rule found for domain %s and version %s", requestBody.Context.Domain, requestBody.Context.Version) - } - - // Match the rule - for _, rule := range matchingRules { - for _, ep := range rule.Endpoints { - if strings.EqualFold(ep, endpoint) { - switch rule.RoutingType { - case "msgq": - return &definition.Route{ - RoutingType: rule.RoutingType, - TopicID: rule.Target.TopicID, - }, nil - case "url": - return &definition.Route{ - RoutingType: rule.RoutingType, - TargetURL: rule.Target.URL, - }, nil - case "bpp": - return handleRouting(rule, requestBody.Context.BppURI, endpoint, "bpp") - case "bap": - return handleRouting(rule, requestBody.Context.BapURI, endpoint, "bap") - default: - return nil, fmt.Errorf("unsupported routingType: %s", rule.RoutingType) - } - } - } - } - - // If domain and version match but endpoint is not found, return an error - return nil, fmt.Errorf("endpoint '%s' is not supported for domain %s and version %s", endpoint, requestBody.Context.Domain, requestBody.Context.Version) -} - -// getMatchingRules returns all rules that match the given domain and version -func (r *Router) getMatchingRules(domain, version string) []routingRule { - var matchingRules []routingRule - for _, rule := range r.rules { - if rule.Domain == domain && rule.Version == version { - matchingRules = append(matchingRules, rule) - } - } - return matchingRules -} - -// handleRouting handles routing for bap and bpp routing type -func handleRouting(rule routingRule, uri, endpoint string, routingType string) (*definition.Route, error) { - if uri == "" { - if rule.Target.URL != "" { - return &definition.Route{ - RoutingType: routingType, - TargetURL: rule.Target.URL, - }, nil - } else { - return nil, fmt.Errorf("no target URI or URL found for %s routing type and %s endpoint", routingType, endpoint) - } - } - return &definition.Route{ - RoutingType: routingType, - TargetURL: uri, - }, nil -} diff --git a/pkg/plugin/implementation/router/router_test.go b/pkg/plugin/implementation/router/router_test.go deleted file mode 100644 index 3d3fe70..0000000 --- a/pkg/plugin/implementation/router/router_test.go +++ /dev/null @@ -1,452 +0,0 @@ -package router - -import ( - "context" - "embed" - "net/url" - "os" - "path/filepath" - "strings" - "testing" -) - -//go:embed testData/* -var testData embed.FS - -func setupTestConfig(t *testing.T, yamlFileName string) string { - t.Helper() - - // Create a temporary directory for the routing rules - configDir, err := os.MkdirTemp("", "routing_rules") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - - // Read the YAML file content - yamlContent := readYAMLFile(t, yamlFileName) - - // Write the routing rules to a file - rulesFilePath := filepath.Join(configDir, "routing_rules.yaml") - if err := os.WriteFile(rulesFilePath, []byte(yamlContent), 0644); err != nil { - t.Fatalf("Failed to write routing rules file: %v", err) - } - - return rulesFilePath -} - -func readYAMLFile(t *testing.T, fileName string) string { - t.Helper() - - // Read the YAML file - content, err := testData.ReadFile("testData/" + fileName) - if err != nil { - t.Fatalf("Failed to read YAML file: %v", err) - } - - return string(content) -} - -// setupRouter is a helper function to create router instance. -func setupRouter(t *testing.T, configFile string) (*Router, func() error, string) { - rulesFilePath := setupTestConfig(t, configFile) - config := &Config{ - RoutingConfig: rulesFilePath, - } - router, _, err := New(context.Background(), config) - if err != nil { - t.Fatalf("New failed: %v", err) - } - return router, nil, rulesFilePath -} - -// TestNew tests the New function. -func TestNew(t *testing.T) { - ctx := context.Background() - - // List of YAML files in the testData directory - yamlFiles := []string{ - "bap_caller.yaml", - "bap_receiver.yaml", - "bpp_caller.yaml", - "bpp_receiver.yaml", - } - - for _, yamlFile := range yamlFiles { - t.Run(yamlFile, func(t *testing.T) { - rulesFilePath := setupTestConfig(t, yamlFile) - defer os.RemoveAll(filepath.Dir(rulesFilePath)) - - // Define test cases - tests := []struct { - name string - config *Config - expectedError string - }{ - { - name: "Valid configuration", - config: &Config{ - RoutingConfig: rulesFilePath, - }, - expectedError: "", - }, - { - name: "Empty config", - config: nil, - expectedError: "config cannot be nil", - }, - { - name: "Empty routing config path", - config: &Config{ - RoutingConfig: "", - }, - expectedError: "routingConfig path is empty", - }, - { - name: "Routing config file does not exist", - config: &Config{ - RoutingConfig: "/nonexistent/path/to/rules.yaml", - }, - expectedError: "error reading config file", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - router, _, err := New(ctx, tt.config) - - // Check for expected error - if tt.expectedError != "" { - if err == nil || !strings.Contains(err.Error(), tt.expectedError) { - t.Errorf("expected error %q, got %v", tt.expectedError, err) - } - return - } - - // Ensure no error occurred - if err != nil { - t.Errorf("unexpected error: %v", err) - return - } - - // Ensure the router and close function are not nil - if router == nil { - t.Error("expected a non-nil Router instance, got nil") - } - }) - } - }) - } -} - -// TestValidateRulesSuccess tests the validate function for success cases. -func TestValidateRulesSuccess(t *testing.T) { - tests := []struct { - name string - rules []routingRule - }{ - { - name: "Valid rules with url routing", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "url", - Target: target{ - URL: "https://example.com/api", - }, - Endpoints: []string{"on_search", "on_select"}, - }, - }, - }, - { - name: "Valid rules with msgq routing", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "msgq", - Target: target{ - TopicID: "example_topic", - }, - Endpoints: []string{"on_search", "on_select"}, - }, - }, - }, - { - name: "Valid rules with bpp routing to gateway", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "bpp", - Target: target{ - URL: "https://mock_gateway.com/api", - }, - Endpoints: []string{"search"}, - }, - }, - }, - { - name: "Valid rules with bpp routing", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "bpp", - Endpoints: []string{"select"}, - }, - }, - }, - { - name: "Valid rules with bap routing", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "bap", - Endpoints: []string{"select"}, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateRules(tt.rules) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - }) - } -} - -// TestValidateRulesFailure tests the validate function for failure cases. -func TestValidateRulesFailure(t *testing.T) { - tests := []struct { - name string - rules []routingRule - expectedErr string - }{ - { - name: "Missing domain", - rules: []routingRule{ - { - Version: "1.0.0", - RoutingType: "url", - Target: target{ - URL: "https://example.com/api", - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: domain, version, and routingType are required", - }, - { - name: "Missing version", - rules: []routingRule{ - { - Domain: "retail", - RoutingType: "url", - Target: target{ - URL: "https://example.com/api", - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: domain, version, and routingType are required", - }, - { - name: "Missing routingType", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - Target: target{ - URL: "https://example.com/api", - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: domain, version, and routingType are required", - }, - { - name: "Invalid routingType", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "invalid", - Target: target{ - URL: "https://example.com/api", - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: unknown routingType 'invalid'", - }, - { - name: "Missing url for routingType: url", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "url", - Target: target{ - // URL is missing - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: url is required for routingType 'url'", - }, - { - name: "Missing topic_id for routingType: msgq", - rules: []routingRule{ - { - Domain: "retail", - Version: "1.0.0", - RoutingType: "msgq", - Target: target{ - // TopicID is missing - }, - Endpoints: []string{"search", "select"}, - }, - }, - expectedErr: "invalid rule: topicId is required for routingType 'msgq'", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateRules(tt.rules) - if err == nil { - t.Errorf("expected error: %v, got nil", tt.expectedErr) - } else if err.Error() != tt.expectedErr { - t.Errorf("expected error: %v, got: %v", tt.expectedErr, err) - } - }) - } -} - -// TestRouteSuccess tests the Route function for success cases. -func TestRouteSuccess(t *testing.T) { - ctx := context.Background() - - // Define success test cases - tests := []struct { - name string - configFile string - url string - body string - }{ - { - name: "Valid domain, version, and endpoint (bpp routing with gateway URL)", - configFile: "bap_caller.yaml", - url: "https://example.com/v1/ondc/search", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0"}}`, - }, - { - name: "Valid domain, version, and endpoint (bpp routing with bpp_uri)", - configFile: "bap_caller.yaml", - url: "https://example.com/v1/ondc/select", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0", "bpp_uri": "https://bpp1.example.com"}}`, - }, - { - name: "Valid domain, version, and endpoint (url routing)", - configFile: "bpp_receiver.yaml", - url: "https://example.com/v1/ondc/select", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0"}}`, - }, - { - name: "Valid domain, version, and endpoint (msgq routing)", - configFile: "bpp_receiver.yaml", - url: "https://example.com/v1/ondc/search", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0"}}`, - }, - { - name: "Valid domain, version, and endpoint (bap routing with bap_uri)", - configFile: "bpp_caller.yaml", - url: "https://example.com/v1/ondc/on_select", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0", "bap_uri": "https://bap1.example.com"}}`, - }, - { - name: "Valid domain, version, and endpoint (bpp routing with bpp_uri)", - configFile: "bap_receiver.yaml", - url: "https://example.com/v1/ondc/on_select", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0", "bpp_uri": "https://bpp1.example.com"}}`, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - router, _, rulesFilePath := setupRouter(t, tt.configFile) - defer os.RemoveAll(filepath.Dir(rulesFilePath)) - - parsedURL, _ := url.Parse(tt.url) - _, err := router.Route(ctx, parsedURL, []byte(tt.body)) - - // Ensure no error occurred - if err != nil { - t.Errorf("unexpected error: %v", err) - } - }) - } -} - -// TestRouteFailure tests the Route function for failure cases. -func TestRouteFailure(t *testing.T) { - ctx := context.Background() - - // Define failure test cases - tests := []struct { - name string - configFile string - url string - body string - expectedError string - }{ - { - name: "Unsupported endpoint", - configFile: "bpp_receiver.yaml", - url: "https://example.com/v1/ondc/unsupported", - body: `{"context": {"domain": "ONDC:TRV11", "version": "2.0.0"}}`, - expectedError: "endpoint 'unsupported' is not supported for domain ONDC:TRV11 and version 2.0.0", - }, - { - name: "No matching rule", - configFile: "bpp_receiver.yaml", - url: "https://example.com/v1/ondc/select", - body: `{"context": {"domain": "ONDC:SRV11", "version": "2.0.0"}}`, - expectedError: "no matching routing rule found for domain ONDC:SRV11 and version 2.0.0", - }, - { - name: "Missing bap_uri for bap routing", - configFile: "bpp_caller.yaml", - url: "https://example.com/v1/ondc/on_search", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0"}}`, - expectedError: "no target URI or URL found for bap routing type and on_search endpoint", - }, - { - name: "Missing bpp_uri for bpp routing", - configFile: "bap_caller.yaml", - url: "https://example.com/v1/ondc/select", - body: `{"context": {"domain": "ONDC:TRV10", "version": "2.0.0"}}`, - expectedError: "no target URI or URL found for bpp routing type and select endpoint", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - router, _, rulesFilePath := setupRouter(t, tt.configFile) - defer os.RemoveAll(filepath.Dir(rulesFilePath)) - - parsedURL, _ := url.Parse(tt.url) - _, err := router.Route(ctx, parsedURL, []byte(tt.body)) - - // Check for expected error - if err == nil || !strings.Contains(err.Error(), tt.expectedError) { - t.Errorf("expected error %q, got %v", tt.expectedError, err) - } - }) - } -} diff --git a/pkg/plugin/implementation/router/testData/bap_caller.yaml b/pkg/plugin/implementation/router/testData/bap_caller.yaml deleted file mode 100644 index b1d5a44..0000000 --- a/pkg/plugin/implementation/router/testData/bap_caller.yaml +++ /dev/null @@ -1,25 +0,0 @@ -routingRules: - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "bpp" - target: - url: "https://gateway.example.com" - endpoints: - - search - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "bpp" - endpoints: - - select - - init - - confirm - - status - - cancel - - domain: "ONDC:TRV12" - version: "2.0.0" - routingType: "bpp" - endpoints: - - select - - init - - confirm - - status \ No newline at end of file diff --git a/pkg/plugin/implementation/router/testData/bap_receiver.yaml b/pkg/plugin/implementation/router/testData/bap_receiver.yaml deleted file mode 100644 index ca4a478..0000000 --- a/pkg/plugin/implementation/router/testData/bap_receiver.yaml +++ /dev/null @@ -1,20 +0,0 @@ -routingRules: - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "url" - target: - url: "https://services-backend/trv/v1" - endpoints: - - on_select - - on_init - - on_confirm - - on_status - - on_update - - on_cancel - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "msgq" - target: - topic_id: "trv_topic_id1" - endpoints: - - on_search \ No newline at end of file diff --git a/pkg/plugin/implementation/router/testData/bpp_caller.yaml b/pkg/plugin/implementation/router/testData/bpp_caller.yaml deleted file mode 100644 index 0d9a670..0000000 --- a/pkg/plugin/implementation/router/testData/bpp_caller.yaml +++ /dev/null @@ -1,23 +0,0 @@ -routingRules: - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "bap" - endpoints: - - on_search - - on_select - - on_init - - on_confirm - - on_status - - on_update - - on_cancel - - domain: "ONDC:TRV11" - version: "2.0.0" - routingType: "bap" - endpoints: - - on_search - - on_select - - on_init - - on_confirm - - on_status - - on_update - - on_cancel \ No newline at end of file diff --git a/pkg/plugin/implementation/router/testData/bpp_receiver.yaml b/pkg/plugin/implementation/router/testData/bpp_receiver.yaml deleted file mode 100644 index 6febce6..0000000 --- a/pkg/plugin/implementation/router/testData/bpp_receiver.yaml +++ /dev/null @@ -1,30 +0,0 @@ -routingRules: - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "url" - target: - url: "https://services-backend/trv/v1" - endpoints: - - select - - init - - confirm - - status - - cancel - - - domain: "ONDC:TRV10" - version: "2.0.0" - routingType: "msgq" - target: - topic_id: "trv_topic_id1" - endpoints: - - search - - - domain: "ONDC:TRV11" - version: "2.0.0" - routingType: "url" - target: - url: "https://services-backend/trv/v1" - endpoints: - - select - - init - - confirm \ No newline at end of file diff --git a/pkg/plugin/implementation/schemaValidator/cmd/plugin.go b/pkg/plugin/implementation/schemaValidator/cmd/plugin.go index 6882ce4..2a8f44a 100644 --- a/pkg/plugin/implementation/schemaValidator/cmd/plugin.go +++ b/pkg/plugin/implementation/schemaValidator/cmd/plugin.go @@ -17,10 +17,10 @@ func (vp schemaValidatorProvider) New(ctx context.Context, config map[string]str return nil, nil, errors.New("context cannot be nil") } - // Extract schema_dir from the config map - schemaDir, ok := config["schema_dir"] + // Extract schemaDir from the config map + schemaDir, ok := config["schemaDir"] if !ok || schemaDir == "" { - return nil, nil, errors.New("config must contain 'schema_dir'") + return nil, nil, errors.New("config must contain 'schemaDir'") } // Create a new schemaValidator instance with the provided configuration diff --git a/pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go b/pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go index 7e06b55..59be949 100644 --- a/pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go +++ b/pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go @@ -63,7 +63,7 @@ func TestValidatorProviderSuccess(t *testing.T) { { name: "Valid schema directory", ctx: context.Background(), // Valid context - config: map[string]string{"schema_dir": schemaDir}, + config: map[string]string{"schemaDir": schemaDir}, expectedError: "", }, } @@ -114,24 +114,24 @@ func TestValidatorProviderFailure(t *testing.T) { name: "Config is empty", ctx: context.Background(), config: map[string]string{}, - expectedError: "config must contain 'schema_dir'", + expectedError: "config must contain 'schemaDir'", }, { - name: "schema_dir is empty", + name: "schemaDir is empty", ctx: context.Background(), - config: map[string]string{"schema_dir": ""}, - expectedError: "config must contain 'schema_dir'", + config: map[string]string{"schemaDir": ""}, + expectedError: "config must contain 'schemaDir'", }, { name: "Invalid schema directory", ctx: context.Background(), // Valid context - config: map[string]string{"schema_dir": "/invalid/dir"}, + config: map[string]string{"schemaDir": "/invalid/dir"}, expectedError: "failed to initialise schemaValidator: schema directory does not exist: /invalid/dir", }, { name: "Nil context", ctx: nil, // Nil context - config: map[string]string{"schema_dir": schemaDir}, + config: map[string]string{"schemaDir": schemaDir}, expectedError: "context cannot be nil", }, } diff --git a/pkg/plugin/implementation/schemaValidator/schemaValidator.go b/pkg/plugin/implementation/schemaValidator/schemaValidator.go index a46ceb2..2d6b189 100644 --- a/pkg/plugin/implementation/schemaValidator/schemaValidator.go +++ b/pkg/plugin/implementation/schemaValidator/schemaValidator.go @@ -49,7 +49,7 @@ func New(ctx context.Context, config *Config) (*SchemaValidator, func() error, e if err := v.initialise(); err != nil { return nil, nil, fmt.Errorf("failed to initialise schemaValidator: %v", err) } - return v, v.Close, nil + return v, nil, nil } // Validate validates the given data against the schema. @@ -195,8 +195,3 @@ func (v *SchemaValidator) initialise() error { return nil } - -// Close releases resources (mock implementation returning nil). -func (v *SchemaValidator) Close() error { - return nil -} diff --git a/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go b/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go index b60c834..277b539 100644 --- a/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go +++ b/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go @@ -289,7 +289,7 @@ func TestValidator_Initialise(t *testing.T) { } } -func TestValidator_New_Success(t *testing.T) { +func TestValidatorNew_Success(t *testing.T) { schemaDir := setupTestSchema(t) defer os.RemoveAll(schemaDir) @@ -300,7 +300,7 @@ func TestValidator_New_Success(t *testing.T) { } } -func TestValidator_New_Failure(t *testing.T) { +func TestValidatorNewFailure(t *testing.T) { tests := []struct { name string config *Config @@ -315,22 +315,6 @@ func TestValidator_New_Failure(t *testing.T) { }, wantErr: "config cannot be nil", }, - // { - // name: "Config is empty", - // config: &Config{}, - // setupFunc: func(schemaDir string) error { - // return nil - // }, - // wantErr: "config must contain 'schema_dir'", - // }, - // { - // name: "schema_dir is empty", - // config: &Config{SchemaDir: ""}, - // setupFunc: func(schemaDir string) error { - // return nil - // }, - // wantErr: "config must contain 'schema_dir'", - // }, { name: "Failed to initialise validators", config: &Config{ diff --git a/pkg/plugin/manager.go b/pkg/plugin/manager.go index 209e0e6..5e75357 100644 --- a/pkg/plugin/manager.go +++ b/pkg/plugin/manager.go @@ -27,11 +27,6 @@ type PluginConfig struct { Config map[string]string `yaml:"config"` } -// SchemaDetails contains information about the plugin schema directory. -type SchemaDetails struct { - SchemaDir string `yaml:"schemaDir"` -} - // Manager handles dynamic plugin loading and management. type Manager struct { sp definition.SignerProvider @@ -79,7 +74,13 @@ func NewManager(ctx context.Context, cfg *Config) (*Manager, error) { return nil, fmt.Errorf("failed to load encryption plugin: %w", err) } - return &Manager{sp: sp, vp: vp, pb: pb, ep: ep, dp: dp, cfg: cfg}, nil + // Load schema validation plugin. + svp, err := provider[definition.SchemaValidatorProvider](cfg.Root, cfg.Encrypter.ID) + if err != nil { + return nil, fmt.Errorf("failed to load schema validation plugin: %w", err) + } + + return &Manager{sp: sp, vp: vp, pb: pb, ep: ep, dp: dp, svp: svp, cfg: cfg}, nil } // provider loads a plugin dynamically and retrieves its provider instance. @@ -176,3 +177,16 @@ func (m *Manager) Publisher(ctx context.Context) (definition.Publisher, error) { } return publisher, nil } + +// Encrypter retrieves the encryption plugin instance. +func (m *Manager) SchemaValidation(ctx context.Context) (definition.SchemaValidator, func() error, error) { + if m.svp == nil { + return nil, nil, fmt.Errorf("schema validation plugin provider not loaded") + } + + schemaValidator, close, err := m.svp.New(ctx, m.cfg.SchemaValidator.Config) + if err != nil { + return nil, nil, fmt.Errorf("failed to initialize schema validator: %w", err) + } + return schemaValidator, close, nil +}