Creating Plugins
Use this guide to author your own Omnata plugin.
In the previous sections, we walked through some example plugins to demonstrate how they work.
Here, we'll cover the development tools that Omnata provides to help simplify the task and make you productive.
In this example, we'll build a plugin which supports outbound syncing. Once you're familiar with this, the inbound functionality works similarly.
Summary
Ultimately, creating a plugin is an simple as uploading a python class with a product logo, and optionally some other python files or libraries. These are packaged and distributed as Snowflake Native Applications.
Omnata provides a development kit which helps by providing:
a plugin template as a starting point
a convenient command-line interface (CLI) which takes care of uploading and packaging your plugin code, and registering it with the Omnata Application
a "development session" concept, so that you can use an interactive session (e.g. a Jupyter notebook) to build the plugin functionality incrementally with a fast feedback loop, and verify that it's behaviour is correct
automated test case generation, including HTTP recording with secrets redacted
Once it's working correctly, we can migrate it all into the plugin class and tidy it up.
Step 1 - App Familiarisation
Read over your application's API documentation to gain familiarisation with it.
Questions to answer:
What use cases does the application have for receiving data from Snowflake? What are some examples?
What style of sync will it be? Event-style, where Snowflake rows are published once? Or record-style, where ongoing changes are replicated?
How do people typically call the API? Is there a python package we can leverage, or will we make http requests?
What information do we need to connect to the app? (e.g. API Key, OAuth Client Credentials)
What information do we need to collect to configure the sync behaviour? (e.g. names of objects/fields in the app, any other options exposed by the app's API)
What rate limits apply to the API?
Step 2 - Environment setup
To enable iterative prototyping of a plugin, we recommend using Visual Studio Code with the Python extension. This will help you manage your Python environment, and also includes Jupyter support which works nicely with our SDK.
Your Python plugin is able to use any of the Python packages available in the Snowflake Anaconda channel or on PyPi. By adding the package to the requirements.txt file, the Plugin uploader will either reference it on Anaconda or download it from PyPi.
We recommend using a Python environment manager like conda
to keep your plugin's environment controlled and minimal.
In order to develop plugins, you'll need to install the Omnata Plugin Devkit:
After this, all plugin development commands can be see by running:
Finally, the Omnata plugin devkit uses snowcli to authenticate to your Snowflake environment, which means you must follow its onboarding instructions first.
Step 3 - Create Plugin from template
We recommend you create a git repository and clone it first, so that you can properly manage changes to your code.
Run the following command to generate a plugin project into the current directory:
Start by editing the plugin's get_manifest
method, so that it returns a unique name and the real label for your app, as well as the sync directions and strategies you intend to support.
Then you can run the following command to upload your plugin to your Snowflake account:
After this command completes, unless you overrode the defaults:
Your code will have been uploaded to a stage named
OMNATA_PLUGIN_DEVELOPMENT.<Plugin ID>.PLUGIN_CODE
An application package named
<Plugin ID>_PLUGIN
will have been created, with a version namedDEVELOPMENT
Then you can create/update an instance of your plugin by running:
This will create an application from the above application package.
There's one final step which only needs to be done once, initially. Because applications have no visiblity of each other by default, we have to register the plugin application with the Omnata Sync Engine:
Now in the Omnata UI, you should see your plugin in the list.
Step 4 - Connect to your App
Edit the plugin's connection_form
method so that it returns the fields you want to present to the user. You can see the form whenever you create a new connection in the UI.
Also edit the plugin's connect
method to have it do a direct connection test, or return OAuth parameters to commence an OAuth flow.
Upload the plugin using sample code shown in the plugin_upload.ipynb
notebook. There will be warnings to say that the plugin is incomplete, that's ok.
Once it's uploaded, you can go into the Omnata UI, create a new Connection, then select your new app from the list. Ensure that the connection is created without errors.
Step 5 - Define Sync Parameters
Now modify the outbound_configuration_form
method to return the fields required for sync configuration. This usually involves at least one fixed value (like the Salesforce object name or the Slack channel name).
To map the Snowflake table data to something inside the app, you choose an appropriate type of Mapper
to return:
FormFieldMappingSelector
provides a visual column -> field mapper. Your Plugin provides a list of possible target fields in the app, and the user selects which Snowflake columns to map to them. This mapper is most common in record-based systems like Salesforce CRM.FormJinjaTemplate
provides a text-based template, which can have Snowflake column values interpolated. This mapper is most common in event-based systems like Slack.
Once you've defined the form, upload the plugin again to apply the changes. Then, create a Sync in Omnata. Just choose a manual schedule so that it never runs automatically.
Step 6 - Sample data
Now, create a table with sample data. This will be used to test the plugin.
Step 7 - Build via a development session
Use the example code provided in the plugin_development.ipynb
notebook to create a development session.
A development session simplifies the hardest part of plugin development; writing the code that talks to the App. It does this by connecting to your Snowflake account and retrieving what's normally provided to the sync_outbound
method during a scheduled sync.
Instead of having to continually upload new versions of your plugin and re-run syncs until the sync_outbound
method works perfectly start to finish, you can simply use the parameters
and sync_request
objects in your Jupyter notebook to gradually construct the code.
As part of this, you'll capture the outcome of the API operation back into a DataFrame to return to Omnata. This DataFrame contains the columns:
IDENTIFIER - Provided in the original apply request
SUCCESS - A boolean flag to indicate true/false
APP_IDENTIFIER - (Optional) an identifier for this record on the app side
RESULT - A JSON object containing any useful/relevant information about the record or specific errors encountered. Error messages returned under the "error" property will be displayed in the UI for troubleshooting.
The response DataFrame can be validated with:
This will return a Success or Failure message back to the terminal
Once you get a success message, you can complete the scenario:
Step 8 - Generate test cases automatically
Once your Jupyter notebook code is working, and you can see data appearing in your app correctly, you should move the code from your Jupyter notebook into the apply_records
method of your plugin.
Once this is done you can re-run your development session start to finish going directly against your completed plugin class, as shown in plugin_test.ipynb
.
If it all works as expected, you can generate a behave test:
This will output a feature file, as well as a VCR.py cassette containing your HTTP requests and responses, which is referenced in the behave test.
The test case generator assumes that everything worked correctly, but you need to confirm this yourself!
In other words, the test case is useful for ensuring you don't inadvertently break this scenario in future, but it gives no guarantees of original correctness.
It also relies on recordings of the app responses, which assumes the app's behaviour will remain consistent.
This behave test can be ran at any time, without needing to connect to Snowflake or your App.
You can continue to record and generate new test cases to cover other sync scenarios and account for different behaviours in the app.
Step 9 - Implement inbound syncing
Similar to outbound, implement the inbound_configuration_form
and sync_inbound
functions to enable inbound syncing.
Step 10 - Complete your plugin
With the plugin fully working locally, you can upload it again.
Now Omnata can start syncing data for you by scheduling the sync you created.
Last updated