diff --git a/pkg/discovery/gateway/client.go b/pkg/discovery/agent/agent.go similarity index 76% rename from pkg/discovery/gateway/client.go rename to pkg/discovery/agent/agent.go index f3eea9f..ab0cff2 100644 --- a/pkg/discovery/gateway/client.go +++ b/pkg/discovery/agent/agent.go @@ -1,10 +1,9 @@ -package gateway +package agent import ( "context" "crypto/sha256" "fmt" - "net/http" "net/url" "sync" @@ -14,6 +13,7 @@ import ( "github.com/Axway/agent-sdk/pkg/apic" "github.com/Axway/agent-sdk/pkg/apic/provisioning" "github.com/Axway/agent-sdk/pkg/cache" + corecfg "github.com/Axway/agent-sdk/pkg/config" "github.com/Axway/agent-sdk/pkg/filter" "github.com/Axway/agent-sdk/pkg/util" "github.com/Axway/agent-sdk/pkg/util/log" @@ -21,61 +21,98 @@ import ( "github.com/Axway/agents-kong/pkg/common" "github.com/Axway/agents-kong/pkg/discovery/config" "github.com/Axway/agents-kong/pkg/discovery/kong" - kutil "github.com/Axway/agents-kong/pkg/discovery/kong" "github.com/Axway/agents-kong/pkg/discovery/subscription" ) -const ( - https = "https" -) - var kongToCRDMapper = map[string]string{ kong.BasicAuthPlugin: provisioning.BasicAuthCRD, kong.KeyAuthPlugin: provisioning.APIKeyCRD, kong.OAuthPlugin: provisioning.OAuthSecretCRD, } -func NewClient(agentConfig config.AgentConfig) (*Client, error) { - kongGatewayConfig := agentConfig.KongGatewayCfg - clientBase := &http.Client{} - kongClient, err := kutil.NewKongClient(clientBase, kongGatewayConfig) +type kongClient interface { + // Provisioning + CreateConsumer(ctx context.Context, id, name string) (*klib.Consumer, error) + AddConsumerACL(ctx context.Context, id string) error + DeleteConsumer(ctx context.Context, id string) error + // Credential + DeleteOauth2(ctx context.Context, consumerID, clientID string) error + DeleteHttpBasic(ctx context.Context, consumerID, username string) error + DeleteAuthKey(ctx context.Context, consumerID, authKey string) error + CreateHttpBasic(ctx context.Context, consumerID string, basicAuth *klib.BasicAuth) (*klib.BasicAuth, error) + CreateOauth2(ctx context.Context, consumerID string, oauth2 *klib.Oauth2Credential) (*klib.Oauth2Credential, error) + CreateAuthKey(ctx context.Context, consumerID string, keyAuth *klib.KeyAuth) (*klib.KeyAuth, error) + // Access Request + AddRouteACL(ctx context.Context, routeID, allowedID string) error + RemoveRouteACL(ctx context.Context, routeID, revokedID string) error + AddQuota(ctx context.Context, routeID, allowedID, quotaInterval string, quotaLimit int) error + // Discovery + ListServices(ctx context.Context) ([]*klib.Service, error) + ListRoutesForService(ctx context.Context, serviceId string) ([]*klib.Route, error) + GetSpecForService(ctx context.Context, service *klib.Service) ([]byte, error) + GetKongPlugins() *kong.Plugins +} + +type Agent struct { + logger log.FieldLogger + centralCfg corecfg.CentralConfig + kongGatewayCfg *config.KongGatewayConfig + kongClient kongClient + plugins kong.Plugins + cache cache.Cache + filter filter.Filter +} + +func NewAgent(agentConfig config.AgentConfig, agentOpts ...func(a *Agent)) (*Agent, error) { + ka := &Agent{ + logger: log.NewFieldLogger().WithComponent("agent").WithPackage("kongAgent"), + centralCfg: agentConfig.CentralCfg, + kongGatewayCfg: agentConfig.KongGatewayCfg, + cache: cache.New(), + } + for _, o := range agentOpts { + o(ka) + } + + var err error + if ka.kongClient == nil { + ka.kongClient, err = kong.NewKongClient(ka.kongGatewayCfg) + } if err != nil { return nil, err } - daCache := cache.New() - logger := log.NewFieldLogger().WithField("component", "agent") - plugins, err := kongClient.Plugins.ListAll(context.Background()) + pluginLister := ka.kongClient.GetKongPlugins() + if pluginLister == nil { + return nil, fmt.Errorf("could not get kong plugin lister") + } + plugins, err := ka.kongClient.GetKongPlugins().ListAll(context.Background()) if err != nil { return nil, err } - discoveryFilter, err := filter.NewFilter(agentConfig.KongGatewayCfg.Spec.Filter) + ka.filter, err = filter.NewFilter(agentConfig.KongGatewayCfg.Spec.Filter) if err != nil { return nil, err } - if err = hasGlobalACLEnabledInPlugins(logger, plugins, agentConfig.KongGatewayCfg.ACL.Disable); err != nil { - logger.WithError(err).Error("ACL Plugin configured as required, but none found in Kong plugins.") + if err = hasGlobalACLEnabledInPlugins(ka.logger, plugins, agentConfig.KongGatewayCfg.ACL.Disable); err != nil { + ka.logger.WithError(err).Error("ACL Plugin configured as required, but none found in Kong plugins.") return nil, err } - provisionLogger := log.NewFieldLogger().WithComponent("provision").WithPackage("kong") opts := []subscription.ProvisionerOption{} if agentConfig.KongGatewayCfg.ACL.Disable { opts = append(opts, subscription.WithACLDisable()) } - subscription.NewProvisioner(kongClient, provisionLogger, opts...) + subscription.NewProvisioner(ka.kongClient, opts...) + return ka, nil +} - return &Client{ - logger: logger, - centralCfg: agentConfig.CentralCfg, - kongGatewayCfg: kongGatewayConfig, - kongClient: kongClient, - cache: daCache, - mode: common.Marketplace, - filter: discoveryFilter, - }, nil +func withKongClient(kongClient kongClient) func(a *Agent) { + return func(a *Agent) { + a.kongClient = kongClient + } } func pluginIsGlobal(p *klib.Plugin) bool { @@ -99,13 +136,13 @@ func hasGlobalACLEnabledInPlugins(logger log.FieldLogger, plugins []*klib.Plugin return fmt.Errorf("acl plugin is not enabled/installed, install and enable or change the config to disable this check") } -func (gc *Client) DiscoverAPIs() error { +func (gc *Agent) DiscoverAPIs() error { gc.logger.Info("execute discovery process") ctx := context.Background() var err error - plugins := kutil.Plugins{PluginLister: gc.kongClient.GetKongPlugins()} + plugins := kong.Plugins{PluginLister: gc.kongClient.GetKongPlugins()} gc.plugins = plugins services, err := gc.kongClient.ListServices(ctx) @@ -118,7 +155,7 @@ func (gc *Client) DiscoverAPIs() error { return nil } -func (gc *Client) processKongServicesList(ctx context.Context, services []*klib.Service) { +func (gc *Agent) processKongServicesList(ctx context.Context, services []*klib.Service) { wg := new(sync.WaitGroup) for _, service := range services { if !gc.filter.Evaluate(toTagsMap(service)) { @@ -146,7 +183,7 @@ func toTagsMap(service *klib.Service) map[string]string { return filters } -func (gc *Client) processSingleKongService(ctx context.Context, service *klib.Service) error { +func (gc *Agent) processSingleKongService(ctx context.Context, service *klib.Service) error { log := gc.logger.WithField(common.AttrServiceName, *service.Name) log.Info("processing service") @@ -184,7 +221,7 @@ func (gc *Client) processSingleKongService(ctx context.Context, service *klib.Se return nil } -func (gc *Client) specPreparation(ctx context.Context, route *klib.Route, service *klib.Service, spec apic.SpecProcessor) { +func (gc *Agent) specPreparation(ctx context.Context, route *klib.Route, service *klib.Service, spec apic.SpecProcessor) { log := gc.logger.WithField(common.AttrRouteID, *route.ID). WithField(common.AttrServiceID, *service.ID) @@ -218,7 +255,7 @@ func (gc *Client) specPreparation(ctx context.Context, route *klib.Route, servic log.Info("Successfully published to central") } -func (gc *Client) processKongRoute(route *klib.Route) []apic.EndpointDefinition { +func (gc *Agent) processKongRoute(route *klib.Route) []apic.EndpointDefinition { if route == nil { return []apic.EndpointDefinition{} } @@ -234,7 +271,7 @@ func (gc *Client) processKongRoute(route *klib.Route) []apic.EndpointDefinition return kRoute.GetEndpoints() } -func (gc *Client) processKongAPI( +func (gc *Agent) processKongAPI( ctx context.Context, route *klib.Route, service *klib.Service, @@ -347,9 +384,9 @@ func (ka *KongAPI) oAuthSecurity(spec apic.OasSpecProcessor, config map[string]i s := url.URL{} for _, e := range ka.endpoints { - if e.Protocol == https { + if e.Protocol == httpsScheme { s = url.URL{ - Scheme: https, + Scheme: httpsScheme, Host: fmt.Sprintf("%v:%v", e.Host, e.Port), Path: e.BasePath, } diff --git a/pkg/discovery/agent/agent_test.go b/pkg/discovery/agent/agent_test.go new file mode 100644 index 0000000..935659d --- /dev/null +++ b/pkg/discovery/agent/agent_test.go @@ -0,0 +1,142 @@ +package agent + +import ( + "context" + "testing" + + "github.com/Axway/agent-sdk/pkg/agent" + "github.com/Axway/agent-sdk/pkg/apic/mock" + "github.com/Axway/agent-sdk/pkg/cache" + corecfg "github.com/Axway/agent-sdk/pkg/config" + "github.com/Axway/agent-sdk/pkg/filter" + "github.com/Axway/agent-sdk/pkg/util/log" + config "github.com/Axway/agents-kong/pkg/discovery/config" + "github.com/Axway/agents-kong/pkg/discovery/kong" + klib "github.com/kong/go-kong/kong" + "github.com/stretchr/testify/assert" +) + +func stringPtr(s string) *string { + return &s +} + +func boolPtr(b bool) *bool { + return &b +} + +func intPtr(i int) *int { + return &i +} + +func TestNewAgent(t *testing.T) { + testCases := map[string]struct { + gatewayConfig *config.KongGatewayConfig + client *mockKongClient + expectErr bool + }{ + "error when plugin lister is not created": { + gatewayConfig: &config.KongGatewayConfig{}, + client: &mockKongClient{}, + expectErr: true, + }, + "error getting kong plugins using lister": { + gatewayConfig: &config.KongGatewayConfig{}, + client: &mockKongClient{ + GetKongPluginsMock: func() *kong.Plugins { + return &kong.Plugins{PluginLister: &mockPluginLister{}} + }, + }, + expectErr: true, + }, + "error hit because ACL was not installed": { + gatewayConfig: &config.KongGatewayConfig{}, + client: &mockKongClient{ + GetKongPluginsMock: func() *kong.Plugins { + return &kong.Plugins{PluginLister: &mockPluginLister{plugins: []*klib.Plugin{}}} + }, + }, + expectErr: true, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + cfg := config.AgentConfig{ + CentralCfg: corecfg.NewCentralConfig(corecfg.DiscoveryAgent), + KongGatewayCfg: tc.gatewayConfig, + } + agent.InitializeForTest(&mock.Client{}, agent.TestWithMarketplace()) + + a, err := NewAgent(cfg, withKongClient(tc.client)) + if tc.expectErr { + assert.Nil(t, a) + assert.NotNil(t, err) + } + }) + } +} + +func TestDiscovery(t *testing.T) { + testCases := map[string]struct { + client *mockKongClient + expectErr bool + }{ + "expect error when services call fails": { + client: &mockKongClient{ + GetKongPluginsMock: func() *kong.Plugins { + return &kong.Plugins{PluginLister: &mockPluginLister{plugins: []*klib.Plugin{}}} + }, + }, + expectErr: true, + }, + "success when no services returned": { + client: &mockKongClient{ + GetKongPluginsMock: func() *kong.Plugins { + return &kong.Plugins{PluginLister: &mockPluginLister{plugins: []*klib.Plugin{}}} + }, + ListServicesMock: func(context.Context) ([]*klib.Service, error) { + return []*klib.Service{}, nil + }, + }, + }, + "success when services returned but no routes": { + client: &mockKongClient{ + GetKongPluginsMock: func() *kong.Plugins { + return &kong.Plugins{PluginLister: &mockPluginLister{plugins: []*klib.Plugin{}}} + }, + ListServicesMock: func(context.Context) ([]*klib.Service, error) { + return []*klib.Service{ + { + Enabled: boolPtr(true), + Host: stringPtr("petstore.com"), + ID: stringPtr("petstore-id"), + Name: stringPtr("PetStore"), + Tags: []*string{}, + }, + }, nil + }, + }, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + f, _ := filter.NewFilter("") + ka := &Agent{ + logger: log.NewFieldLogger().WithComponent("agent").WithPackage("kongAgent"), + centralCfg: corecfg.NewCentralConfig(corecfg.DiscoveryAgent), + kongGatewayCfg: &config.KongGatewayConfig{}, + cache: cache.New(), + kongClient: tc.client, + filter: f, + } + + // agent.InitializeForTest() + + err := ka.DiscoverAPIs() + if tc.expectErr { + assert.NotNil(t, err) + return + } + assert.Nil(t, err) + }) + } +} diff --git a/pkg/discovery/agent/definitions.go b/pkg/discovery/agent/definitions.go new file mode 100644 index 0000000..be5fb6d --- /dev/null +++ b/pkg/discovery/agent/definitions.go @@ -0,0 +1,26 @@ +package agent + +import ( + "github.com/Axway/agent-sdk/pkg/apic" +) + +type KongAPI struct { + spec []byte + id string + name string + description string + version string + url string + documentation []byte + resourceType string + endpoints []apic.EndpointDefinition + image string + imageContentType string + crds []string + apiUpdateSeverity string + agentDetails map[string]string + tags []string + stage string + stageName string + ard string +} diff --git a/pkg/discovery/agent/mockkongclient_test.go b/pkg/discovery/agent/mockkongclient_test.go new file mode 100644 index 0000000..c64d18f --- /dev/null +++ b/pkg/discovery/agent/mockkongclient_test.go @@ -0,0 +1,155 @@ +package agent + +import ( + "context" + "fmt" + + "github.com/Axway/agents-kong/pkg/discovery/kong" + klib "github.com/kong/go-kong/kong" +) + +type mockKongClient struct { + // Provisioning + CreateConsumerMock func(context.Context, string, string) (*klib.Consumer, error) + AddConsumerACLMock func(context.Context, string) error + DeleteConsumerMock func(context.Context, string) error + // Credential + DeleteOauth2Mock func(context.Context, string, string) error + DeleteHttpBasicMock func(context.Context, string, string) error + DeleteAuthKeyMock func(context.Context, string, string) error + CreateHttpBasicMock func(context.Context, string, *klib.BasicAuth) (*klib.BasicAuth, error) + CreateOauth2Mock func(context.Context, string, *klib.Oauth2Credential) (*klib.Oauth2Credential, error) + CreateAuthKeyMock func(context.Context, string, *klib.KeyAuth) (*klib.KeyAuth, error) + // Access Request + AddRouteACLMock func(context.Context, string, string) error + RemoveRouteACLMock func(context.Context, string, string) error + AddQuotaMock func(context.Context, string, string, string, int) error + // Discovery + ListServicesMock func(context.Context) ([]*klib.Service, error) + ListRoutesForServiceMock func(context.Context, string) ([]*klib.Route, error) + GetSpecForServiceMock func(context.Context, *klib.Service) ([]byte, error) + GetKongPluginsMock func() *kong.Plugins +} + +func (m *mockKongClient) CreateConsumer(ctx context.Context, id, name string) (*klib.Consumer, error) { + if m.CreateConsumerMock != nil { + return m.CreateConsumerMock(ctx, id, name) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) AddConsumerACL(ctx context.Context, id string) error { + if m.AddConsumerACLMock != nil { + return m.AddConsumerACLMock(ctx, id) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) DeleteConsumer(ctx context.Context, id string) error { + if m.DeleteConsumerMock != nil { + return m.DeleteConsumerMock(ctx, id) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) DeleteOauth2(ctx context.Context, consumerID, clientID string) error { + if m.DeleteOauth2Mock != nil { + return m.DeleteOauth2Mock(ctx, consumerID, clientID) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) DeleteHttpBasic(ctx context.Context, consumerID, username string) error { + if m.DeleteHttpBasicMock != nil { + return m.DeleteHttpBasicMock(ctx, consumerID, username) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) DeleteAuthKey(ctx context.Context, consumerID, authKey string) error { + if m.DeleteAuthKeyMock != nil { + return m.DeleteAuthKeyMock(ctx, consumerID, authKey) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) CreateHttpBasic(ctx context.Context, consumerID string, basicAuth *klib.BasicAuth) (*klib.BasicAuth, error) { + if m.CreateHttpBasicMock != nil { + return m.CreateHttpBasicMock(ctx, consumerID, basicAuth) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) CreateOauth2(ctx context.Context, consumerID string, oauth2 *klib.Oauth2Credential) (*klib.Oauth2Credential, error) { + if m.CreateOauth2Mock != nil { + return m.CreateOauth2Mock(ctx, consumerID, oauth2) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) CreateAuthKey(ctx context.Context, consumerID string, keyAuth *klib.KeyAuth) (*klib.KeyAuth, error) { + if m.CreateAuthKeyMock != nil { + return m.CreateAuthKeyMock(ctx, consumerID, keyAuth) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) AddRouteACL(ctx context.Context, routeID, allowedID string) error { + if m.AddRouteACLMock != nil { + return m.AddRouteACLMock(ctx, routeID, allowedID) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) RemoveRouteACL(ctx context.Context, routeID, revokedID string) error { + if m.RemoveRouteACLMock != nil { + return m.RemoveRouteACLMock(ctx, routeID, revokedID) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) AddQuota(ctx context.Context, routeID, allowedID, quotaInterval string, quotaLimit int) error { + if m.AddQuotaMock != nil { + return m.AddQuotaMock(ctx, routeID, allowedID, quotaInterval, quotaLimit) + } + return fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) ListServices(ctx context.Context) ([]*klib.Service, error) { + if m.ListServicesMock != nil { + return m.ListServicesMock(ctx) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) ListRoutesForService(ctx context.Context, serviceId string) ([]*klib.Route, error) { + if m.ListRoutesForServiceMock != nil { + return m.ListRoutesForServiceMock(ctx, serviceId) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) GetSpecForService(ctx context.Context, service *klib.Service) ([]byte, error) { + if m.GetSpecForServiceMock != nil { + return m.GetSpecForServiceMock(ctx, service) + } + return nil, fmt.Errorf("unimplemented test func") +} + +func (m *mockKongClient) GetKongPlugins() *kong.Plugins { + if m.GetKongPluginsMock != nil { + return m.GetKongPluginsMock() + } + return nil +} + +type mockPluginLister struct { + plugins []*klib.Plugin +} + +func (m *mockPluginLister) ListAll(ctx context.Context) ([]*klib.Plugin, error) { + if m.plugins == nil { + return nil, fmt.Errorf("not implemented by test") + } + return m.plugins, nil +} diff --git a/pkg/discovery/gateway/route.go b/pkg/discovery/agent/route.go similarity index 87% rename from pkg/discovery/gateway/route.go rename to pkg/discovery/agent/route.go index a7c9d56..270a3e0 100644 --- a/pkg/discovery/gateway/route.go +++ b/pkg/discovery/agent/route.go @@ -1,4 +1,4 @@ -package gateway +package agent import ( "fmt" @@ -7,6 +7,11 @@ import ( klib "github.com/kong/go-kong/kong" ) +const ( + httpScheme = "http" + httpsScheme = "https" +) + type KongRoute struct { *klib.Route defaultHost string @@ -47,19 +52,19 @@ func (r *KongRoute) handlePaths(host, basePath string) []apic.EndpointDefinition func (r *KongRoute) handleProtocols(host, path string) []apic.EndpointDefinition { endpoints := make([]apic.EndpointDefinition, 0) for _, protocol := range r.Protocols { - if *protocol == "http" && r.httpPort != 0 { + if *protocol == httpScheme && r.httpPort != 0 { endpoints = append(endpoints, apic.EndpointDefinition{ Host: host, Port: int32(r.httpPort), - Protocol: "http", + Protocol: httpScheme, BasePath: path, }) } - if *protocol == "https" && r.httpsPort != 0 { + if *protocol == httpsScheme && r.httpsPort != 0 { endpoints = append(endpoints, apic.EndpointDefinition{ Host: host, Port: int32(r.httpsPort), - Protocol: "https", + Protocol: httpsScheme, BasePath: path, }) } diff --git a/pkg/discovery/gateway/route_test.go b/pkg/discovery/agent/route_test.go similarity index 99% rename from pkg/discovery/gateway/route_test.go rename to pkg/discovery/agent/route_test.go index de1de09..d678a7d 100644 --- a/pkg/discovery/gateway/route_test.go +++ b/pkg/discovery/agent/route_test.go @@ -1,4 +1,4 @@ -package gateway +package agent import ( "testing" diff --git a/pkg/discovery/cmd/cmd.go b/pkg/discovery/cmd/cmd.go index 5f39177..ea13655 100644 --- a/pkg/discovery/cmd/cmd.go +++ b/pkg/discovery/cmd/cmd.go @@ -7,8 +7,8 @@ import ( corecfg "github.com/Axway/agent-sdk/pkg/config" "github.com/Axway/agent-sdk/pkg/util/log" + "github.com/Axway/agents-kong/pkg/discovery/agent" "github.com/Axway/agents-kong/pkg/discovery/config" - "github.com/Axway/agents-kong/pkg/discovery/gateway" ) var DiscoveryCmd corecmd.AgentRootCmd @@ -35,14 +35,14 @@ func run() error { var err error stopChan := make(chan struct{}) - gatewayClient, err := gateway.NewClient(agentConfig) + kongAgent, err := agent.NewAgent(agentConfig) if err != nil { return err } go func() { for { - err = gatewayClient.DiscoverAPIs() + err = kongAgent.DiscoverAPIs() if err != nil { log.Errorf("error in processing: %v", err) stopChan <- struct{}{} diff --git a/pkg/discovery/gateway/client_test.go b/pkg/discovery/gateway/client_test.go deleted file mode 100644 index f8fcc00..0000000 --- a/pkg/discovery/gateway/client_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package gateway - -import ( - "testing" - - corecfg "github.com/Axway/agent-sdk/pkg/config" - config "github.com/Axway/agents-kong/pkg/discovery/config" -) - -func TestKongClient(t *testing.T) { - gatewayConfig := &config.KongGatewayConfig{} - _ = config.AgentConfig{ - CentralCfg: corecfg.NewCentralConfig(corecfg.DiscoveryAgent), - KongGatewayCfg: gatewayConfig, - } -} diff --git a/pkg/discovery/gateway/definitions.go b/pkg/discovery/gateway/definitions.go deleted file mode 100644 index c3ffe63..0000000 --- a/pkg/discovery/gateway/definitions.go +++ /dev/null @@ -1,44 +0,0 @@ -package gateway - -import ( - "github.com/Axway/agent-sdk/pkg/apic" - "github.com/Axway/agent-sdk/pkg/cache" - corecfg "github.com/Axway/agent-sdk/pkg/config" - "github.com/Axway/agent-sdk/pkg/filter" - "github.com/Axway/agent-sdk/pkg/util/log" - - config "github.com/Axway/agents-kong/pkg/discovery/config" - "github.com/Axway/agents-kong/pkg/discovery/kong" -) - -type Client struct { - logger log.FieldLogger - centralCfg corecfg.CentralConfig - kongGatewayCfg *config.KongGatewayConfig - kongClient kong.KongAPIClient - plugins kong.Plugins - cache cache.Cache - mode string - filter filter.Filter -} - -type KongAPI struct { - spec []byte - id string - name string - description string - version string - url string - documentation []byte - resourceType string - endpoints []apic.EndpointDefinition - image string - imageContentType string - crds []string - apiUpdateSeverity string - agentDetails map[string]string - tags []string - stage string - stageName string - ard string -} diff --git a/pkg/discovery/kong/kongclient.go b/pkg/discovery/kong/kongclient.go index 57b3074..f8ddbdd 100644 --- a/pkg/discovery/kong/kongclient.go +++ b/pkg/discovery/kong/kongclient.go @@ -67,12 +67,14 @@ type KongClient struct { clientTimeout time.Duration } -func NewKongClient(baseClient *http.Client, kongConfig *config.KongGatewayConfig) (*KongClient, error) { +func NewKongClient(kongConfig *config.KongGatewayConfig) (*KongClient, error) { headers := make(http.Header) var kongEndpoint string kongTransport := http.DefaultTransport.(*http.Transport) kongTransport.TLSClientConfig = kongConfig.Admin.TLS.BuildTLSConfig() - baseClient.Transport = kongTransport + baseClient := &http.Client{ + Transport: kongTransport, + } kongEndpoint = kongConfig.Admin.Url if kongConfig.Admin.Auth.APIKey.Value != "" { diff --git a/pkg/discovery/kong/provisioning_test.go b/pkg/discovery/kong/provisioning_test.go index d3bd7e0..f23ee81 100644 --- a/pkg/discovery/kong/provisioning_test.go +++ b/pkg/discovery/kong/provisioning_test.go @@ -112,7 +112,7 @@ func createClient(responses map[string]response) KongAPIClient { if err := cfg.ValidateCfg(); err != nil { panic(err) } - client, _ := NewKongClient(&http.Client{}, cfg) + client, _ := NewKongClient(cfg) return client } diff --git a/pkg/discovery/subscription/provision.go b/pkg/discovery/subscription/provision.go index c340455..2d09055 100644 --- a/pkg/discovery/subscription/provision.go +++ b/pkg/discovery/subscription/provision.go @@ -3,6 +3,8 @@ package subscription import ( "context" + klib "github.com/kong/go-kong/kong" + "github.com/Axway/agent-sdk/pkg/agent" "github.com/Axway/agent-sdk/pkg/apic/provisioning" "github.com/Axway/agent-sdk/pkg/util/log" @@ -15,14 +17,38 @@ import ( type ProvisionerOption func(*provisioner) +type kongClient interface { + // Provisioning + CreateConsumer(ctx context.Context, id, name string) (*klib.Consumer, error) + AddConsumerACL(ctx context.Context, id string) error + DeleteConsumer(ctx context.Context, id string) error + // Credential + DeleteOauth2(ctx context.Context, consumerID, clientID string) error + DeleteHttpBasic(ctx context.Context, consumerID, username string) error + DeleteAuthKey(ctx context.Context, consumerID, authKey string) error + CreateHttpBasic(ctx context.Context, consumerID string, basicAuth *klib.BasicAuth) (*klib.BasicAuth, error) + CreateOauth2(ctx context.Context, consumerID string, oauth2 *klib.Oauth2Credential) (*klib.Oauth2Credential, error) + CreateAuthKey(ctx context.Context, consumerID string, keyAuth *klib.KeyAuth) (*klib.KeyAuth, error) + // Access Request + AddRouteACL(ctx context.Context, routeID, allowedID string) error + RemoveRouteACL(ctx context.Context, routeID, revokedID string) error + AddQuota(ctx context.Context, routeID, allowedID, quotaInterval string, quotaLimit int) error + // Discovery + ListServices(ctx context.Context) ([]*klib.Service, error) + ListRoutesForService(ctx context.Context, serviceId string) ([]*klib.Route, error) + GetSpecForService(ctx context.Context, service *klib.Service) ([]byte, error) + GetKongPlugins() *kong.Plugins +} + type provisioner struct { logger log.FieldLogger - client kong.KongAPIClient + client kongClient aclDisable bool } // NewProvisioner creates a type to implement the SDK Provisioning methods for handling subscriptions -func NewProvisioner(client kong.KongAPIClient, logger log.FieldLogger, opts ...ProvisionerOption) { +func NewProvisioner(client kongClient, opts ...ProvisionerOption) { + logger := log.NewFieldLogger().WithComponent("provision").WithPackage("subscription") logger.Info("Registering provisioning callbacks") provisioner := &provisioner{ client: client,