| name | openflow-gdrive-setup |
| description | Interactive setup for OpenFlow Google Drive demo. Prompts for missing config, creates infrastructure, writes to manifest. |
| parent_skill | openflow-gdrive-demo |
OpenFlow Google Drive — Setup
Interactive setup that prompts for all missing config and provisions infrastructure.
When to Load
Parent SKILL.md routes here on: "setup", "provision", "configure", "first time", "initialize"
Prerequisites
- Snowflake connection configured in
manifest.toml [snowflake].connection
ACCOUNTADMIN or equivalent role for creating EAI/network rules
Workflow
Step 1: Resolve Config (manifest → env → prompt)
eval $(python3 -c "
import tomllib, os
m = tomllib.load(open('.sfutils/manifest.toml', 'rb'))
o = m.get('openflow', {})
rt = o.get('runtime', {})
src = o.get('source', {}).get('gdrive', {})
s = m.get('snowflake', {})
print(f'CONNECTION={s.get(\"connection\", os.environ.get(\"SNOWFLAKE_DEFAULT_CONNECTION_NAME\", \"\"))}')
print(f'DATABASE={o.get(\"database\", os.environ.get(\"OPENFLOW_DATABASE\", \"\"))}')
print(f'SCHEMA={o.get(\"schema\", os.environ.get(\"OPENFLOW_SCHEMA\", \"\"))}')
print(f'ROLE={o.get(\"role\", os.environ.get(\"OPENFLOW_ROLE\", \"\"))}')
print(f'WAREHOUSE={o.get(\"warehouse\", os.environ.get(\"OPENFLOW_WAREHOUSE\", \"\"))}')
print(f'RUNTIME={rt.get(\"name\", os.environ.get(\"OPENFLOW_RUNTIME\", \"\"))}')
print(f'EAI={o.get(\"eai\", os.environ.get(\"OPENFLOW_EAI\", \"\"))}')
print(f'DRIVE_ID={src.get(\"drive_id\", os.environ.get(\"GDRIVE_DRIVE_ID\", \"\"))}')
print(f'FOLDER_NAME={src.get(\"folder_name\", os.environ.get(\"GDRIVE_FOLDER_NAME\", \"\"))}')
print(f'GCP_CRED={src.get(\"credential_path\", os.environ.get(\"GCP_CREDENTIAL_PATH\", \"~/.snowflake/cortex/secrets/gcp-service-account.json\"))}')
")
For each empty value, use ask_user_question showing the env var value (if set) as the default option.
⚠️ MANDATORY STOP: Present all resolved values and wait for user confirmation before proceeding.
Step 2: Verify Connection
snow connection test -c $CONNECTION
If fails: Stop — user must fix their Snowflake connection.
Step 3: Verify Role and Warehouse
snow sql -q "SHOW ROLES LIKE '$ROLE'" -c $CONNECTION --format json
snow sql -q "SHOW WAREHOUSES LIKE '$WAREHOUSE'" -c $CONNECTION --format json
If role/warehouse missing: Inform user and stop.
Step 4: Verify Runtime and Profile
The bootstrap skill already ran $openflow setup. Read runtime metadata from its cache:
cat ~/.snowflake/cortex/memory/openflow_infrastructure_${CONNECTION}.json | jq '{
runtime: .deployments[0].runtimes[0].runtime_name,
role: .deployments[0].runtimes[0].execute_as_role,
profile: .deployments[0].runtimes[0].nipyapi_profile
}'
If cache is empty or missing, invoke $openflow with "setup" intent to re-discover.
Step 5: Verify or Create EAI
Check if EAI exists in the manifest ([openflow].eai). If set, verify it's enabled:
snow sql -q "DESCRIBE INTEGRATION $EAI" -c $CONNECTION --format json
If EAI exists and enabled: Proceed to Step 6.
If EAI missing: STOP. Invoke $sfutils:network-rule with:
- Type: EGRESS
- Hosts:
googleapis.com, www.googleapis.com, oauth2.googleapis.com, accounts.google.com
- Rule name:
{PREFIX}_EGRESS_RULE (or EGRESS_RULE if no prefix)
- EAI name:
{PREFIX}_OPENFLOW_EAI (or OPENFLOW_EAI if no prefix)
- Database/Schema:
OPENFLOW_DEMOS.NETWORKS
- Grant USAGE to:
OPENFLOW_DEMOS_ROLE
- Manifest path:
.sfutils/manifest.toml
Do NOT write SQL for EAI/NW creation. Wait for the skill to confirm.
Then ask user to attach EAI to runtime via Snowsight.
Step 6: Write Config to Manifest
The $sfutils:network-rule and $sfutils:programmatic-access-token skills write their own sections. Write remaining config values to .sfutils/manifest.toml:
[openflow].database
[openflow].schema
[openflow].role
[openflow].warehouse
[openflow].connector_flow = "unstructured-google-drive-cdc-no-dwd"
[openflow.source.gdrive].drive_id
[openflow.source.gdrive].folder_name
Step 7: Verify PAT
Check if [pat.openflow-runner] exists and is COMPLETE in manifest.
| Result | Action |
|---|
| COMPLETE | Setup done -- PAT exists |
| MISSING | STOP. Invoke $sfutils:programmatic-access-token (see bootstrap Step 8 for params) |
Do NOT write PAT SQL manually.
Stopping Points
- ✋ After Step 1: user must confirm config values
- ✋ If runtime not found: user must create via $openflow or Snowsight
- ✋ If EAI missing: user must create
Output
Setup complete!
Connection: $CONNECTION
Database: $DATABASE.$SCHEMA
Runtime: $RUNTIME (ACTIVE)
Profile: $PROFILE
EAI: $EAI
PAT: $SA_USER (COMPLETE)
Manifest: .sfutils/manifest.toml updated