# Openflow Gdrive Demo

> Deploy, clean up, or manage the Google Drive CDC connector (no DWD) on OpenFlow. Use when: openflow demo, gdrive connector, deploy google drive connector, cleanup, reset demo, setup openflow, deploy connector, start connector, configure openflow.

- Skill: `snowflake-labs/openflow-gdrive-demo` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add snowflake-labs/openflow-gdrive-demo`
- Raw SKILL.md: https://api.skillmd.com/api/skills/snowflake-labs/openflow-gdrive-demo/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: snowflake-labs (https://skillmd.com/u/snowflake-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/snowflake-labs/openflow-gdrive-demo

---


# OpenFlow Google Drive Connector Demo

Google Drive to Snowflake (Cortex Search) via OpenFlow. No domain-wide delegation required.

## Prerequisites (Gate Checks)

Run these checks before routing to any sub-skill. If any gate fails, STOP and guide the user to fix it.

### Gate 0: Environment Bootstrap

**MANDATORY: Execute every step in `../bootstrap/SKILL.md` before proceeding.** Do NOT skip this gate. Do NOT proceed to Gate 1 until bootstrap is fully complete.

The bootstrap:
1. Copies scaffold files (`.env.example`, `.mise.toml`, `sql/`) to `$PWD`
2. Resolves and verifies Snowflake connection
3. Creates `.env` (ask for `OPENFLOW_GDRIVE_ID` and `OPENFLOW_GDRIVE_FOLDER_NAME`)
4. Creates `.sfutils/manifest.toml`
5. Runs `mise install` and `mise run setup`
6. Runs `mise run sf-setup` (creates roles, database, warehouse)
7. Creates PAT via `$sfutils:programmatic-access-token`
8. Creates EAI via `$sfutils:network-rule`
9. Discovers runtime and creates nipyapi profile via `$openflow` (uses PAT from Step 7)

If any step fails, STOP and help the user fix it. Do NOT skip steps.

### Gate 1: Google Shared Drive

**Important:** The connector works with **Google Shared Drives only** -- regular Drive folders will silently fail (no files discovered).

Ask the user via `ask_user_question`:
- "Shared Drive is ready with documents" -- proceed
- "I need to set this up" -- guide them:
  1. Create a Google Shared Drive (not a regular folder)
  2. Upload sample documents (run `mise run sample-data` for test files)
  3. Grant the GCP service account access to the Shared Drive
  4. Come back and confirm

### Gate 2: GCP Service Account Credential

```bash
test -f "$(eval echo ${GCP_CREDENTIAL_PATH:-~/.snowflake/cortex/secrets/gcp-service-account.json})" && echo "OK" || echo "MISSING"
```

**If MISSING:** STOP. Ask user to place the GCP service account JSON key at the expected path.

## Config Resolution

Load `references/config-resolution.md` for the resolution snippet, manifest schema, and naming conventions.

Resolution order: manifest.toml > environment variables > prompt user.

## Intent Detection

| Intent | Triggers | Action |
|--------|----------|--------|
| SETUP | "setup", "provision", "configure", "first time", "initialize" | **Load** `setup/SKILL.md` |
| DEPLOY | "deploy", "run", "start", "add connector" | **Load** `deploy/SKILL.md` |
| CLEANUP | "cleanup", "clean", "reset", "tear down", "remove" | **Load** `cleanup/SKILL.md` |
| UPDATE_IP | "moved networks", "new network", "conference wifi", "hotel wifi", "IP changed", "update IP", "blocked", "can't connect" | **Load** `update-ip/SKILL.md` |

If ambiguous, ask the user which mode.

## Forbidden Actions

- **Do not delete `.sfutils/`** -- the manifest tracks all provisioned resources across runs; losing it means manual cleanup
- **Do not write PAT or network rule SQL directly** -- always invoke `$sfutils:programmatic-access-token` or `$sfutils:network-rule` which handle keyring, manifest, and IDD compliance
- **Do not hardcode config values** -- read from manifest so replay and multi-user flows work
- **Do not proceed with empty required fields** -- empty values cause silent failures in NiFi parameter contexts
- **Do not silently use env-sourced values** -- env vars may be stale from a previous session; always confirm
- **Do not guess warehouse or resource names** -- wrong names cause permission errors that are hard to diagnose

## Stopping Points

- After Gate checks: if any gate fails
- Each sub-skill has its own stopping points (see individual SKILL.md files)

## Troubleshooting

| Issue | Cause | Fix |
|-------|-------|-----|
| nipyapi 403 "Authorization denied" | PAT role restriction doesn't match OpenFlow Admin role | Recreate PAT with `ROLE_RESTRICTION = OPENFLOW_ADMIN` (the role from setup.sql with NiFi canvas access) |
| nipyapi 401 "Integration does not exist" | SA_ROLE lacks runtime's `execute_as_role` | `GRANT ROLE {execute_as_role} TO ROLE {SA_ROLE}` |
| nipyapi 401 | PAT expired | Invoke `$sfutils:programmatic-access-token` to rotate |
| nipyapi 401 after rotation | IP changed | **Load** `update-ip/SKILL.md` |
| nipyapi hits localhost:9443 | Profile not created or wrong name | Re-run nipyapi profile creation |
| Token extraction fails | `show-pat` can't find keyring entry | `pat verify --user {SA_USER}` |
| Schema creation fails | Missing permissions | Check role grants, use admin_role |
| No data after 2 min | EAI not attached | Verify EAI on runtime via DESCRIBE |
| No data after 2 min | Wrong Drive ID | Must be a Shared Drive ID, not folder ID |
| No data after 2 min | Schema ownership | Verify role owns schema |
| `pat check-setup --run-setup` fails | Template rendering error with newer snow CLI | Create DB/schemas manually: `CREATE DATABASE IF NOT EXISTS {DB}; CREATE SCHEMA IF NOT EXISTS {DB}.NETWORKS; CREATE SCHEMA IF NOT EXISTS {DB}.POLICIES;` |
| `upload_asset` fails for GCP credential | Sensitive parameter in inherited context cannot be overridden | Use `configure_inherited_params` instead of `upload_asset` for sensitive params |
| mise `.env` parse error | Unquoted value with spaces | Always quote values in `.env`: `OPENFLOW_GDRIVE_FOLDER_NAME="My Folder"` |

## Output

Depending on intent:
- **DEPLOY**: Running connector with data flowing into Cortex Search
- **SETUP**: Infrastructure provisioned, manifest populated
- **CLEANUP**: Schema dropped, flow deleted, manifest reset
- **UPDATE_IP**: Network rule updated, PAT rotated, connectivity restored

