Skip to content

Commit 5ccc211

Browse files
grvsahilGaurav Sahil
andauthored
feat: initial source implementation (#2)
* feat: initial source implementation * seperated source logic into iterator * added test cases * added integration test * remove go generate directive from source * fix: test cases * fix: teardown * added go header * added file chunk mechanism for files larger than 3 mb * added configurable chunk * fix: updated readme * fix: large file processing * fix: refactored iterator * fix: handle file modification while read * fix: source integration test * modify README file * fix: refactored iterator to provide record on demand * added source and destination directories in docker compose * fix: test workflow --------- Co-authored-by: Gaurav Sahil <[email protected]>
1 parent b3a097e commit 5ccc211

33 files changed

+1748
-416
lines changed

.github/pull_request_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ Fixes # (issue)
88

99
### Quick checks:
1010

11-
- [ ] There is no other [pull request](https://github.com/conduitio/conduit-connector-connectorname/pulls) for the same update/change.
11+
- [ ] There is no other [pull request](https://github.com/conduitio/conduit-connector-sftp/pulls) for the same update/change.
1212
- [ ] I have written unit tests.
1313
- [ ] I have made sure that the PR is of reasonable size and can be easily reviewed.

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ jobs:
1717
go-version-file: 'go.mod'
1818

1919
- name: Test
20-
run: make test-integration GOTEST_FLAGS="-v -count=1"
20+
run: make test GOTEST_FLAGS="-v -count=1"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
.vscode
2121

2222
# Binary, built with `make build`
23-
/conduit-connector-connectorname
23+
/conduit-connector-sftp
2424

2525
### OS ###
2626
.DS_Store

.golangci.goheader.template

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright © {{ copyright-year }} Meroxa, Inc.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

.golangci.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ linters-settings:
2020
- .WithMessagef(
2121
- .WithStack(
2222
- (context.Context).Err()
23-
23+
goheader:
24+
template-path: '.golangci.goheader.template'
25+
values:
26+
regexp:
27+
copyright-year: 20[2-9]\d
28+
2429
issues:
2530
exclude-rules:
2631
- path: _test\.go

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ builds:
88
env:
99
- CGO_ENABLED=0
1010
ldflags:
11-
- "-s -w -X 'github.com/conduitio/conduit-connector-connectorname.version={{ .Tag }}'"
11+
- "-s -w -X 'github.com/conduitio/conduit-connector-sftp.version={{ .Tag }}'"
1212
checksum:
1313
name_template: checksums.txt
1414
archives:

Makefile

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,28 @@ VERSION=$(shell git describe --tags --dirty --always)
22

33
.PHONY: build
44
build:
5-
go build -ldflags "-X 'github.com/conduitio/conduit-connector-connectorname.version=${VERSION}'" -o conduit-connector-connectorname cmd/connector/main.go
5+
go build -ldflags "-X 'github.com/conduitio/conduit-connector-sftp.version=${VERSION}'" -o conduit-connector-sftp cmd/connector/main.go
66

77
.PHONY: test
88
test:
9-
go test $(GOTEST_FLAGS) -race ./...
10-
11-
.PHONY: test-integration
12-
test-integration:
139
# run required docker containers, execute integration tests, stop containers after tests
1410
docker compose -f test/docker-compose.yml up -d
1511
go test $(GOTEST_FLAGS) -v -race ./...; ret=$$?; \
1612
docker compose -f test/docker-compose.yml down; \
1713
exit $$ret
1814

15+
.PHONY: gofumpt
16+
gofumpt:
17+
go install mvdan.cc/gofumpt@latest
18+
19+
.PHONY: fmt
20+
fmt: gofumpt
21+
gofumpt -l -w .
22+
23+
.PHONY: lint
24+
lint:
25+
golangci-lint run -v
26+
1927
.PHONY: generate
2028
generate:
2129
go generate ./...
@@ -25,11 +33,3 @@ install-tools:
2533
@echo Installing tools from tools.go
2634
@go list -e -f '{{ join .Imports "\n" }}' tools.go | xargs -I % go list -f "%@{{.Module.Version}}" % | xargs -tI % go install %
2735
@go mod tidy
28-
29-
.PHONY: fmt
30-
fmt:
31-
gofumpt -l -w .
32-
33-
.PHONY: lint
34-
lint:
35-
golangci-lint run

README.md

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,36 @@
1-
# Conduit Connector Template
1+
# Conduit Connector SFTP
22

3-
This is a template project for building [Conduit](https://conduit.io) connectors in Go. It makes it possible to
4-
start working on a Conduit connector in a matter of seconds.
3+
The SFTP connector is one of [Conduit](https://github.com/ConduitIO/conduit) plugins. It
4+
provides both, a source and a destination SFTP connector.
55

6-
## Quick start
6+
## How to build it
77

8-
1. Click [_Use this template_](https://github.com/new?template_name=conduit-connector-template&template_owner=ConduitIO) and clone your new repository.
9-
2. Initialize the repository using [`setup.sh`](https://github.com/ConduitIO/conduit-connector-template/blob/main/setup.sh) and commit your changes.
10-
```sh
11-
./setup.sh github.com/myusername/conduit-connector-myconnector
12-
git add -A
13-
git commit -m "initialize repository"
14-
```
15-
3. Set up [automatic Dependabot PR merges](#automatically-merging-dependabot-prs).
8+
Run `make build`.
169

17-
With that, you're all set up and ready to start working on your connector! As a next step, we recommend that you
18-
check out the [Conduit Connector SDK](https://github.com/ConduitIO/conduit-connector-sdk).
10+
## Testing
1911

20-
## What's included?
12+
Run `make test` to run all the unit and integration tests.
2113

22-
* Skeleton code for the connector's configuration, source and destination.
23-
* Example unit tests.
24-
* A [Makefile](/Makefile) with commonly used targets.
25-
* A [GitHub workflow](/.github/workflows/test.yml) to build the code and run the tests.
26-
* A [GitHub workflow](/.github/workflows/lint.yml) to run a pre-configured set of linters.
27-
* A [GitHub workflow](/.github/workflows/release.yml) which automatically creates a release when a tag is pushed.
28-
* A [Dependabot setup](/.github/dependabot.yml) which checks your dependencies for available updates and
29-
[merges minor version upgrades](/.github/workflows/dependabot-auto-merge-go.yml) automatically.
30-
* [Issue](/.github/ISSUE_TEMPLATE) and [PR templates](/.github/pull_request_template.md).
31-
* A [README template](/README_TEMPLATE.md).
14+
## Source
3215

33-
## Automatically merging Dependabot PRs
16+
The source SFTP connector monitors a directory on an SFTP server for files matching a specified pattern. It reads these files and converts them into `opencdc.Record` that can be processed by Conduit. For handling large files, it splits them into smaller chunks, enabling smooth data handling through the Conduit pipeline.
17+
The connector supports both password and private key authentication methods.
3418

35-
> [!NOTE]
36-
> This applies only to public connector repositories, as branch protection rules are not enforced in private repositories.
19+
### Configuration Options
3720

38-
The template makes it simple to keep your connector up-to-date using automatic merging of
39-
[Dependabot](https://github.com/dependabot) PRs. To make use of this setup, you need to adjust
40-
some repository settings.
21+
| name | description | required | default value |
22+
| -------------- | ----------------------------------------------------------------------------------------------------- | -------- | -------- |
23+
| `address` | Address is the address of the sftp server to connect.| **true** | |
24+
| `hostKey` | HostKey is the key used for host key callback validation.| **true** | |
25+
| `username`| User is the username of the SFTP user. | **true** | |
26+
| `password`| Password is the SFTP password (can be used as passphrase for private key). | false | |
27+
| `privateKeyPath`| PrivateKeyPath is the private key for ssh login.| false | |
28+
| `directoryPath` | DirectoryPath is the path to the directory to read data. | **true** | |
29+
| `filePattern` | Pattern to match files that should be read (e.g., "*.txt") | false | `*` |
30+
| `fileChunkSizeBytes` | Maximum size of a file chunk in bytes to split large files. | false | `3145728` |
4131

42-
1. Navigate to Settings -> General and allow auto-merge of PRs.
32+
## Destination
4333

44-
![Allow auto-merge](https://github.com/ConduitIO/conduit-connector-template/assets/8320753/695b15f0-85b4-49cb-966d-649e9bf03455)
34+
### Configuration Options
4535

46-
2. Navigate to Settings -> Branches and add a branch protection rule.
47-
48-
![Add branch protection rule](https://github.com/ConduitIO/conduit-connector-template/assets/8320753/9f5a07bc-d141-42b9-9918-e8d9cc648482)
49-
50-
3. Create a rule for branch `main` that requires status checks `build` and `golangci-lint`.
51-
52-
![Status checks](https://github.com/ConduitIO/conduit-connector-template/assets/8320753/96219185-c329-432a-8623-9b4462015f32)
53-
54-
## Recommended repository settings
55-
56-
- Allow squash merging only.
57-
- Always suggest updating pull request branches.
58-
- Automatically delete head branches.
59-
- Branch protection rules on branch `main` (only in public repositories):
60-
- Require a pull request before merging.
61-
- Require approvals.
62-
- Require status checks `build` and `golangci-lint`.
63-
- Require branches to be up to date before merging.
64-
- Require conversation resolution before merging.
65-
- Do not allow bypassing the above settings.
36+
![scarf pixel](https://static.scarf.sh/a.png?x-pxid=64b333ae-77ad-4895-a5cd-a73bb14362d9)

cmd/connector/main.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
1+
// Copyright © 2024 Meroxa, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
115
package main
216

317
import (
4-
connectorname "github.com/conduitio/conduit-connector-connectorname"
18+
sftp "github.com/conduitio-labs/conduit-connector-sftp"
519
sdk "github.com/conduitio/conduit-connector-sdk"
620
)
721

822
func main() {
9-
sdk.Serve(connectorname.Connector)
23+
sdk.Serve(sftp.Connector)
1024
}

config.go

Lines changed: 0 additions & 10 deletions
This file was deleted.

config/config.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright © 2024 Meroxa, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:generate paramgen -output=paramgen.go Config
16+
17+
package config
18+
19+
import "fmt"
20+
21+
var ErrEmptyAuthFields = fmt.Errorf("both %q and %q can not be empty", ConfigPassword, ConfigPrivateKeyPath)
22+
23+
// Config contains shared config parameters, common to the source and destination.
24+
type Config struct {
25+
// Address is the address of the sftp server to connect.
26+
Address string `json:"address" validate:"required"`
27+
// HostKey is the key used for host key callback validation.
28+
HostKey string `json:"hostKey" validate:"required"`
29+
// User is the SFTP user.
30+
Username string `json:"username" validate:"required"`
31+
// Password is the SFTP password (can be used as passphrase for private key).
32+
Password string `json:"password"`
33+
// PrivateKeyPath is the private key for ssh login.
34+
PrivateKeyPath string `json:"privateKeyPath"`
35+
// DirectoryPath is the path to the directory to read/write data.
36+
DirectoryPath string `json:"directoryPath" validate:"required"`
37+
}
38+
39+
// Validate is used for custom validation for sftp authentication configuration.
40+
func (c *Config) Validate() error {
41+
if c.Password == "" && c.PrivateKeyPath == "" {
42+
return ErrEmptyAuthFields
43+
}
44+
return nil
45+
}

config/config_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright © 2024 Meroxa, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"testing"
19+
)
20+
21+
func TestConfig_Validate(t *testing.T) {
22+
type fields struct {
23+
Address string
24+
Username string
25+
Password string
26+
PrivateKeyPath string
27+
}
28+
tests := []struct {
29+
name string
30+
fields fields
31+
wantErr error
32+
}{
33+
{
34+
name: "success: password authentication",
35+
fields: fields{
36+
Address: "localhost:22",
37+
Username: "user",
38+
Password: "pass",
39+
},
40+
wantErr: nil,
41+
},
42+
{
43+
name: "success: privatekey authentication",
44+
fields: fields{
45+
Address: "localhost:22",
46+
Username: "user",
47+
PrivateKeyPath: "path",
48+
},
49+
wantErr: nil,
50+
},
51+
{
52+
name: "error: missing password and privateKeyPath",
53+
fields: fields{
54+
Address: "localhost:22",
55+
Username: "user",
56+
},
57+
wantErr: ErrEmptyAuthFields,
58+
},
59+
}
60+
for _, tt := range tests {
61+
t.Run(tt.name, func(t *testing.T) {
62+
c := &Config{
63+
Address: tt.fields.Address,
64+
Username: tt.fields.Username,
65+
Password: tt.fields.Password,
66+
PrivateKeyPath: tt.fields.PrivateKeyPath,
67+
}
68+
err := c.Validate()
69+
if err != nil {
70+
if tt.wantErr != nil && tt.wantErr.Error() != err.Error() {
71+
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
72+
}
73+
}
74+
})
75+
}
76+
}

0 commit comments

Comments
 (0)