Skip to content

AIS-1630 - Create Datasource API - #1294

Open
prachikurade1 wants to merge 4 commits into
IBM:mainfrom
prachikurade1:AIS_1630_updated
Open

AIS-1630 - Create Datasource API#1294
prachikurade1 wants to merge 4 commits into
IBM:mainfrom
prachikurade1:AIS_1630_updated

Conversation

@prachikurade1

Copy link
Copy Markdown
Contributor
  • Create Datasource API:
  • Validates the request body - datasource name, provider id, metadata
  • Metadata is validated as per the schema.json set for the provider
  • Validation for duplicate datasource name
  • Test the connection - return an error if it fails - network error, auth error or access error
  • Insert if all the above passes and return the id of the datasource created.

Signed-off-by: Prachi Kurade <prachi.kurade1@ibm.com>
Signed-off-by: Prachi Kurade <prachi.kurade1@ibm.com>
Signed-off-by: Prachi Kurade <prachi.kurade1@ibm.com>
ProviderID string `json:"provider_id" binding:"required"`
// Metadata holds the provider-specific configuration. Sensitive fields (format: "password"
// in the JSON schema) are encrypted at rest; all other fields are stored in plain text.
Metadata map[string]any `json:"metadata" binding:"required"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets make this params similar to CreateApplication

Comment on lines +6 to +7
Name string `json:"name" binding:"required,min=3,max=100"`
// ProviderID identifies the provider implementation (e.g. "object_storage", "file_system").

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also do other validations like supporting chars, case insensitive validations etc

Comment on lines +20 to +23
// providerObjectStorage is the provider ID for S3-compatible object storage connectors.
providerObjectStorage = "object_storage"
// providerFileSystem is the provider ID for SSH/SFTP file system connectors.
providerFileSystem = "file_system"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us move this to constant package as it might be used in multiple places

Comment on lines +75 to +78
existing, err := s.connectorRepo.GetByName(ctx, req.Name)
if err != nil {
return nil, fmt.Errorf("failed to check for existing connector: %w", err)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above let us make this case insensitive

Comment on lines +25 to +30
// SensitiveFields returns the credential fields that must be encrypted at rest.
func (t *fileSystemTester) SensitiveFields() map[string]bool {
return map[string]bool{
"private_key": true,
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us not hardcode this. Let it be generic and be computed from values.schema.json whether its sensitive or not

Comment on lines +82 to +87
if !isAWS {
// IBM COS, MinIO, and other S3-compatible stores: supply the custom
// endpoint and enable path-style addressing.
o.BaseEndpoint = aws.String(endpointURL)
o.UsePathStyle = true
}

@mayuka-c mayuka-c Aug 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us make this inverse,
For AWS do the if check as it is specific and rest flow can be generic

Comment on lines +13 to +15
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/smithy-go"

@mayuka-c mayuka-c Aug 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there not a common package which could provide common s3 methods?
or else we need to use aws-sdk is it?

@prachikurade1 prachikurade1 Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package is compatible with s3 based storage systems and is the most recommended one.

Comment on lines +163 to +164
func regionFromEndpoint(endpointURL string) string {
cosAliases := map[string]string{"us": "us-south", "eu": "eu-de", "ap": "jp-tok"}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again here is there not a generic way?
What if a region is removed/modified/deleted?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I see default as "us-east-1". Was this discussed with the design team?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the way even Digitize Service has implemented. A mapping needs to be maintained and updated if regions are changed.
Digitize mapping -
https://github.com/IBM/project-ai-services/blob/main/services/digitize/connectors/scanners/config.py#L48

"us-east-1" is the standard default region used for AWS. Checked Digitize implementation as well and they have done the same.
Default region - https://github.com/IBM/project-ai-services/blob/main/services/digitize/connectors/scanners/config.py#L36

Comment on lines +20 to +21
encryptionKey := os.Getenv("DB_ENCRYPTION_KEY")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us have constant for DB_ENCRYPTION_KEY in constants pkg

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there should be a check for an empty string. I see you are checking during runtime, which isn't ideal. It should fail fast.

secretKey, _ := params["secret_access_key"].(string)
prefix, _ := params["prefix"].(string)

isAWS := strings.Contains(endpointURL, awsEndpointSuffix)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if user wants to use GCS or ABS, will this work?
Do we need to again check and add specific logics?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For GCS it will work, will need minor tweaks to handle error codes for access/auth errors.
For Azure , it will not work because Azure Blob storage is not s3 compatible.

if sensitiveKeys[k] {
plaintext, ok := v.(string)
if !ok {
return nil, fmt.Errorf("sensitive field %q must be a string", k)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be StatusBadRequest instead of server error (500).

Signed-off-by: Prachi Kurade <prachi.kurade1@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants