Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GMT-109: Snowflake writer supporting GCP #3

Merged
merged 30 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d3457d9
Remove all foreign-key stuff (as it is deprecated)
romantmb Mar 1, 2024
c848e00
Do refactor of SnowflakeWriteAdapter.php (wip)
romantmb Mar 6, 2024
7c9ced6
Fix snowflake driver spec
romantmb Mar 6, 2024
a91b348
Update SnowflakeWriteAdapter (first working draft)
romantmb Mar 6, 2024
5bff8a5
Filter ignored table fields (aka ItemConfig's)
romantmb Mar 6, 2024
2c3c52b
Remove upload of test .csv files into buckets, replace with copying i…
romantmb Mar 6, 2024
c065a7b
Remove foreign-key func. tests (as multiple tables nor foreign keys a…
romantmb Mar 7, 2024
d2561ed
- fix copying of .csv in tests
romantmb Mar 7, 2024
a693e5d
Update tests (vol. 2)
romantmb Mar 8, 2024
cc99437
Replace empty strings and 'NULL's with null in COPY INTO query
romantmb Mar 8, 2024
9470717
Update tests (vol. 3, all good)
romantmb Mar 8, 2024
f28f36a
Cleanup unused write strategy
romantmb Mar 8, 2024
2de154b
Set stopOnFailure="false" in phpunit.xml.dist
romantmb Mar 11, 2024
ff25f1e
Fix workflows/push.yml (dockerhub user)
romantmb Mar 11, 2024
131878f
Update workflows/push.yml (app image & dev portal ID)
romantmb Mar 11, 2024
d6efd78
Fix image name in docker-compose.yml
romantmb Mar 11, 2024
6443d52
Revert replacing of empty strings and 'NULL's with null in COPY INTO …
romantmb Mar 11, 2024
027c607
Delete obsolete tests of nullable & default date types
romantmb Mar 11, 2024
901ddfd
Copy test .csv files into each func. test, remove obsolete test of nu…
romantmb Mar 11, 2024
252c524
Delete 'tests-prepare-data' script from composer.json
romantmb Mar 11, 2024
4781179
Add unit tests on PUT & COPY INTO queries
romantmb Mar 11, 2024
c02c07e
- remove STORAGE_API_TOKEN
romantmb Mar 12, 2024
752f330
Improve push.yml, fix values
romantmb Mar 12, 2024
09d3cf7
Update example configuration in README.md
romantmb Mar 12, 2024
36ee2c5
Fix 'install dependencies' cmd in README.md
romantmb Mar 13, 2024
59378bd
Drop unnecessary SnowflakeItemConfig (same as ItemConfig)
romantmb Mar 13, 2024
460023d
Drop unnecessary SnowflakeExportConfig & SnowflakeTableNodesDecorator
romantmb Mar 13, 2024
d89c438
tests: validate config
ondrajodas Mar 13, 2024
f7ba548
Move generating of PUT & COPY INTO queries into SnowflakeQueryBuilder…
romantmb Mar 13, 2024
4c28d4e
Remove redundant query debug
romantmb Mar 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.dist
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
STORAGE_API_TOKEN=
KBC_URL=
KBC_RUNID=
DB_HOST=
Expand Down
85 changes: 52 additions & 33 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
name: 'GitHub Actions'
'on':
- push
on: [ push ]
concurrency: 'ci-${{ github.ref }}'
env:
APP_IMAGE: keboola-component
# Name of the image
APP_IMAGE: keboola/wr-db-snowflake-gcs # must be same in docker-compose.yml

# Developer portal login
KBC_DEVELOPERPORTAL_VENDOR: keboola
KBC_DEVELOPERPORTAL_APP: keboola.db-writer-snowflake-gcs
KBC_DEVELOPERPORTAL_APP: keboola.wr-db-snowflake-gcs
KBC_DEVELOPERPORTAL_USERNAME: keboola+wr_db_snowflake_gcs
KBC_DEVELOPERPORTAL_PASSWORD: '${{ secrets.KBC_DEVELOPERPORTAL_PASSWORD }}'
DOCKERHUB_USER: ''
DOCKERHUB_TOKEN: '${{ secrets.DOCKERHUB_TOKEN }}'
KBC_STORAGE_TOKEN: '${{ secrets.KBC_STORAGE_TOKEN }}'
KBC_DEVELOPERPORTAL_PASSWORD: ${{ secrets.KBC_DEVELOPERPORTAL_PASSWORD }}

# DockerHub login
DOCKERHUB_USER: keboolabot
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

# Test DB
DB_HOST: kebooladev.snowflakecomputing.com
DB_PORT: 443
DB_USER: snowflake_writer_gcs
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
DB_DATABASE: snowflake_writer_gcs
DB_SCHEMA: snowflake_writer_gcs
DB_WAREHOUSE: snowflake_writer_gcs

# Testing staging storage projects
KBC_RUNID: 123456
KBC_STORAGE_TOKEN: ''
KBC_URL: 'https://connection.keboola.com/'
KBC_TEST_PROJECT_URL: ''
KBC_TEST_PROJECT_CONFIGS: ''
jobs:
Expand All @@ -21,7 +38,7 @@ jobs:
is_semantic_tag: '${{ steps.tag.outputs.is_semantic_tag }}'
steps:
- name: 'Check out the repo'
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: 'Print Docker version'
run: 'docker -v'
- name: 'Docker login'
Expand All @@ -40,31 +57,33 @@ jobs:
- name: 'Push image to ECR'
uses: keboola/action-push-to-ecr@master
with:
vendor: '${{ env.KBC_DEVELOPERPORTAL_VENDOR }}'
app_id: '${{ env.KBC_DEVELOPERPORTAL_APP }}'
username: '${{ env.KBC_DEVELOPERPORTAL_USERNAME }}'
password: '${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}'
tag: '${{ steps.tag.outputs.app_image_tag }}'
push_latest: '${{ steps.tag.outputs.is_semantic_tag }}'
source_image: '${{ env.APP_IMAGE}}'
vendor: ${{ env.KBC_DEVELOPERPORTAL_VENDOR }}
app_id: ${{ env.KBC_DEVELOPERPORTAL_APP }}
username: ${{ env.KBC_DEVELOPERPORTAL_USERNAME }}
password: ${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}
tag: ${{ steps.tag.outputs.app_image_tag }}
push_latest: ${{ steps.tag.outputs.is_semantic_tag }}
source_image: ${{ env.APP_IMAGE}}
tests:
needs: build
runs-on: ubuntu-latest
steps:
- name: 'Check out the repo'
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: 'Pull image from ECR'
uses: keboola/action-pull-from-ecr@master
with:
vendor: '${{ env.KBC_DEVELOPERPORTAL_VENDOR }}'
app_id: '${{ env.KBC_DEVELOPERPORTAL_APP }}'
username: '${{ env.KBC_DEVELOPERPORTAL_USERNAME }}'
password: '${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}'
tag: '${{ needs.build.outputs.app_image_tag }}'
target_image: '${{ env.APP_IMAGE}}'
vendor: ${{ env.KBC_DEVELOPERPORTAL_VENDOR }}
app_id: ${{ env.KBC_DEVELOPERPORTAL_APP }}
username: ${{ env.KBC_DEVELOPERPORTAL_USERNAME }}
password: ${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}
tag: ${{ needs.build.outputs.app_image_tag }}
target_image: ${{ env.APP_IMAGE}}
tag_as_latest: true
- name: 'Run tests'
run: 'docker run ${{env.APP_IMAGE}} composer ci'
run: |
docker-compose run --rm \
app composer ci
tests-in-kbc:
needs: build
runs-on: ubuntu-latest
Expand All @@ -73,10 +92,10 @@ jobs:
if: 'env.KBC_STORAGE_TOKEN && env.KBC_TEST_PROJECT_CONFIGS'
uses: keboola/action-run-configs-parallel@master
with:
token: '${{ env.KBC_STORAGE_TOKEN }}'
componentId: '${{ env.KBC_DEVELOPERPORTAL_APP }}'
tag: '${{ needs.build.outputs.app_image_tag }}'
configs: '${{ env.KBC_TEST_PROJECT_CONFIGS }}'
token: ${{ env.KBC_STORAGE_TOKEN }}
componentId: ${{ env.KBC_DEVELOPERPORTAL_APP }}
tag: ${{ needs.build.outputs.app_image_tag }}
configs: ${{ env.KBC_TEST_PROJECT_CONFIGS }}
deploy:
needs:
- build
Expand All @@ -88,8 +107,8 @@ jobs:
- name: 'Set tag in the Developer Portal'
uses: keboola/action-set-tag-developer-portal@master
with:
vendor: '${{ env.KBC_DEVELOPERPORTAL_VENDOR }}'
app_id: '${{ env.KBC_DEVELOPERPORTAL_APP }}'
username: '${{ env.KBC_DEVELOPERPORTAL_USERNAME }}'
password: '${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}'
tag: '${{ needs.build.outputs.app_image_tag }}'
vendor: ${{ env.KBC_DEVELOPERPORTAL_VENDOR }}
app_id: ${{ env.KBC_DEVELOPERPORTAL_APP }}
username: ${{ env.KBC_DEVELOPERPORTAL_USERNAME }}
password: ${{ env.KBC_DEVELOPERPORTAL_PASSWORD }}
tag: ${{ needs.build.outputs.app_image_tag }}
137 changes: 72 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,97 +9,104 @@ Writes data to Snowflake Database.
## Example configuration

```json
{
"db": {
"host": "HOST",
"port": "PORT",
"database": "DATABASE",
"user": "USERNAME",
"password": "PASSWORD",
"schema": "SCHEMA",
"warehouse": "WAREHOUSE",
"ssh": {
"enabled": true,
"keys": {
"private": "ENCRYPTED_PRIVATE_SSH_KEY",
"public": "PUBLIC_SSH_KEY"
},
"sshHost": "PROXY_HOSTNAME"
}
{
"parameters": {
"db": {
"host": "HOST",
"port": "PORT",
"database": "DATABASE",
"user": "USERNAME",
"password": "PASSWORD",
"schema": "SCHEMA",
"warehouse": "WAREHOUSE",
"ssh": {
"enabled": true,
"keys": {
"private": "ENCRYPTED_PRIVATE_SSH_KEY",
"public": "PUBLIC_SSH_KEY"
},
"sshHost": "PROXY_HOSTNAME"
}
},
"tableId": "simple",
"dbName": "simple",
"export": true,
"incremental": false,
"primaryKey": ["id"],
"items": [
{
"name": "id",
"dbName": "id",
"type": "int",
"size": null,
"nullable": null,
"default": null
},
{
"name": "name",
"dbName": "name",
"type": "varchar",
"size": 255,
"nullable": null,
"default": null
},
{
"name": "glasses",
"dbName": "glasses",
"type": "varchar",
"size": 255,
"nullable": null,
"default": null
}
]
},
"storage": {
"input": {
"tables": [
{
"tableId": "simple",
"dbName": "simple",
"export": true,
"incremental": true,
"primaryKey": ["id"],
"items": [
{
"name": "id",
"dbName": "id",
"type": "int",
"size": null,
"nullable": null,
"default": null
},
{
"name": "name",
"dbName": "name",
"type": "nvarchar",
"size": 255,
"nullable": null,
"default": null
},
{
"name": "glasses",
"dbName": "glasses",
"type": "nvarchar",
"size": 255,
"nullable": null,
"default": null
}
]
"source": "simple",
"destination": "simple.csv"
}
]
}
}
}
```

## Development

Required snowflake resource for writer:
```sql
CREATE DATABASE "snowflake_writer";
USE DATABASE "snowflake_writer";
CREATE TRANSIENT SCHEMA "snowflake_writer";
CREATE WAREHOUSE "snowflake_writer" WITH
CREATE DATABASE "snowflake_writer_gcs";
USE DATABASE "snowflake_writer_gcs";
CREATE TRANSIENT SCHEMA "snowflake_writer_gcs";
CREATE WAREHOUSE "snowflake_writer_gcs" WITH
WAREHOUSE_SIZE = 'XSMALL'
WAREHOUSE_TYPE = 'STANDARD'
AUTO_SUSPEND = 900
AUTO_RESUME = TRUE;
CREATE ROLE "snowflake_writer";
GRANT USAGE ON WAREHOUSE "snowflake_writer" TO ROLE "snowflake_writer";
GRANT USAGE ON DATABASE "snowflake_writer" TO ROLE "snowflake_writer";
GRANT ALL ON SCHEMA "snowflake_writer" TO ROLE "snowflake_writer";
GRANT ALL ON FUTURE TABLES IN SCHEMA "snowflake_writer" TO ROLE "snowflake_writer";
GRANT ALL ON FUTURE VIEWS IN SCHEMA "snowflake_writer" TO ROLE "snowflake_writer";
CREATE USER "snowflake_writer"
CREATE ROLE "snowflake_writer_gcs";
GRANT USAGE ON WAREHOUSE "snowflake_writer_gcs" TO ROLE "snowflake_writer_gcs";
GRANT USAGE ON DATABASE "snowflake_writer_gcs" TO ROLE "snowflake_writer_gcs";
GRANT ALL ON SCHEMA "snowflake_writer_gcs" TO ROLE "snowflake_writer_gcs";
GRANT ALL ON FUTURE TABLES IN SCHEMA "snowflake_writer_gcs" TO ROLE "snowflake_writer_gcs";
GRANT ALL ON FUTURE VIEWS IN SCHEMA "snowflake_writer_gcs" TO ROLE "snowflake_writer_gcs";
CREATE USER "snowflake_writer_gcs"
PASSWORD = 'password'
DEFAULT_ROLE = "snowflake_writer"
DEFAULT_WAREHOUSE = "snowflake_writer"
DEFAULT_NAMESPACE = "snowflake_writer"."snowflake_writer"
DEFAULT_ROLE = "snowflake_writer_gcs"
DEFAULT_WAREHOUSE = "snowflake_writer_gcs"
DEFAULT_NAMESPACE = "snowflake_writer_gcs"."snowflake_writer_gcs"
MUST_CHANGE_PASSWORD = FALSE;
GRANT ROLE "snowflake_writer" TO USER "snowflake_writer";
GRANT ROLE "snowflake_writer_gcs" TO USER "snowflake_writer_gcs";
```

App is developed on localhost using TDD.

1. Clone from repository: `git clone [email protected]:keboola/db-writer-snowflake.git`
2. Change directory: `cd db-writer-snowflake`
3. Install dependencies: `docker-compose run --rm php composer install -n`
3. Install dependencies: `docker-compose run --rm dev composer install -n`
4. Create `.env` file:
```bash
STORAGE_API_TOKEN=
KBC_URL=
KBC_RUNID=
DB_HOST=
Expand Down
7 changes: 2 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"ext-PDO": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-odbc": "*",
"keboola/db-writer-adapter": "^0.1.0",
"keboola/db-writer-common": "^6.0",
"keboola/db-writer-config": "^0.1.0",
Expand All @@ -24,7 +25,6 @@
"require-dev": {
"cweagans/composer-patches": "^1.7",
"keboola/coding-standard": "^15.0",
"keboola/csv": "^1.5",
"keboola/datadir-tests": "^5.6",
"keboola/storage-api-client": "^14.15",
"phpstan/phpstan": "^1.10",
Expand All @@ -40,17 +40,14 @@
"psr-4": {
"Keboola\\DbWriter\\Snowflake\\Tests\\": "tests/phpunit/",
"Keboola\\DbWriter\\Snowflake\\TraitTests\\": "tests/traits/",
"Keboola\\DbWriter\\Snowflake\\FunctionalTests\\": "tests/functional/",
"Keboola\\DbWriter\\Snowflake\\PrepareTestsData\\": "tests/prepare-data/"
"Keboola\\DbWriter\\Snowflake\\FunctionalTests\\": "tests/functional/"
}
},
"scripts": {
"tests": [
"@tests-prepare-data",
"@tests-phpunit",
"@tests-datadir"
],
"tests-prepare-data": "php ./tests/prepare-data/prepareData.php",
"tests-phpunit": "phpunit --testsuite unit",
"tests-datadir": "phpunit --testsuite functional",
"tests-perf": "phpunit --testsuite perf",
Expand Down
17 changes: 9 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading