-
Notifications
You must be signed in to change notification settings - Fork 215
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
Confluence as source plugin #5404
Merged
kkondaka
merged 21 commits into
opensearch-project:main
from
san81:confluence-as-source-plugin
Feb 11, 2025
Merged
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
ae65748
confluence source
san81 d20e6fa
merging main
san81 98660a1
matching config structure to be more inline for Confluence
san81 b358db7
merging main
san81 6f40d65
Functional confluence version
san81 378c41f
Saving page content as text
san81 d9a98d0
injectable plugin metrics
san81 04ac7c0
Introduced atlassian common module
san81 0e89bf0
functional with making use of Atlassian Commons package
san81 66befd5
test cases in a running state
san81 4fde3e9
atlassian commons gradle file
san81 6bd3451
moved the test to the atlassian commons
san81 f8e8d45
additional code coverage
san81 47ee223
better names
san81 15e0b4a
better naming
san81 14a5870
making a default implementation
san81 6ae21b9
Merge branch 'main' of github.com:san81/data-prepper into confluence-…
san81 f207bcc
addressing review comments
san81 aaaf3fc
validating page type filter
san81 b68fd99
fixed failing tests
san81 928e253
using InvalidPluginConfigurationException instead of BadRequestException
san81 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
26 changes: 26 additions & 0 deletions
26
data-prepper-plugins/saas-source-plugins/atlassian-commons/build.gradle
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,26 @@ | ||
plugins { | ||
id 'java' | ||
} | ||
|
||
|
||
dependencies { | ||
|
||
implementation project(path: ':data-prepper-api') | ||
implementation project(path: ':data-prepper-plugins:saas-source-plugins:source-crawler') | ||
implementation project(path: ':data-prepper-plugins:common') | ||
|
||
implementation 'com.fasterxml.jackson.core:jackson-core' | ||
implementation 'com.fasterxml.jackson.core:jackson-databind' | ||
|
||
implementation 'io.micrometer:micrometer-core' | ||
implementation 'org.projectlombok:lombok:1.18.30' | ||
annotationProcessor 'org.projectlombok:lombok:1.18.30' | ||
implementation(libs.spring.web) | ||
|
||
implementation(libs.spring.context) { | ||
exclude group: 'commons-logging', module: 'commons-logging' | ||
} | ||
|
||
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.4' | ||
testImplementation project(path: ':data-prepper-test-common') | ||
} |
59 changes: 59 additions & 0 deletions
59
.../main/java/org/opensearch/dataprepper/plugins/source/atlassian/AtlassianSourceConfig.java
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,59 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import jakarta.validation.Valid; | ||
import lombok.Getter; | ||
import org.opensearch.dataprepper.plugins.source.atlassian.configuration.AuthenticationConfig; | ||
import org.opensearch.dataprepper.plugins.source.source_crawler.base.CrawlerSourceConfig; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
public class AtlassianSourceConfig implements CrawlerSourceConfig { | ||
|
||
private static final int DEFAULT_BATCH_SIZE = 50; | ||
|
||
/** | ||
* Jira account url | ||
*/ | ||
@JsonProperty("hosts") | ||
protected List<String> hosts; | ||
|
||
/** | ||
* Authentication Config to Access Jira | ||
*/ | ||
@JsonProperty("authentication") | ||
@Valid | ||
protected AuthenticationConfig authenticationConfig; | ||
|
||
/** | ||
* Batch size for fetching tickets | ||
*/ | ||
@JsonProperty("batch_size") | ||
protected int batchSize = DEFAULT_BATCH_SIZE; | ||
|
||
|
||
/** | ||
* Boolean property indicating end to end acknowledgments state | ||
*/ | ||
@JsonProperty("acknowledgments") | ||
private boolean acknowledgments = false; | ||
|
||
public String getAccountUrl() { | ||
return this.getHosts().get(0); | ||
} | ||
|
||
public String getAuthType() { | ||
return this.getAuthenticationConfig().getAuthType(); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...g/opensearch/dataprepper/plugins/source/atlassian/configuration/AuthenticationConfig.java
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,46 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.configuration; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import jakarta.validation.Valid; | ||
import jakarta.validation.constraints.AssertTrue; | ||
import lombok.Getter; | ||
|
||
import static org.opensearch.dataprepper.plugins.source.atlassian.utils.Constants.BASIC; | ||
import static org.opensearch.dataprepper.plugins.source.atlassian.utils.Constants.OAUTH2; | ||
|
||
|
||
@Getter | ||
public class AuthenticationConfig { | ||
@JsonProperty("basic") | ||
@Valid | ||
private BasicConfig basicConfig; | ||
|
||
@JsonProperty("oauth2") | ||
@Valid | ||
private Oauth2Config oauth2Config; | ||
|
||
@AssertTrue(message = "Authentication config should have either basic or oauth2") | ||
private boolean isValidAuthenticationConfig() { | ||
boolean hasBasic = basicConfig != null; | ||
boolean hasOauth = oauth2Config != null; | ||
return hasBasic ^ hasOauth; | ||
} | ||
|
||
public String getAuthType() { | ||
if (basicConfig != null) { | ||
return BASIC; | ||
} else { | ||
return OAUTH2; | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...n/java/org/opensearch/dataprepper/plugins/source/atlassian/configuration/BasicConfig.java
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,29 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.configuration; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import jakarta.validation.constraints.AssertTrue; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class BasicConfig { | ||
@JsonProperty("username") | ||
private String username; | ||
|
||
@JsonProperty("password") | ||
private String password; | ||
|
||
@AssertTrue(message = "Username and Password are both required for Basic Auth") | ||
private boolean isBasicConfigValid() { | ||
return username != null && password != null; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
.../java/org/opensearch/dataprepper/plugins/source/atlassian/configuration/Oauth2Config.java
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,36 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.configuration; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import jakarta.validation.constraints.AssertTrue; | ||
import lombok.Getter; | ||
import org.opensearch.dataprepper.model.plugin.PluginConfigVariable; | ||
|
||
@Getter | ||
public class Oauth2Config { | ||
@JsonProperty("client_id") | ||
private String clientId; | ||
|
||
@JsonProperty("client_secret") | ||
private String clientSecret; | ||
|
||
@JsonProperty("access_token") | ||
private PluginConfigVariable accessToken; | ||
|
||
@JsonProperty("refresh_token") | ||
private PluginConfigVariable refreshToken; | ||
|
||
@AssertTrue(message = "Client ID, Client Secret, Access Token, and Refresh Token are both required for Oauth2") | ||
private boolean isOauth2ConfigValid() { | ||
return clientId != null && clientSecret != null && accessToken != null && refreshToken != null; | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
...in/java/org/opensearch/dataprepper/plugins/source/atlassian/rest/AtlassianRestClient.java
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,79 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.rest; | ||
|
||
import com.google.common.annotations.VisibleForTesting; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.opensearch.dataprepper.plugins.source.atlassian.rest.auth.AtlassianAuthConfig; | ||
import org.opensearch.dataprepper.plugins.source.source_crawler.exception.BadRequestException; | ||
import org.opensearch.dataprepper.plugins.source.source_crawler.exception.UnauthorizedException; | ||
import org.opensearch.dataprepper.plugins.source.source_crawler.utils.AddressValidation; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
|
||
import static org.opensearch.dataprepper.logging.DataPrepperMarkers.NOISY; | ||
import static org.opensearch.dataprepper.plugins.source.atlassian.utils.Constants.MAX_RETRIES; | ||
|
||
@Slf4j | ||
public class AtlassianRestClient { | ||
|
||
public static final List<Integer> RETRY_ATTEMPT_SLEEP_TIME = List.of(1, 2, 5, 10, 20, 40); | ||
private int sleepTimeMultiplier = 1000; | ||
private final RestTemplate restTemplate; | ||
private final AtlassianAuthConfig authConfig; | ||
|
||
public AtlassianRestClient(RestTemplate restTemplate, AtlassianAuthConfig authConfig) { | ||
this.restTemplate = restTemplate; | ||
this.authConfig = authConfig; | ||
} | ||
|
||
|
||
protected <T> ResponseEntity<T> invokeRestApi(URI uri, Class<T> responseType) throws BadRequestException { | ||
AddressValidation.validateInetAddress(AddressValidation.getInetAddress(uri.toString())); | ||
int retryCount = 0; | ||
while (retryCount < MAX_RETRIES) { | ||
try { | ||
return restTemplate.getForEntity(uri, responseType); | ||
} catch (HttpClientErrorException ex) { | ||
HttpStatus statusCode = ex.getStatusCode(); | ||
String statusMessage = ex.getMessage(); | ||
log.error("An exception has occurred while getting response from Jira search API {}", ex.getMessage()); | ||
if (statusCode == HttpStatus.FORBIDDEN) { | ||
throw new UnauthorizedException(statusMessage); | ||
} else if (statusCode == HttpStatus.UNAUTHORIZED) { | ||
log.error(NOISY, "Token expired. We will try to renew the tokens now", ex); | ||
authConfig.renewCredentials(); | ||
} else if (statusCode == HttpStatus.TOO_MANY_REQUESTS) { | ||
log.error(NOISY, "Hitting API rate limit. Backing off with sleep timer.", ex); | ||
} | ||
try { | ||
Thread.sleep((long) RETRY_ATTEMPT_SLEEP_TIME.get(retryCount) * sleepTimeMultiplier); | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException("Sleep in the retry attempt got interrupted", e); | ||
} | ||
} | ||
retryCount++; | ||
} | ||
String errorMessage = String.format("Exceeded max retry attempts. Failed to execute the Rest API call %s", uri); | ||
log.error(errorMessage); | ||
throw new RuntimeException(errorMessage); | ||
} | ||
|
||
@VisibleForTesting | ||
public void setSleepTimeMultiplier(int multiplier) { | ||
sleepTimeMultiplier = multiplier; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...n/java/org/opensearch/dataprepper/plugins/source/atlassian/rest/BasicAuthInterceptor.java
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,42 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.rest; | ||
|
||
import org.opensearch.dataprepper.plugins.source.atlassian.AtlassianSourceConfig; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpRequest; | ||
import org.springframework.http.client.ClientHttpRequestExecution; | ||
import org.springframework.http.client.ClientHttpRequestInterceptor; | ||
import org.springframework.http.client.ClientHttpResponse; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Base64; | ||
|
||
|
||
public class BasicAuthInterceptor implements ClientHttpRequestInterceptor { | ||
private final String username; | ||
private final String password; | ||
|
||
public BasicAuthInterceptor(AtlassianSourceConfig config) { | ||
this.username = config.getAuthenticationConfig().getBasicConfig().getUsername(); | ||
this.password = config.getAuthenticationConfig().getBasicConfig().getPassword(); | ||
} | ||
|
||
@Override | ||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { | ||
String auth = username + ":" + password; | ||
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.US_ASCII)); | ||
String authHeader = "Basic " + new String(encodedAuth); | ||
request.getHeaders().set(HttpHeaders.AUTHORIZATION, authHeader); | ||
return execution.execute(request, body); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...va/org/opensearch/dataprepper/plugins/source/atlassian/rest/CustomRestTemplateConfig.java
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,42 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.source.atlassian.rest; | ||
|
||
|
||
import org.opensearch.dataprepper.plugins.source.atlassian.AtlassianSourceConfig; | ||
import org.opensearch.dataprepper.plugins.source.atlassian.rest.auth.AtlassianAuthConfig; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.http.client.ClientHttpRequestInterceptor; | ||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import static org.opensearch.dataprepper.plugins.source.atlassian.utils.Constants.OAUTH2; | ||
|
||
@Configuration | ||
public class CustomRestTemplateConfig { | ||
|
||
@Bean | ||
public RestTemplate basicAuthRestTemplate(AtlassianSourceConfig config, AtlassianAuthConfig authConfig) { | ||
RestTemplate restTemplate = new RestTemplate(); | ||
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); | ||
ClientHttpRequestInterceptor httpInterceptor; | ||
if (OAUTH2.equals(config.getAuthType())) { | ||
httpInterceptor = new OAuth2RequestInterceptor(authConfig); | ||
} else { | ||
httpInterceptor = new BasicAuthInterceptor(config); | ||
} | ||
restTemplate.getInterceptors().add(httpInterceptor); | ||
return restTemplate; | ||
} | ||
|
||
|
||
} |
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.
Why is this a list of hosts? It seems the code only supports one host and that would be simpler for users:
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 is a recommendation from Raj to support future expansion I guess.