-
Notifications
You must be signed in to change notification settings - Fork 224
MotherDuck plugin for DuckDB #511
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
base: main
Are you sure you want to change the base?
Changes from 3 commits
a40313e
f1ce238
e08177c
00e7531
3cf4544
14818e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package motherduck | ||
|
||
import ( | ||
"github.com/1Password/shell-plugins/sdk" | ||
"github.com/1Password/shell-plugins/sdk/importer" | ||
"github.com/1Password/shell-plugins/sdk/provision" | ||
"github.com/1Password/shell-plugins/sdk/schema" | ||
"github.com/1Password/shell-plugins/sdk/schema/credname" | ||
"github.com/1Password/shell-plugins/sdk/schema/fieldname" | ||
) | ||
|
||
func AccessToken() schema.CredentialType { | ||
return schema.CredentialType{ | ||
Name: credname.AccessToken, | ||
DocsURL: sdk.URL("https://motherduck.com/docs/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/#authentication-using-an-access-token"), | ||
ManagementURL: sdk.URL("https://app.motherduck.com/settings/general"), | ||
Fields: []schema.CredentialField{ | ||
{ | ||
Name: fieldname.Token, | ||
MarkdownDescription: "Token used to authenticate to MotherDuck.", | ||
Secret: true, | ||
Composition: &schema.ValueComposition{ | ||
Length: 405, | ||
sterlinm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Charset: schema.Charset{ | ||
Uppercase: true, | ||
Lowercase: true, | ||
Digits: true, | ||
}, | ||
sterlinm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
}, | ||
}, | ||
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping), | ||
Importer: importer.TryAll( | ||
importer.TryEnvVarPair(defaultEnvVarMapping), | ||
)} | ||
} | ||
|
||
var defaultEnvVarMapping = map[string]sdk.FieldName{ | ||
"motherduck_token": fieldname.Token, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package motherduck | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/1Password/shell-plugins/sdk" | ||
"github.com/1Password/shell-plugins/sdk/plugintest" | ||
"github.com/1Password/shell-plugins/sdk/schema/fieldname" | ||
) | ||
|
||
func TestAccessTokenProvisioner(t *testing.T) { | ||
plugintest.TestProvisioner(t, AccessToken().DefaultProvisioner, map[string]plugintest.ProvisionCase{ | ||
"default": { | ||
ItemFields: map[sdk.FieldName]string{ // TODO: Check if this is correct | ||
fieldname.Token: "TERAkHVPg65C6UGDw42llLlgPtZhBbafxnpqs74fjyuKnDpSt7TZNODw3catnivaruR09REDcNIwystkLMlRw5foxRjvytBFmkk0t0x9iHqY0MBY40Ltbcdw8fvt3OzsCgxmbh89v0XIWrRiwCfALA1dbqWDLaatAZWOLQhJmYcggQR6YBVoKM9H7XBrBjDtP7YJOoU2Z7rc7KWgTTqS9vyCtLx7GDSBitWQLvUYuWzvgh94qk1Wt16oua34jzDtosd59ahNlvA1vEqPtkYqC5mNbDbWqcunwelka4tI4uuEfyojeXowBzkv6izjT48J3usTPIIqTFMYgJnMwUtV6n8UgeuLumEsKd86HVLywapqO37zfNrlrVLzjHSv0rGA2NjDgBAueK2clqEXAMPLE", | ||
}, | ||
ExpectedOutput: sdk.ProvisionOutput{ | ||
Environment: map[string]string{ | ||
"MOTHERDUCK_TOKEN": "TERAkHVPg65C6UGDw42llLlgPtZhBbafxnpqs74fjyuKnDpSt7TZNODw3catnivaruR09REDcNIwystkLMlRw5foxRjvytBFmkk0t0x9iHqY0MBY40Ltbcdw8fvt3OzsCgxmbh89v0XIWrRiwCfALA1dbqWDLaatAZWOLQhJmYcggQR6YBVoKM9H7XBrBjDtP7YJOoU2Z7rc7KWgTTqS9vyCtLx7GDSBitWQLvUYuWzvgh94qk1Wt16oua34jzDtosd59ahNlvA1vEqPtkYqC5mNbDbWqcunwelka4tI4uuEfyojeXowBzkv6izjT48J3usTPIIqTFMYgJnMwUtV6n8UgeuLumEsKd86HVLywapqO37zfNrlrVLzjHSv0rGA2NjDgBAueK2clqEXAMPLE", | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccessTokenImporter(t *testing.T) { | ||
plugintest.TestImporter(t, AccessToken().Importer, map[string]plugintest.ImportCase{ | ||
"environment": { | ||
Environment: map[string]string{ // TODO: Check if this is correct | ||
"MOTHERDUCK_TOKEN": "TERAkHVPg65C6UGDw42llLlgPtZhBbafxnpqs74fjyuKnDpSt7TZNODw3catnivaruR09REDcNIwystkLMlRw5foxRjvytBFmkk0t0x9iHqY0MBY40Ltbcdw8fvt3OzsCgxmbh89v0XIWrRiwCfALA1dbqWDLaatAZWOLQhJmYcggQR6YBVoKM9H7XBrBjDtP7YJOoU2Z7rc7KWgTTqS9vyCtLx7GDSBitWQLvUYuWzvgh94qk1Wt16oua34jzDtosd59ahNlvA1vEqPtkYqC5mNbDbWqcunwelka4tI4uuEfyojeXowBzkv6izjT48J3usTPIIqTFMYgJnMwUtV6n8UgeuLumEsKd86HVLywapqO37zfNrlrVLzjHSv0rGA2NjDgBAueK2clqEXAMPLE", | ||
}, | ||
ExpectedCandidates: []sdk.ImportCandidate{ | ||
{ | ||
Fields: map[sdk.FieldName]string{ | ||
fieldname.Token: "TERAkHVPg65C6UGDw42llLlgPtZhBbafxnpqs74fjyuKnDpSt7TZNODw3catnivaruR09REDcNIwystkLMlRw5foxRjvytBFmkk0t0x9iHqY0MBY40Ltbcdw8fvt3OzsCgxmbh89v0XIWrRiwCfALA1dbqWDLaatAZWOLQhJmYcggQR6YBVoKM9H7XBrBjDtP7YJOoU2Z7rc7KWgTTqS9vyCtLx7GDSBitWQLvUYuWzvgh94qk1Wt16oua34jzDtosd59ahNlvA1vEqPtkYqC5mNbDbWqcunwelka4tI4uuEfyojeXowBzkv6izjT48J3usTPIIqTFMYgJnMwUtV6n8UgeuLumEsKd86HVLywapqO37zfNrlrVLzjHSv0rGA2NjDgBAueK2clqEXAMPLE", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package motherduck | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/1Password/shell-plugins/sdk" | ||
"github.com/1Password/shell-plugins/sdk/needsauth" | ||
"github.com/1Password/shell-plugins/sdk/schema" | ||
"github.com/1Password/shell-plugins/sdk/schema/credname" | ||
) | ||
|
||
func NotWhenAnyArgsContain(argsSequence ...string) sdk.NeedsAuthentication { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment on what this custom implementation does and why it is needed and can't be built with the existing functions? That can increase the confidence that this plugin behaves as expected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I replaced this with a more specific helper function. We only use need to authenticate with 1password if the connection string contains 'md:' but motherduck_token is not specified in the connection string and not set as an environment variable. |
||
return func(in sdk.NeedsAuthenticationInput) bool { | ||
if len(argsSequence) == 0 { | ||
return true | ||
} | ||
|
||
if len(argsSequence) > len(in.CommandArgs) { | ||
return true | ||
} | ||
|
||
for i := range in.CommandArgs { | ||
if i+len(argsSequence) > len(in.CommandArgs) { | ||
return true | ||
} | ||
|
||
matches := true | ||
for i, argsToCompare := range in.CommandArgs[i : i+len(argsSequence)] { | ||
if !strings.Contains(argsToCompare, argsSequence[i]) { | ||
matches = false | ||
} | ||
} | ||
|
||
// If the argsToSkip are found in the command-line args, return that the command | ||
// does not not require authentication | ||
if matches { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
} | ||
|
||
func DuckDBCLI() schema.Executable { | ||
return schema.Executable{ | ||
Name: "DuckDB CLI", | ||
Runs: []string{"duckdb"}, | ||
DocsURL: sdk.URL("https://duckdb.org/docs/api/cli/overview"), | ||
NeedsAuth: needsauth.IfAll( | ||
needsauth.NotForHelpOrVersion(), | ||
NotWhenAnyArgsContain("motherduck_token="), | ||
), | ||
Uses: []schema.CredentialUsage{ | ||
{ | ||
Name: credname.AccessToken, | ||
}, | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package motherduck | ||
|
||
import ( | ||
"github.com/1Password/shell-plugins/sdk" | ||
"github.com/1Password/shell-plugins/sdk/schema" | ||
) | ||
|
||
func New() schema.Plugin { | ||
return schema.Plugin{ | ||
Name: "motherduck", | ||
Platform: schema.PlatformInfo{ | ||
Name: "MotherDuck", | ||
Homepage: sdk.URL("https://motherduck.com"), // TODO: Check if this is correct | ||
sterlinm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
Credentials: []schema.CredentialType{ | ||
AccessToken(), | ||
}, | ||
Executables: []schema.Executable{ | ||
DuckDBCLI(), | ||
}, | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.