-
Notifications
You must be signed in to change notification settings - Fork 899
Initial Jira connector commit #3613
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
Initial Jira connector commit #3613
Conversation
Jeffail
left a comment
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.
Hey @zoltancsontosness! Just a couple of comments, code looks really neat on a first pass through.
internal/impl/jira/logging.go
Outdated
| args: optional arguments for format string interpolation | ||
| */ | ||
| func (j *jiraProc) debug(format string, args ...interface{}) { | ||
| if j != nil && j.log != nil { |
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.
It's actually safe to call methods on a nil *service.Logger as it already guards against nil references: https://github.com/redpanda-data/benthos/blob/main/public/service/logger.go#L49, so we don't really need this wrapper and are probably better off without 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.
done ✔️
internal/impl/jira/constants.go
Outdated
| package jira | ||
|
|
||
| // JiraAPIBasePath is the base path for Jira Rest API | ||
| const JiraAPIBasePath = "/rest/api/3" |
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.
This probably doesn't need to be its own file, lets move this into client.go.
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.
done ✔️
|
Would you mind converting block comments to line comments especially for docstrings? |
internal/impl/jira/README.md
Outdated
| @@ -0,0 +1 @@ | |||
| package jira | |||
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.
This is probably not needed.
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.
done ✔️
|
Also, would be good to add file headers. |
internal/impl/jira/config.go
Outdated
| "github.com/redpanda-data/benthos/v4/public/service" | ||
| ) | ||
|
|
||
| type jiraProc struct { |
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.
I like the split to different resources files, I'm confused why this one is called config?
Probably jiraProc belongs to resources, the rest to processor.
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.
done ✔️
|
I’d like to suggest we reduce the number of exported types in the package to keep the API simple and easy to use. It would also be clearer if all Jira-specific code lived in a single package, for example |
|
Please add enterprise license check Look for |
internal/impl/jira/filter.go
Outdated
| If customFields are present in the data, they will also be replaced with their real name; | ||
| example: custom_field_10100 will be replaced with "Story Points" | ||
| */ | ||
| func (j *jiraProc) filter(data interface{}, selectors selectorTree, custom map[string]string) (interface{}, error) { |
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.
Use any instead of interface{}
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.
Could this be a function not method? Or method of selectorTree?
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.
done ✔️
internal/impl/jira/filter.go
Outdated
| "summary": {} | ||
| } | ||
| */ | ||
| func (j *jiraProc) buildSelectorTree(fields []string, custom map[string]string) (selectorTree, error) { |
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.
How about selectorTreeFrom() - a constructor not a method of jiraProc
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.
done ✔️
| Package http_helper usage | ||
|
|
||
| Overview | ||
| - Provides a thin, robust wrapper around net/http to: |
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.
Improve rendering in go doc.
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.
done ✔️
|
|
||
| 5. Example helper wrapping a Jira call | ||
|
|
||
| func callJira(ctx context.Context, client *http.Client, req *http.Request) ([]byte, *jira_helper.JiraError) { |
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.
Improve code formatting - maybe use examples https://go.dev/blog/examples
reduce number of exported types; moved most of the code inside the jirahttp package;
internal/impl/jira/processor.go
Outdated
| return &jirahttp.JiraProc{ | ||
| BaseURL: baseURL, | ||
| Username: username, | ||
| ApiToken: apiToken, | ||
| MaxResults: maxResults, | ||
| RetryOpts: http_helper.RetryOptions{ | ||
| MaxRetries: maxRetries, | ||
| }, | ||
| HttpClient: http_metrics.NewInstrumentedClient( | ||
| mgr.Metrics(), "jira_http", | ||
| httpClient), | ||
| Log: mgr.Logger(), | ||
| }, nil |
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.
We'd like to have all the connect integration code here - in the main jira package, and all the rest, http related, in jirahttp. Also, the helpers belong to jirahttp, as they contain logic specific to JIRA http needs and semantics.
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.
done ✔️
internal/impl/jira/processor.go
Outdated
| ) | ||
|
|
||
| // Configuration specification for the Jira processor | ||
| var jiraProcessorConfigSpec = service.NewConfigSpec(). |
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.
Use function instead of a global variable.
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.
done ✔️
internal/impl/jira/processor.go
Outdated
| @@ -0,0 +1,161 @@ | |||
| // Copyright 2024 Redpanda Data, Inc. | |||
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.
Rename this file to processor_jira.go
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.
done ✔️
internal/impl/jira/processor.go
Outdated
| Description("Maximum number of retries in case of 429 HTTP Status Code"). | ||
| Default(10)) | ||
|
|
||
| func newJiraProcessor(conf *service.ParsedConfig, mgr *service.Resources) (*jirahttp.JiraProc, error) { |
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.
I'm confused, we have a constructor for a type defined in a different package.
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.
done ✔️
internal/impl/jira/processor.go
Outdated
| BaseURL: baseURL, | ||
| Username: username, | ||
| ApiToken: apiToken, | ||
| MaxResults: maxResults, | ||
| RetryOpts: http_helper.RetryOptions{ | ||
| MaxRetries: maxRetries, | ||
| }, | ||
| HttpClient: http_metrics.NewInstrumentedClient( | ||
| mgr.Metrics(), "jira_http", | ||
| httpClient), | ||
| Log: mgr.Logger(), |
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.
The type should have a real constructor and those fields should not be exported.
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.
done ✔️
internal/impl/jira/processor_test.go
Outdated
|
|
||
| tests := []struct { | ||
| name string | ||
| yaml string |
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.
It's safer to avoid names that conflict with common package names
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.
done ✔️
|
The only type exported from |
refactor and make jirahttp package more reusable
|
I wonder why we have decided to implement custom retries for http instead of using something established like https://github.com/hashicorp/go-retryablehttp. It would be faster, easier and more secure. To make this retry scheme work in general case you need a more graceful handling of request body, for example note that (from Do) Given that at this point I suggest to move http_helper.go to jirahttp. |
|
Also, the jira_helper hosting only seems to have a lot in common with the retries and most likely be integrated there - maybe we can reuse the error now each package has it's own. |
|
I'd like to suggest we add Given that we'd like to add more HTTP based processors it makes sense to put pure HTTP concerns is a dedicated package. Then http_metrics should go there, as well as logging, PROXY setting and autodetection that I think will be important. cc @Jeffail |
|
nit: could we rename |
|
We'd take care of |
merge jira_helper and http_helper; merge client.go with jira_http.go
internal/impl/jira/processor_jira.go
Outdated
| // It holds the client state and orchestrates calls into the jirahttp package. | ||
| type jiraProcessor struct { | ||
| log *service.Logger | ||
| jiraHttp *jirahttp.Client |
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.
For clarity let's rename that to client.
|
@zoltancsontosness I think that in general we are good to go. Last items:
|
|
Please make sure lining and testing works. |
move helpers to jirahttp
|
@mmatczuk can you please run the pipeline again to see if the linting passes? locally it runs successfully |
fix lint import error
|
tried generating the docs with |
|
Work moved to #3699 closing this. |
Redpanda Jira Connector
Prerequisites for development
Install go
Install go-task
go install github.com/go-task/task/v3/cmd/task@latestRunning & testing the connector
Set GOBIN variable
go env -w GOBIN=$(pwd)/binLint and format the code
Build the application
go buildSet variables specific to connector that you are running based on config.yaml file (see redpanda secrets):
export JIRA_API_TOKEN=yourTokenRun the connector
./connect --config config.yamlConfig & usage examples
processorconfiguration:inputconfiguration that produces one message into the pipeline: