diff --git a/apim-apk-agent/internal/constants/constants.go b/apim-apk-agent/internal/constants/constants.go index e305e288..c11c3678 100644 --- a/apim-apk-agent/internal/constants/constants.go +++ b/apim-apk-agent/internal/constants/constants.go @@ -37,7 +37,7 @@ const ( // APIM Mediation constants const ( InterceptorService = "apkCallInterceptorService" - BackendJWT = "BackEndJWT" + BackendJWT = "backEndJWT" AddHeader = "apkAddHeader" RemoveHeader = "apkRemoveHeader" MirrorRequest = "apkMirrorRequest" diff --git a/apim-apk-agent/internal/messaging/notification_listener.go b/apim-apk-agent/internal/messaging/notification_listener.go index b8cd6bd1..fe353a8a 100644 --- a/apim-apk-agent/internal/messaging/notification_listener.go +++ b/apim-apk-agent/internal/messaging/notification_listener.go @@ -428,21 +428,20 @@ func handleAIProviderEvents(data []byte, eventType string, c client.Client) { } if strings.EqualFold(aiProviderCreate, eventType) { - logger.LoggerMessaging.Infof("Create for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.TenantDomain) - synchronizer.FetchAIProvidersOnEvent(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.TenantDomain, c, false) + logger.LoggerMessaging.Infof("Create for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.Event.TenantDomain) + synchronizer.FetchAIProvidersOnEvent(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.Event.TenantDomain, c, false) aiProviders := managementserver.GetAllAIProviders() logger.LoggerMessaging.Debugf("AI Providers Internal Map: %v", aiProviders) } else if strings.EqualFold(aiProviderUpdate, eventType) { - logger.LoggerMessaging.Infof("Update for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.TenantDomain) - synchronizer.FetchAIProvidersOnEvent(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.TenantDomain, c, false) + logger.LoggerMessaging.Infof("Update for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.Event.TenantDomain) + synchronizer.FetchAIProvidersOnEvent(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.Event.TenantDomain, c, false) aiProviders := managementserver.GetAllAIProviders() logger.LoggerMessaging.Debugf("AI Providers Internal Map: %v", aiProviders) } else if strings.EqualFold(aiProviderDelete, eventType) { - logger.LoggerMessaging.Infof("Deletion for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.TenantDomain) - aiProvider := managementserver.GetAIProvider(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.TenantDomain) - sha1ValueforCRName := synchronizer.GetSha1Value(aiProvider.Name + "-" + aiProvider.APIVersion + "-" + aiProvider.Organization) - k8sclient.DeleteAIProviderCR(sha1ValueforCRName, c) - managementserver.DeleteAIProvider(aiProviderEvent.Name, aiProviderEvent.APIVersion, aiProviderEvent.TenantDomain) + logger.LoggerMessaging.Infof("Deletion for AI Provider: %s for tenant: %s", aiProviderEvent.Name, aiProviderEvent.Event.TenantDomain) + aiProvider := managementserver.GetAIProvider(aiProviderEvent.ID) + k8sclient.DeleteAIProviderCR(aiProvider.ID, c) + managementserver.DeleteAIProvider(aiProviderEvent.ID) aiProviders := managementserver.GetAllAIProviders() logger.LoggerMessaging.Debugf("AI Providers Internal Map: %v", aiProviders) } diff --git a/apim-apk-agent/internal/synchronizer/aiproviders_fetcher.go b/apim-apk-agent/internal/synchronizer/aiproviders_fetcher.go index d1ab7116..023415b1 100644 --- a/apim-apk-agent/internal/synchronizer/aiproviders_fetcher.go +++ b/apim-apk-agent/internal/synchronizer/aiproviders_fetcher.go @@ -139,8 +139,8 @@ func FetchAIProvidersOnEvent(aiProviderName string, aiProviderVersion string, or logger.LoggerSynchronizer.Errorf("Error occurred while unmarshelling AI Provider event data %v", err) return } - logger.LoggerSynchronizer.Debugf("AI Providers received: %v", aiProviderList.APIs) - var aiProviders []eventhubTypes.AIProvider = aiProviderList.APIs + logger.LoggerSynchronizer.Debugf("AI Providers received: %v", aiProviderList.AIProviders) + var aiProviders []eventhubTypes.AIProvider = aiProviderList.AIProviders if cleanupDeletedProviders { aiProvidersFromK8, _, errK8 := k8sclient.RetrieveAllAIProvidersFromK8s(c, "") @@ -149,7 +149,7 @@ func FetchAIProvidersOnEvent(aiProviderName string, aiProviderVersion string, or if cpName, exists := aiP.ObjectMeta.Labels["CPName"]; exists { found := false for _, aiProviderFromCP := range aiProviders { - if (aiProviderFromCP.Name == cpName) { + if aiProviderFromCP.Name == cpName { found = true break } @@ -186,11 +186,10 @@ func createAIProvider(aiProvider *eventhubTypes.AIProvider) dpv1alpha3.AIProvide conf, _ := config.ReadConfigs() sha1ValueofAIProviderName := GetSha1Value(aiProvider.Name) sha1ValueOfOrganization := GetSha1Value(aiProvider.Organization) - sha1ValueforCRName := GetSha1Value(aiProvider.Name + "-" + aiProvider.APIVersion + "-" + aiProvider.Organization) labelMap := map[string]string{"name": sha1ValueofAIProviderName, "organization": sha1ValueOfOrganization, "InitiateFrom": "CP", - "CPName" : aiProvider.Name, + "CPName": aiProvider.Name, } var modelInputSource string var modelAttributeIdentifier string @@ -225,7 +224,7 @@ func createAIProvider(aiProvider *eventhubTypes.AIProvider) dpv1alpha3.AIProvide crAIProvider := dpv1alpha3.AIProvider{ ObjectMeta: metav1.ObjectMeta{ - Name: sha1ValueforCRName, + Name: aiProvider.ID, Namespace: conf.DataPlane.Namespace, Labels: labelMap, }, diff --git a/apim-apk-agent/internal/utils/apis_fetcher.go b/apim-apk-agent/internal/utils/apis_fetcher.go index 933d5ba2..312e080b 100644 --- a/apim-apk-agent/internal/utils/apis_fetcher.go +++ b/apim-apk-agent/internal/utils/apis_fetcher.go @@ -24,9 +24,9 @@ package synchronizer import ( - "fmt" "crypto/sha1" "encoding/hex" + "fmt" "archive/zip" "bytes" @@ -39,8 +39,8 @@ import ( transformer "github.com/wso2/product-apim-tooling/apim-apk-agent/pkg/transformer" "sigs.k8s.io/controller-runtime/pkg/client" - mapperUtil "github.com/wso2/product-apim-tooling/apim-apk-agent/internal/mapper" k8sclientUtil "github.com/wso2/product-apim-tooling/apim-apk-agent/internal/k8sClient" + mapperUtil "github.com/wso2/product-apim-tooling/apim-apk-agent/internal/mapper" ) func init() { @@ -111,7 +111,7 @@ func FetchAPIsOnEvent(conf *config.Config, apiUUID *string, k8sClient client.Cli return nil, err } - apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, api, prodAIRL, sandAIRL, apkErr := transformer.GenerateAPKConf(artifact.APIJson, artifact.CertArtifact, apiDeployment.OrganizationID) + apkConf, apiUUID, revisionID, configuredRateLimitPoliciesMap, endpointSecurityData, api, prodAIRL, sandAIRL, apkErr := transformer.GenerateAPKConf(artifact.APIJson, artifact.CertArtifact, apiDeployment.OrganizationID) if prodAIRL == nil { // Try to delete production AI ratelimit for this api k8sclientUtil.DeleteAIRatelimitPolicy(generateSHA1HexHash(api.Name, api.Version, "production"), k8sClient) diff --git a/apim-apk-agent/pkg/eventhub/types/types.go b/apim-apk-agent/pkg/eventhub/types/types.go index 39c31f8b..feea63c6 100644 --- a/apim-apk-agent/pkg/eventhub/types/types.go +++ b/apim-apk-agent/pkg/eventhub/types/types.go @@ -134,11 +134,12 @@ type SubscriptionPolicyList struct { // AIProviderList for struct list of AIProvider type AIProviderList struct { - APIs []AIProvider `json:"apis"` + AIProviders []AIProvider `json:"llmProviders"` } // AIProvider for struct AIProvider type AIProvider struct { + ID string `json:"id"` Name string `json:"name"` APIVersion string `json:"apiVersion"` Organization string `json:"organization"` diff --git a/apim-apk-agent/pkg/managementserver/event_holder.go b/apim-apk-agent/pkg/managementserver/event_holder.go index 8f85e59c..1db1ae31 100644 --- a/apim-apk-agent/pkg/managementserver/event_holder.go +++ b/apim-apk-agent/pkg/managementserver/event_holder.go @@ -44,17 +44,17 @@ func init() { // AddAIProvider adds an AI provider to the aiProviderMap func AddAIProvider(aiProvider eventHub.AIProvider) { - aiProviderMap[aiProvider.Name+aiProvider.APIVersion+aiProvider.Organization] = aiProvider + aiProviderMap[aiProvider.ID] = aiProvider } // GetAIProvider returns an AI provider from the aiProviderMap -func GetAIProvider(name string, apiVersion string, organization string) eventHub.AIProvider { - return aiProviderMap[name+apiVersion+organization] +func GetAIProvider(id string) eventHub.AIProvider { + return aiProviderMap[id] } // DeleteAIProvider deletes an AI provider from the aiProviderMap -func DeleteAIProvider(name string, apiVersion string, organization string) { - delete(aiProviderMap, name+apiVersion+organization) +func DeleteAIProvider(id string) { + delete(aiProviderMap, id) } // GetAllAIProviders returns all the AI providers in the aiProviderMap @@ -101,7 +101,7 @@ func DeleteRateLimitPolicy(name string, tenantDomain string) { } // DeleteSubscriptionPolicy deletes a subscription policy from the subscriptionPolicyMap -func DeleteSubscriptionPolicy(name string, tenantDomain string){ +func DeleteSubscriptionPolicy(name string, tenantDomain string) { delete(subscriptionPolicyMap, name+tenantDomain) } diff --git a/apim-apk-agent/pkg/managementserver/rest_server.go b/apim-apk-agent/pkg/managementserver/rest_server.go index 1c349e4f..ef3c8bcc 100644 --- a/apim-apk-agent/pkg/managementserver/rest_server.go +++ b/apim-apk-agent/pkg/managementserver/rest_server.go @@ -160,17 +160,18 @@ func createAPIYaml(apiCPEvent *APICPEvent) (string, string) { if apiCPEvent.API.APIType == "GraphQL" { apiType = "GRAPHQL" } - apiSubType := "DEFAULT" - if apiCPEvent.API.APISubType != "" { - apiSubType = apiCPEvent.API.APISubType - } - var aiConfiguration = make(map[string]interface{}) - if apiCPEvent.API.AIConfiguration.LLMProviderName != "" || apiCPEvent.API.AIConfiguration.LLMProviderAPIVersion != "" { + + var subTypeConfiguration = make(map[string]interface{}) + if apiCPEvent.API.APISubType != "" || apiCPEvent.API.AIConfiguration.LLMProviderID != "" || + apiCPEvent.API.AIConfiguration.LLMProviderName != "" || + apiCPEvent.API.AIConfiguration.LLMProviderAPIVersion != "" { logger.LoggerMgtServer.Debugf("AI Configuration: %+v", apiCPEvent.API.AIConfiguration) - aiConfiguration["llmProviderName"] = apiCPEvent.API.AIConfiguration.LLMProviderName - aiConfiguration["llmProviderApiVersion"] = apiCPEvent.API.AIConfiguration.LLMProviderAPIVersion + subTypeConfiguration["subtype"] = apiCPEvent.API.APISubType + subTypeConfiguration["_configuration"] = "{\"llmProviderId\":\"" + + apiCPEvent.API.AIConfiguration.LLMProviderID + "\"}" } - logger.LoggerMgtServer.Debugf("Recieved AI Configuration: %+v", aiConfiguration) + logger.LoggerMgtServer.Debugf("Subtype Configuration: %+v", subTypeConfiguration) + data := map[string]interface{}{ "type": "api", "version": "v4.4.0", @@ -189,7 +190,6 @@ func createAPIYaml(apiCPEvent *APICPEvent) (string, string) { "enableSchemaValidation": false, "enableSubscriberVerification": false, "type": apiType, - "subType": apiSubType, "transport": []string{"http", "https"}, "endpointConfig": map[string]interface{}{ "endpoint_type": apiCPEvent.API.EndpointProtocol, @@ -211,8 +211,8 @@ func createAPIYaml(apiCPEvent *APICPEvent) (string, string) { "scopes": scopes, }, } - if len(aiConfiguration) > 0 { - data["data"].(map[string]interface{})["aiConfiguration"] = aiConfiguration + if len(subTypeConfiguration) > 0 { + data["data"].(map[string]interface{})["subtypeConfiguration"] = subTypeConfiguration } // TODO when we start to process sandbox we need to have this if condition. For now we remove sandbox endpoint always. // if apiCPEvent.API.SandEndpoint == "" { diff --git a/apim-apk-agent/pkg/managementserver/types.go b/apim-apk-agent/pkg/managementserver/types.go index c1ea0588..538026dd 100644 --- a/apim-apk-agent/pkg/managementserver/types.go +++ b/apim-apk-agent/pkg/managementserver/types.go @@ -163,6 +163,7 @@ type AIRL struct { // AIConfiguration holds the AI configuration type AIConfiguration struct { + LLMProviderID string `json:"llmProviderID"` LLMProviderName string `json:"llmProviderName"` LLMProviderAPIVersion string `json:"llmProviderApiVersion"` } diff --git a/apim-apk-agent/pkg/messaging/event_types.go b/apim-apk-agent/pkg/messaging/event_types.go index 1d3a8d00..a3cd8509 100644 --- a/apim-apk-agent/pkg/messaging/event_types.go +++ b/apim-apk-agent/pkg/messaging/event_types.go @@ -179,6 +179,7 @@ type PolicyInfo struct { type AIProviderEvent struct { Name string `json:"name"` APIVersion string `json:"apiVersion"` + ID string `json:"id"` Event } diff --git a/apim-apk-agent/pkg/transformer/api_model.go b/apim-apk-agent/pkg/transformer/api_model.go index 0357582a..4531b187 100644 --- a/apim-apk-agent/pkg/transformer/api_model.go +++ b/apim-apk-agent/pkg/transformer/api_model.go @@ -170,22 +170,27 @@ type APIMApi struct { SecuritySchemes []string `json:"securityScheme"` AdditionalProperties []AdditionalProperties `yaml:"additionalProperties"` // AdditionalPropertiesMap []AdditionalPropertiesMap `yaml:"additionalPropertiesMap"` - CORSConfiguration CORSConfiguration `yaml:"corsConfiguration"` - EndpointConfig EndpointConfig `yaml:"endpointConfig"` - Operations []APIMOperation `yaml:"operations"` - OrganizationID string `yaml:"organizationId"` - RevisionID uint32 `yaml:"revisionId"` - RevisionedAPIID string `yaml:"revisionedApiId"` - APIThrottlingPolicy string `yaml:"apiThrottlingPolicy"` - APIPolicies APIMOperationPolicies `yaml:"apiPolicies"` - AIConfiguration APIMAIConfiguration `yaml:"aiConfiguration"` - MaxTps *MaxTps `yaml:"maxTps"` + CORSConfiguration CORSConfiguration `yaml:"corsConfiguration"` + EndpointConfig EndpointConfig `yaml:"endpointConfig"` + Operations []APIMOperation `yaml:"operations"` + OrganizationID string `yaml:"organizationId"` + RevisionID uint32 `yaml:"revisionId"` + RevisionedAPIID string `yaml:"revisionedApiId"` + APIThrottlingPolicy string `yaml:"apiThrottlingPolicy"` + APIPolicies APIMOperationPolicies `yaml:"apiPolicies"` + SubtypeConfiguration SubtypeConfiguration `yaml:"subtypeConfiguration"` + MaxTps *MaxTps `yaml:"maxTps"` } -// APIMAIConfiguration holds the configuration details for AI providers -type APIMAIConfiguration struct { - LLMProviderName string `yaml:"llmProviderName"` - LLMProviderAPIVersion string `yaml:"llmProviderApiVersion"` +// SubtypeConfiguration holds the details for Subtypes +type SubtypeConfiguration struct { + Subtype string `json:"subtype"` + Configuration string `json:"_configuration"` +} + +// Configuration holds the configuration details for the subtype +type Configuration struct { + LLMProviderID string `json:"llmProviderId"` } // APIYaml is a wrapper struct for YAML representation of an API. diff --git a/apim-apk-agent/pkg/transformer/transformer.go b/apim-apk-agent/pkg/transformer/transformer.go index 0da38b2b..d05ca6f1 100644 --- a/apim-apk-agent/pkg/transformer/transformer.go +++ b/apim-apk-agent/pkg/transformer/transformer.go @@ -75,6 +75,7 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat } apiYamlData := apiYaml.Data + logger.LoggerTransformer.Debugf("apiYamlData: %v", apiYamlData) apk.Name = apiYamlData.Name apk.Context = apiYamlData.Context @@ -84,11 +85,18 @@ func GenerateAPKConf(APIJson string, certArtifact CertificateArtifact, organizat apk.DefinitionPath = "/definition" apk.SubscriptionValidation = true - if apiYamlData.AIConfiguration.LLMProviderName != "" && apiYamlData.AIConfiguration.LLMProviderAPIVersion != "" { - sha1ValueforCRName := GetSha1Value(apiYamlData.AIConfiguration.LLMProviderName + "-" + apiYamlData.AIConfiguration.LLMProviderAPIVersion + "-" + organizationID) + if apiYamlData.SubtypeConfiguration.Subtype == "AIAPI" && apiYamlData.SubtypeConfiguration.Configuration != "" { + // Unmarshal the _configuration field into the Configuration struct + var config Configuration + err := json.Unmarshal([]byte(apiYamlData.SubtypeConfiguration.Configuration), &config) + if err != nil { + fmt.Println("Error unmarshalling _configuration:", err) + return "", "null", 0, nil, EndpointSecurityConfig{}, nil, nil, nil, err + } + sha1ValueforCRName := config.LLMProviderID apk.AIProvider = &AIProvider{ Name: sha1ValueforCRName, - APIVersion: apiYamlData.AIConfiguration.LLMProviderAPIVersion, + APIVersion: "1", } }