Ahmed Al-Dulimi
07/05/2023, 5:12 PMssh dbt@bastion-prod.company.something -N -C -L "5432:<http://prod-db.something.amazonaws.com:5432|prod-db.something.amazonaws.com:5432>"
and my profiles.yml
would look something like this:
threads: 4
host: localhost
port: 5432
user: dbt
pass: psql_pass
dbname: db
schema: schema
I tried replicating this in Dagster using dagster-ssh, but there aren't any examples to see how. Using the source code as reference, I tried this but it didn't work:
resources = {
"dbt": DbtCliClientResource(
project_dir=DBT_PROJECT_PATH,
profiles_dir=DBT_PROFILES,
),
"ssh": SSHResource(
remote_host="bastion-prod.company.something",
remote_port=22,
key_string=PRIVATE_KEY,
username="dbt", timeout=20).get_tunnel(
remote_port=5432,
remote_host="<http://prod-db.something.amazonaws.com|prod-db.something.amazonaws.com>",
local_port=5432)
}
I get this error (but the key is correct when i do it outside Dagster)
Database Error
connection to server at "localhost" (::1), port 5432 failed: FATAL: password authentication failed for user "dbt"
If it helps, this is how I'm loading by dbt assets
dbt_assets = load_assets_from_dbt_project(
project_dir=DBT_PROJECT_PATH, profiles_dir=DBT_PROFILES,
)
thanks :)Navah Farahat
07/05/2023, 9:07 PMdagster-ssh
uses paramiko under the covers, and i bet it's paramiko that needs your connection parameters to be different, probably the key. i have used paramiko in a few standalone scripts (outside of dagster) to connect to our postgres db via ssh tunnel, and IIRC i couldn't just take the flags and values from my typical ssh navah@integration-db... -N -C
command and make them kwargs in a paramiko.SSHTunnelForwarder()
object. but i don't remember what i had to change š© sorry!Navah Farahat
07/05/2023, 9:07 PMdagster-ssh
resource is doing! it's establishing the connection using paramiko.SSHTunnelForwarder()
, so if you can put together an independent python script that tries to connect that way, the error will probably be more descriptive!Ahmed Al-Dulimi
07/06/2023, 6:25 AMserver = SSHTunnelForwarder(
'bastion-prod.company.something',
ssh_username="dbt",
ssh_pkey="~/.ssh/id_rsa",
remote_bind_address=("<http://prod-db.something.amazonaws.com|prod-db.something.amazonaws.com>", 5432),
local_bind_address=('0.0.0.0', 5432)
)
server.start()
conn = psycopg2.connect(host="127.0.0.1", port=5432, dbname="something", user="dbt", password="something")
but when I try to use dagster-ssh
like this:
resources = {
"dbt": DbtCliClientResource(
project_dir=DBT_PROJECT_PATH,
profiles_dir=DBT_PROFILES,
target="prod",
),
"ssh": SSHResource(
remote_host="bastion-prod.company.something",
remote_port=22,
key_file="~/.ssh/id_rsa",
username="dbt").get_tunnel(
remote_port=5432,
remote_host="<http://prod-db.something.amazonaws.com|prod-db.something.amazonaws.com>",
local_port=5432),
}
I get the following dbt error, which I'm assuming means the tunnel wasn't setup correctly. Am I using the SSHResource
correctly here?
Database Error
connection to server at "localhost" (::1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
Navah Farahat
07/06/2023, 1:59 PMNavah Farahat
07/06/2023, 2:02 PMSSHResource
and the DbtCliClientResource
also need to be given their args through the .configured()
method, but i just noticed you didn'tNavah Farahat
07/06/2023, 2:07 PMsnake_case_resource.configured({kwargs_dict})
, including multiple `dbt_cli_resource`s, `snowflake_resource`s, etc.Ahmed Al-Dulimi
08/04/2023, 4:13 PMTodd de Quincey
08/09/2023, 3:03 PMTodd de Quincey
08/09/2023, 3:06 PMNavah Farahat
08/10/2023, 1:50 PMTodd de Quincey
08/11/2023, 12:52 PMNavah Farahat
08/11/2023, 4:22 PMssh_resource = SSHResource(remote_host=...
remote_port=...,
username=...,
...)
and hereās the syntax you actually want to use to create a configured ssh resource object:
ssh_connection = ssh_resource
.configured({"remote_host": ...,
"remote_port": ...,
"username":...,
...
})
basically you have to give the configuration params as a dict through the .configured()
method, and thatās general advice for all resource objects with configuration, which is why i made the example so generalized šNavah Farahat
08/11/2023, 4:26 PMrex
08/11/2023, 6:47 PM