Skip to content

Commit a8ee900

Browse files
committed
added validation
1
1 parent 4250a33 commit a8ee900

16 files changed

+281
-30
lines changed

pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,28 @@
7676
<groupId>org.slf4j</groupId>
7777
<artifactId>slf4j-log4j12</artifactId>
7878
</exclusion>
79+
<exclusion>
80+
<groupId>org.apache.httpcomponents</groupId>
81+
<artifactId>httpclient</artifactId>
82+
</exclusion>
83+
<exclusion>
84+
<groupId>org.apache.httpcomponents</groupId>
85+
<artifactId>httpcore</artifactId>
86+
</exclusion>
7987
</exclusions>
8088
</dependency>
89+
<dependency>
90+
<groupId>org.apache.httpcomponents</groupId>
91+
<artifactId>httpclient</artifactId>
92+
<version>4.5.2</version>
93+
<scope>compile</scope>
94+
</dependency>
95+
<dependency>
96+
<groupId>org.apache.httpcomponents</groupId>
97+
<artifactId>httpcore</artifactId>
98+
<version>4.4.4</version>
99+
<scope>compile</scope>
100+
</dependency>
81101
<!-- should match the gson version used by cdap-->
82102
<dependency>
83103
<groupId>com.google.code.gson</groupId>

src/main/java/io/cdap/plugin/sendgrid/common/SendGridClient.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import io.cdap.plugin.sendgrid.common.helpers.ObjectInfo;
2727
import io.cdap.plugin.sendgrid.common.objects.BasicResult;
2828
import io.cdap.plugin.sendgrid.common.objects.SendGridAuthType;
29-
import io.cdap.plugin.sendgrid.source.batch.SendGridBatchSourceConfig;
29+
import io.cdap.plugin.sendgrid.source.batch.SendGridBatchConfig;
3030

3131
import java.io.IOException;
3232
import java.lang.reflect.ParameterizedType;
@@ -43,6 +43,7 @@
4343
* SendGrid Client
4444
*/
4545
public class SendGridClient {
46+
private static final String CONNECTION_CHECK_ENDPOINT = "alerts";
4647

4748
/**
4849
* Extended version of the original SendGrid API wrapper with added support of basic auth
@@ -77,7 +78,7 @@ private SendGridClient() {
7778
gson = new GsonBuilder().create();
7879
}
7980

80-
public SendGridClient(SendGridBatchSourceConfig config) {
81+
public SendGridClient(SendGridBatchConfig config) {
8182
this();
8283
if (config.getAuthType() == SendGridAuthType.API) {
8384
sendGrid = new SendGridAPIClient(config.getSendGridApiKey());
@@ -129,6 +130,14 @@ private String makeApiRequest(Method method, String endpoint, @Nullable Map<Stri
129130
return response.getBody();
130131
}
131132

133+
/**
134+
* Checks connection to the service by testing API endpoint, in case
135+
* of exception would be generated {@link IOException}
136+
*/
137+
public void checkConnection() throws IOException {
138+
makeApiRequest(Method.GET, CONNECTION_CHECK_ENDPOINT, null);
139+
}
140+
132141
/**
133142
* Verify all incoming arguments for the query object
134143
*

src/main/java/io/cdap/plugin/sendgrid/common/config/BaseSourceConfig.java renamed to src/main/java/io/cdap/plugin/sendgrid/common/config/BaseConfig.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
/**
4040
* Provides all required configuration for reading SendGrid information
4141
*/
42-
public class BaseSourceConfig extends ReferencePluginConfig {
42+
public class BaseConfig extends ReferencePluginConfig {
4343
public static final String PROPERTY_AUTH_TYPE = "authType";
4444
public static final String PROPERTY_SENDGRID_API_KEY = "sendGridApiKey";
4545
public static final String PROPERTY_AUTH_USERNAME = "username";
@@ -134,10 +134,17 @@ public class BaseSourceConfig extends ReferencePluginConfig {
134134
*
135135
* @param referenceName uniquely identify source/sink for lineage, annotating metadata, etc.
136136
*/
137-
public BaseSourceConfig(String referenceName) {
137+
public BaseConfig(String referenceName) {
138138
super(referenceName);
139139
}
140140

141+
/**
142+
* Validate configuration for the issues
143+
*/
144+
protected void validate(FailureCollector failureCollector) {
145+
new BaseConfigValidator(failureCollector, this).validate();
146+
}
147+
141148
/**
142149
* Fetches all fields selected by the user
143150
*/
@@ -223,10 +230,6 @@ public Map<String, String> getRequestArguments() {
223230
return builder.build();
224231
}
225232

226-
public void validate(FailureCollector failureCollector) {
227-
228-
}
229-
230233
/**
231234
* Client authentication way
232235
*/
@@ -271,4 +274,11 @@ public String getStartDate() {
271274
public String getEndDate() {
272275
return endDate;
273276
}
277+
278+
public List<String> getDataSourceTypes() {
279+
if (!Strings.isNullOrEmpty(dataSourceTypes)) {
280+
return Arrays.asList(dataSourceTypes.split(","));
281+
}
282+
return Collections.emptyList();
283+
}
274284
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright © 2019 Cask Data, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package io.cdap.plugin.sendgrid.common.config;
17+
18+
import com.google.common.base.Strings;
19+
import io.cdap.cdap.etl.api.FailureCollector;
20+
import io.cdap.cdap.etl.api.validation.ValidationFailure;
21+
import io.cdap.plugin.sendgrid.common.SendGridClient;
22+
import io.cdap.plugin.sendgrid.common.helpers.ObjectHelper;
23+
import io.cdap.plugin.sendgrid.common.helpers.ObjectInfo;
24+
import io.cdap.plugin.sendgrid.common.objects.DataSourceGroupType;
25+
import io.cdap.plugin.sendgrid.common.objects.SendGridAuthType;
26+
27+
import java.io.IOException;
28+
import java.util.List;
29+
import java.util.stream.Collectors;
30+
31+
/**
32+
* Validates configuration
33+
*/
34+
public class BaseConfigValidator {
35+
protected FailureCollector failureCollector;
36+
protected SendGridClient client = null;
37+
private BaseConfig config;
38+
39+
public BaseConfigValidator(FailureCollector failureCollector, BaseConfig config) {
40+
this.failureCollector = failureCollector;
41+
this.config = config;
42+
}
43+
44+
private void checkAuthType() {
45+
try {
46+
config.getAuthType();
47+
} catch (IllegalArgumentException e) {
48+
failureCollector.addFailure(String.format("Wrong authentication method selected: %s", e.getMessage()), null)
49+
.withConfigProperty(BaseConfig.PROPERTY_AUTH_TYPE);
50+
}
51+
}
52+
53+
private void checkAuthData() {
54+
boolean tryToLogin = true;
55+
56+
switch (config.getAuthType()) {
57+
case BASIC:
58+
if (Strings.isNullOrEmpty(config.getAuthUserName())) {
59+
failureCollector.addFailure("User name is not set", null)
60+
.withConfigProperty(BaseConfig.PROPERTY_AUTH_USERNAME);
61+
tryToLogin = false;
62+
}
63+
if (Strings.isNullOrEmpty(config.getAuthPassword())) {
64+
failureCollector.addFailure("Password is not set", null)
65+
.withConfigProperty(BaseConfig.PROPERTY_AUTH_PASSWORD);
66+
tryToLogin = false;
67+
}
68+
69+
if (tryToLogin) {
70+
client = new SendGridClient(config.getAuthUserName(), config.getAuthPassword());
71+
}
72+
break;
73+
case API:
74+
if (Strings.isNullOrEmpty(config.getSendGridApiKey())) {
75+
failureCollector.addFailure("API Key is not set", null)
76+
.withConfigProperty(BaseConfig.PROPERTY_SENDGRID_API_KEY);
77+
tryToLogin = false;
78+
}
79+
80+
if (tryToLogin) {
81+
client = new SendGridClient(config.getSendGridApiKey());
82+
}
83+
break;
84+
}
85+
}
86+
87+
private void checkCategoriesSelection() {
88+
if (config.getDataSourceTypes().isEmpty()) {
89+
failureCollector.addFailure("Object categories are not set", null)
90+
.withConfigProperty(BaseConfig.PROPERTY_DATA_SOURCE_TYPES);
91+
}
92+
93+
config.getDataSourceTypes()
94+
.forEach(x -> {
95+
try {
96+
DataSourceGroupType.fromString(x);
97+
} catch (IllegalStateException e) {
98+
failureCollector.addFailure(
99+
String.format("Unknown '%s' data source type: %s", x , e.getMessage()), null)
100+
.withStacktrace(e.getStackTrace());
101+
}
102+
});
103+
}
104+
105+
private void checkObjectsSelection() {
106+
List<ObjectInfo> objects = config.getDataSource().stream()
107+
.filter(x -> !Strings.isNullOrEmpty(x))
108+
.map(ObjectHelper::getObjectInfo)
109+
.collect(Collectors.toList());
110+
List<DataSourceGroupType> categories = config.getDataSourceTypes().stream()
111+
.map(DataSourceGroupType::fromString)
112+
.collect(Collectors.toList());
113+
114+
categories.forEach(category -> {
115+
if (objects.stream().noneMatch(x -> x.getDataSourceGroupType() == category)) {
116+
failureCollector.addFailure(
117+
String.format("No objects selected for the category: %s", category.name()), null)
118+
.withConfigProperty(BaseConfig.PROPERTY_DATA_SOURCE);
119+
}
120+
});
121+
}
122+
123+
private void checkFieldSelection() {
124+
List<ObjectInfo> objects = config.getDataSource().stream()
125+
.map(ObjectHelper::getObjectInfo)
126+
.collect(Collectors.toList());
127+
128+
List<String> fields = config.getFields();
129+
130+
objects.forEach(object -> {
131+
if (object.getFieldsDefinitions(fields).isEmpty()) {
132+
failureCollector.addFailure(
133+
String.format("No fields selected for object '%s'", object.getCdapObjectName()), null)
134+
.withConfigProperty(BaseConfig.PROPERTY_DATA_SOURCE_FIELDS);
135+
}
136+
});
137+
}
138+
139+
private void checkClientConnectivity() {
140+
try {
141+
client.checkConnection();
142+
} catch (IOException e) {
143+
ValidationFailure failure = failureCollector
144+
.addFailure(String.format("Issues with API connectivity: %s", e.getMessage()), "Check login settings")
145+
.withStacktrace(e.getStackTrace());
146+
147+
if (config.getAuthType() == SendGridAuthType.BASIC) {
148+
failure
149+
.withConfigProperty(BaseConfig.PROPERTY_AUTH_USERNAME)
150+
.withConfigProperty(BaseConfig.PROPERTY_AUTH_PASSWORD);
151+
}
152+
if (config.getAuthType() == SendGridAuthType.API) {
153+
failure.withConfigProperty(BaseConfig.PROPERTY_SENDGRID_API_KEY);
154+
}
155+
}
156+
}
157+
158+
public void validate() {
159+
client = null;
160+
161+
checkAuthType();
162+
checkAuthData();
163+
checkCategoriesSelection();
164+
checkObjectsSelection();
165+
checkFieldSelection();
166+
167+
if (client != null) { // client could be not constructed, if any of checkAuth tests failed
168+
checkClientConnectivity();
169+
}
170+
}
171+
172+
173+
}

src/main/java/io/cdap/plugin/sendgrid/common/objects/DataSourceGroupType.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
* Entities groups
2222
*/
2323
public enum DataSourceGroupType {
24-
Marketing("Marketing Campaign Objects"),
25-
Stats("Statistic Objects"),
26-
Suppressions("Suppression Objects");
24+
Marketing("MarketingCampaign"),
25+
Stats("Statistic"),
26+
Suppressions("suppression");
2727

2828
private String value;
2929

src/main/java/io/cdap/plugin/sendgrid/common/objects/stats/AdvancedStats.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.google.common.collect.ImmutableMap;
1919
import com.google.gson.annotations.SerializedName;
2020
import io.cdap.cdap.api.data.schema.Schema;
21-
import io.cdap.plugin.sendgrid.common.config.BaseSourceConfig;
21+
import io.cdap.plugin.sendgrid.common.config.BaseConfig;
2222
import io.cdap.plugin.sendgrid.common.helpers.BaseObject;
2323
import io.cdap.plugin.sendgrid.common.helpers.IBaseObject;
2424
import io.cdap.plugin.sendgrid.common.helpers.ObjectDefinition;
@@ -37,7 +37,7 @@
3737
Group = DataSourceGroupType.Stats,
3838
APIUrl = "geo/stats",
3939
RequiredArguments = {
40-
BaseSourceConfig.PROPERTY_START_DATE
40+
BaseConfig.PROPERTY_START_DATE
4141
}
4242
)
4343
public class AdvancedStats extends BaseObject implements IBaseObject {

src/main/java/io/cdap/plugin/sendgrid/common/objects/stats/CategoryStats.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.google.common.collect.ImmutableMap;
1919
import com.google.gson.annotations.SerializedName;
2020
import io.cdap.cdap.api.data.schema.Schema;
21-
import io.cdap.plugin.sendgrid.common.config.BaseSourceConfig;
21+
import io.cdap.plugin.sendgrid.common.config.BaseConfig;
2222
import io.cdap.plugin.sendgrid.common.helpers.BaseObject;
2323
import io.cdap.plugin.sendgrid.common.helpers.IBaseObject;
2424
import io.cdap.plugin.sendgrid.common.helpers.ObjectDefinition;
@@ -37,8 +37,8 @@
3737
Group = DataSourceGroupType.Stats,
3838
APIUrl = "categories/stats",
3939
RequiredArguments = {
40-
BaseSourceConfig.PROPERTY_START_DATE,
41-
BaseSourceConfig.PROPERTY_STAT_CATEGORIES
40+
BaseConfig.PROPERTY_START_DATE,
41+
BaseConfig.PROPERTY_STAT_CATEGORIES
4242
}
4343
)
4444
public class CategoryStats extends BaseObject implements IBaseObject {

src/main/java/io/cdap/plugin/sendgrid/common/objects/stats/GlobalStats.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.google.common.collect.ImmutableMap;
1919
import com.google.gson.annotations.SerializedName;
2020
import io.cdap.cdap.api.data.schema.Schema;
21-
import io.cdap.plugin.sendgrid.common.config.BaseSourceConfig;
21+
import io.cdap.plugin.sendgrid.common.config.BaseConfig;
2222
import io.cdap.plugin.sendgrid.common.helpers.BaseObject;
2323
import io.cdap.plugin.sendgrid.common.helpers.IBaseObject;
2424
import io.cdap.plugin.sendgrid.common.helpers.ObjectDefinition;
@@ -37,7 +37,7 @@
3737
Group = DataSourceGroupType.Stats,
3838
APIUrl = "stats",
3939
RequiredArguments = {
40-
BaseSourceConfig.PROPERTY_START_DATE
40+
BaseConfig.PROPERTY_START_DATE
4141
}
4242
)
4343
public class GlobalStats extends BaseObject implements IBaseObject {

src/main/java/io/cdap/plugin/sendgrid/source/batch/SendGridBatchSourceConfig.java renamed to src/main/java/io/cdap/plugin/sendgrid/source/batch/SendGridBatchConfig.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
*/
1616
package io.cdap.plugin.sendgrid.source.batch;
1717

18-
import io.cdap.plugin.sendgrid.common.config.BaseSourceConfig;
18+
import io.cdap.cdap.etl.api.FailureCollector;
19+
import io.cdap.plugin.sendgrid.common.config.BaseConfig;
1920

2021
/**
2122
* SendGrid Source Plugin configuration
2223
*/
23-
public class SendGridBatchSourceConfig extends BaseSourceConfig {
24-
public SendGridBatchSourceConfig(String referenceName) {
24+
public class SendGridBatchConfig extends BaseConfig {
25+
public SendGridBatchConfig(String referenceName) {
2526
super(referenceName);
2627
}
28+
29+
public void validate(FailureCollector failureCollector) {
30+
new SendGridBatchConfigValidator(failureCollector, this).validate();
31+
}
2732
}

0 commit comments

Comments
 (0)