subtest basic-nodelocal

exec-sql
CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo/bar';
----

inspect-system-table
----
foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1

# Reject invalid nodelocal URIs.
exec-sql
CREATE EXTERNAL CONNECTION "missing-node-id" AS 'nodelocal:///foo';
----
pq: failed to construct External Connection details: failed to create nodelocal external connection: invalid `nodelocal` URI: host component of nodelocal URI must be a node ID (use 'self' to specify each node should access its own local filesystem): nodelocal:///foo

exec-sql
CREATE EXTERNAL CONNECTION "invalid-nodeid-nodelocal" AS 'nodelocal://a/foo';
----
pq: failed to construct External Connection details: failed to create nodelocal external connection: invalid `nodelocal` URI: host component of nodelocal URI must be a node ID: nodelocal://a/foo

# Try to create another External Connection with the same name.
exec-sql
CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo';
----
pq: failed to create external connection: external connection with connection name 'foo' already exists

# Trying to create another External Connection with the same name using
# IF NOT EXISTS should not fail and should leave the existing
# connection unmodified.
exec-sql
CREATE EXTERNAL CONNECTION IF NOT EXISTS foo AS 'nodelocal://1/nope';
----

inspect-system-table
----
foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1


# Create another External Connection with a unique name.
exec-sql
CREATE EXTERNAL CONNECTION bar123 AS 'nodelocal://1/baz';
----

inspect-system-table
----
bar123 STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/baz"}} root 1
foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1

# Drop an External Connection that does not exist.
exec-sql
DROP EXTERNAL CONNECTION baz;
----

exec-sql
DROP EXTERNAL CONNECTION bar123;
----

inspect-system-table
----
foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1

exec-sql
DROP EXTERNAL CONNECTION foo;
----

inspect-system-table
----

subtest end

subtest basic-gcp-kms

disable-check-kms
----

exec-sql
CREATE EXTERNAL CONNECTION "foo-kms" AS 'gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg==';
----

# Reject invalid KMS URIs.
exec-sql
CREATE EXTERNAL CONNECTION "missing-cmk-kms" AS 'gcp-kms:///?AUTH=implicit&CREDENTIALS=baz&ASSUME_ROLE=ronaldo,rashford,bruno&BEARER_TOKEN=foo';
----
pq: failed to construct External Connection details: failed to create GCP KMS external connection: path component of the KMS cannot be empty; must contain the Customer Managed Key

exec-sql
CREATE EXTERNAL CONNECTION "invalid-params-kms" AS 'gcp-kms:///cmk?AUTH=implicit&INVALIDPARAM=baz';
----
pq: failed to construct External Connection details: failed to create GCP KMS external connection: unknown KMS query parameters: INVALIDPARAM

inspect-system-table
----
foo-kms KMS {"provider": "gcp_kms", "simpleUri": {"uri": "gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-kms";
----

inspect-system-table
----

enable-check-kms
----

subtest end

subtest basic-s3

disable-check-external-storage
----

exec-sql
CREATE EXTERNAL CONNECTION "foo-s3" AS 's3://foo/bar?AUTH=specified&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&AWS_REGION=us-east-1&ASSUME_ROLE=ronaldo,rashford,bruno';
----

# Reject invalid S3 URIs.
exec-sql
CREATE EXTERNAL CONNECTION "missing-host-s3" AS 's3:///?AUTH=implicit';
----
pq: failed to construct External Connection details: failed to create s3 external connection: empty host component; s3 URI must specify a target bucket

exec-sql
CREATE EXTERNAL CONNECTION "invalid-params-s3" AS 's3://foo/bar?AUTH=implicit&INVALIDPARAM=baz';
----
pq: failed to construct External Connection details: failed to create s3 external connection: unknown S3 query parameters: INVALIDPARAM

inspect-system-table
----
foo-s3 STORAGE {"provider": "s3", "simpleUri": {"uri": "s3://foo/bar?AUTH=specified&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&AWS_REGION=us-east-1&ASSUME_ROLE=ronaldo,rashford,bruno"}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-s3";
----

inspect-system-table
----

enable-check-external-storage
----

subtest end

subtest basic-kafka-sink

exec-sql
CREATE EXTERNAL CONNECTION "foo-kafka" AS 'kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256'
----

# Reject invalid kafka external connections.
exec-sql
CREATE EXTERNAL CONNECTION "invalid-param-kafka" AS 'kafka://broker.address.com:9092?INVALIDPARAM=baz'
----
pq: failed to construct External Connection details: invalid changefeed sink URI: unknown kafka sink query parameters: INVALIDPARAM

exec-sql
CREATE EXTERNAL CONNECTION "invalid-cert" AS 'kafka://broker.address.com?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg=11'
----
pq: failed to construct External Connection details: invalid changefeed sink URI: param ca_cert must be base 64 encoded: illegal base64 data at input byte 6

inspect-system-table
----
foo-kafka STORAGE {"provider": "kafka", "simpleUri": {"uri": "kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256"}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-kafka"
----

subtest end

subtest basic-userfile

exec-sql
CREATE EXTERNAL CONNECTION "foo-userfile" AS 'userfile:///foo/bar';
----

inspect-system-table
----
foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1

# Reject invalid userfile URIs.
exec-sql
CREATE EXTERNAL CONNECTION "path-clean-userfile" AS 'userfile:///foo/..';
----
pq: failed to construct External Connection details: failed to create userfile external connection: path /foo/.. changes after normalization to /. userfile upload does not permit such path constructs

exec-sql
CREATE EXTERNAL CONNECTION "invalid-param-userfile" AS 'userfile:///foo?INVALIDPARAM=param';
----
pq: failed to construct External Connection details: failed to create userfile external connection: unknown userfile query parameters: INVALIDPARAM

inspect-system-table
----
foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-userfile";
----

subtest end

subtest basic-gs

disable-check-external-storage
----

exec-sql
CREATE EXTERNAL CONNECTION "foo-gs" AS 'gs://bucket/path?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=='
----

# Reject invalid gs external connections.
exec-sql
CREATE EXTERNAL CONNECTION "invalid-param-gs" AS 'gs://bucket/path?INVALIDPARAM=baz'
----
pq: failed to construct External Connection details: failed to create gs external connection: unknown GS query parameters: INVALIDPARAM

exec-sql
CREATE EXTERNAL CONNECTION "invalid-creds-gs" AS 'gs://bucket/path?AUTH=specified&CREDENTIALS=123'
----
pq: failed to construct External Connection details: failed to create gs external connection: error getting credentials from CREDENTIALS: illegal base64 data at input byte 0

inspect-system-table
----
foo-gs STORAGE {"provider": "gs", "simpleUri": {"uri": "gs://bucket/path?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-gs";
----

enable-check-external-storage
----

subtest end

subtest basic-azure

disable-check-external-storage
----

exec-sql
CREATE EXTERNAL CONNECTION "foo-azure" AS 'azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud'
----

exec-sql
CREATE EXTERNAL CONNECTION "bar-azure" AS 'azure-blob://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud'
----

exec-sql
CREATE EXTERNAL CONNECTION "baz-azure" AS 'azure://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud'
----

# Reject invalid azure external connections.
exec-sql
CREATE EXTERNAL CONNECTION "invalid-param-azure" AS 'azure-storage://bucket/path?INVALIDPARAM=baz'
----
pq: failed to construct External Connection details: failed to create azure external connection: unknown azure query parameters: INVALIDPARAM

exec-sql
CREATE EXTERNAL CONNECTION "foo-azure" AS 'azure-storage://bucket/path?&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud'
----
pq: failed to construct External Connection details: failed to create azure external connection: azure uri missing "AZURE_ACCOUNT_NAME" parameter

exec-sql
CREATE EXTERNAL CONNECTION "foo-azure" AS 'azure-storage://bucket/path?&AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=random-env'
----
pq: failed to construct External Connection details: failed to create azure external connection: azure environment: autorest/azure: There is no cloud environment matching the name "RANDOM-ENV"

inspect-system-table
----
bar-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-blob://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root 1
baz-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root 1
foo-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-azure";
----

exec-sql
DROP EXTERNAL CONNECTION "bar-azure";
----

exec-sql
DROP EXTERNAL CONNECTION "baz-azure";
----

enable-check-external-storage
----

disable-check-kms
----

exec-sql
CREATE EXTERNAL CONNECTION "foo-kms" AS 'azure-kms:///cmk/id?AUTH=specified&AZURE_VAULT_NAME=vault&AZURE_CLIENT_ID=client&AZURE_CLIENT_SECRET=secret&AZURE_TENANT_ID=tenant';
----

# Reject invalid KMS URIs.
exec-sql
CREATE EXTERNAL CONNECTION "missing-cmk-kms" AS 'azure-kms:///?AUTH=implicit&CREDENTIALS=baz&ASSUME_ROLE=ronaldo,rashford,bruno&BEARER_TOKEN=foo';
----
pq: failed to construct External Connection details: failed to create Azure KMS external connection: path component of the KMS cannot be empty; must contain the Customer Managed Key

exec-sql
CREATE EXTERNAL CONNECTION "invalid-params-kms" AS 'azure-kms:///cmk?AUTH=implicit&INVALIDPARAM=baz';
----
pq: failed to construct External Connection details: failed to create Azure KMS external connection: unknown KMS query parameters: INVALIDPARAM

inspect-system-table
----
foo-kms KMS {"provider": "azure_kms", "simpleUri": {"uri": "azure-kms:///cmk/id?AUTH=specified&AZURE_VAULT_NAME=vault&AZURE_CLIENT_ID=client&AZURE_CLIENT_SECRET=secret&AZURE_TENANT_ID=tenant"}} root 1

exec-sql
DROP EXTERNAL CONNECTION "foo-kms";
----

inspect-system-table
----

enable-check-kms
----

subtest end
