generated from ConduitIO/conduit-connector-template
-
Notifications
You must be signed in to change notification settings - Fork 0
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
Destination connector implementation. #1
Open
parikshitg
wants to merge
23
commits into
feat/source
Choose a base branch
from
feat/destination
base: feat/source
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
c61252d
feat: package sftp
parikshitg 7eba265
feat: updated initial template and added config
parikshitg 18c505f
feat: updated config
parikshitg dc7f09e
feat: destination configuration
parikshitg 04f08b5
feat: config test and error handling
parikshitg b82c95a
feat: sftp client
parikshitg 56a3958
feat: upload file
parikshitg 5577c00
feat: handled host key callback
parikshitg 51504ef
feat: adding test cases
parikshitg 718a325
fix: lint
parikshitg 9d261ea
feat: acceptance
parikshitg 973c84e
fix: small fix
parikshitg a7d4738
feat: readme
parikshitg 49103a8
feat: upload large file
parikshitg 5f78243
Merge branch 'feat/source' of github.com:conduitio-labs/conduit-conne…
parikshitg 76c91f7
feat: merged source
parikshitg 84087a4
fix: source acceptance to be handled separately
parikshitg 39e1020
Merge branch 'feat/source' of github.com:conduitio-labs/conduit-conne…
parikshitg 393adb2
feat: handled missing filename in metadata
parikshitg b6947af
fix: refactored
parikshitg 3fe8e59
Merge branch 'feat/source' of github.com:conduitio-labs/conduit-conne…
parikshitg 6756d54
fix: source and destination tests
parikshitg 2bba150
fix: linters
parikshitg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright © 2024 Meroxa, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package sftp | ||
|
||
import ( | ||
"fmt" | ||
"os/exec" | ||
"sync/atomic" | ||
"testing" | ||
"time" | ||
|
||
"github.com/conduitio-labs/conduit-connector-sftp/config" | ||
"github.com/conduitio-labs/conduit-connector-sftp/destination" | ||
"github.com/conduitio/conduit-commons/opencdc" | ||
sdk "github.com/conduitio/conduit-connector-sdk" | ||
) | ||
|
||
type driver struct { | ||
sdk.ConfigurableAcceptanceTestDriver | ||
id int64 | ||
} | ||
|
||
func (d *driver) GenerateRecord(_ *testing.T, _ opencdc.Operation) opencdc.Record { | ||
atomic.AddInt64(&d.id, 1) | ||
|
||
content := []byte("hello world") | ||
filename := fmt.Sprintf("%d.txt", d.id) | ||
|
||
return sdk.Util.Source.NewRecordCreate( | ||
nil, | ||
map[string]string{ | ||
opencdc.MetadataCollection: "upload", | ||
opencdc.MetadataCreatedAt: time.Now().UTC().Format(time.RFC3339), | ||
"filename": filename, | ||
"source_path": "/upload", | ||
"file_size": fmt.Sprintf("%d", len(content)), | ||
"mod_time": time.Now().UTC().Format(time.RFC3339), | ||
}, | ||
opencdc.StructuredData{"filename": filename}, | ||
opencdc.RawData(content), | ||
) | ||
} | ||
|
||
func (d *driver) ReadFromDestination(_ *testing.T, records []opencdc.Record) []opencdc.Record { | ||
return records | ||
} | ||
|
||
func TestAcceptance(t *testing.T) { | ||
hostKey, err := setupHostKey() | ||
if err != nil { | ||
fmt.Println(err) | ||
return | ||
} | ||
|
||
sdk.AcceptanceTest(t, &driver{ | ||
ConfigurableAcceptanceTestDriver: sdk.ConfigurableAcceptanceTestDriver{ | ||
Config: sdk.ConfigurableAcceptanceTestDriverConfig{ | ||
Connector: sdk.Connector{ | ||
NewSpecification: Specification, | ||
NewDestination: destination.NewDestination, | ||
NewSource: nil, | ||
}, | ||
DestinationConfig: map[string]string{ | ||
config.ConfigAddress: "localhost:2222", | ||
config.ConfigHostKey: hostKey, | ||
config.ConfigUsername: "user", | ||
config.ConfigPassword: "pass", | ||
config.ConfigDirectoryPath: "/upload", | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func setupHostKey() (string, error) { | ||
cmd := exec.Command("ssh-keyscan", "-t", "rsa", "-p", "2222", "localhost") | ||
output, err := cmd.Output() | ||
if err != nil { | ||
return "", fmt.Errorf("error setupHostKey: %w", err) | ||
} | ||
return string(output), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright © 2024 Meroxa, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package common | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"net" | ||
"os" | ||
|
||
"golang.org/x/crypto/ssh" | ||
) | ||
|
||
var ErrUntrustedKey = fmt.Errorf("host key does not match the trusted key") | ||
|
||
type MismatchKeyTypeError struct { | ||
key1, key2 string | ||
} | ||
|
||
func (e MismatchKeyTypeError) Error() string { | ||
return fmt.Sprintf("host key type mismatch: got %s, want %s", e.key1, e.key2) | ||
} | ||
|
||
func NewMismatchKeyTypeError(key1, key2 string) MismatchKeyTypeError { | ||
return MismatchKeyTypeError{key1, key2} | ||
} | ||
|
||
func SSHConfigAuth(remoteHostKey, username, password, privateKeyPath string) (*ssh.ClientConfig, error) { | ||
//nolint:dogsled // not required here. | ||
hostKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(remoteHostKey)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse server public key: %w", err) | ||
} | ||
|
||
hostKeyCallback := func(_ string, _ net.Addr, key ssh.PublicKey) error { | ||
if key.Type() != hostKey.Type() { | ||
return NewMismatchKeyTypeError(key.Type(), hostKey.Type()) | ||
} | ||
|
||
if !bytes.Equal(key.Marshal(), hostKey.Marshal()) { | ||
return ErrUntrustedKey | ||
} | ||
|
||
return nil | ||
} | ||
|
||
sshConfig := &ssh.ClientConfig{ | ||
User: username, | ||
HostKeyCallback: hostKeyCallback, | ||
} | ||
|
||
if privateKeyPath != "" { | ||
auth, err := authWithPrivateKey(privateKeyPath, password) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
sshConfig.Auth = []ssh.AuthMethod{auth} | ||
return sshConfig, nil | ||
} | ||
|
||
sshConfig.Auth = []ssh.AuthMethod{ssh.Password(password)} | ||
return sshConfig, nil | ||
} | ||
|
||
func authWithPrivateKey(privateKeyPath, password string) (ssh.AuthMethod, error) { | ||
key, err := os.ReadFile(privateKeyPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read private key file: %w", err) | ||
} | ||
|
||
if password != "" { | ||
signer, err := ssh.ParsePrivateKeyWithPassphrase(key, []byte(password)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse private key: %w", err) | ||
} | ||
return ssh.PublicKeys(signer), nil | ||
} | ||
|
||
signer, err := ssh.ParsePrivateKey(key) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse private key: %w", err) | ||
} | ||
|
||
return ssh.PublicKeys(signer), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chunking is a nice feature and it would be good to mention in the readme that we support it and in which way (what metadata is needed, and so on), so that other sources (not only SFTP) can use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioned.