22
22
import io .cdap .cdap .api .annotation .Name ;
23
23
import io .cdap .cdap .etl .api .FailureCollector ;
24
24
import io .cdap .plugin .common .IdUtils ;
25
+ import io .cdap .plugin .common .KeyValueListParser ;
25
26
import io .cdap .plugin .common .ReferencePluginConfig ;
26
27
28
+ import java .util .Arrays ;
29
+ import java .util .HashMap ;
30
+ import java .util .Map ;
31
+ import javax .annotation .Nullable ;
32
+
27
33
/**
28
34
* Basic config class for Elasticsearch plugin.
29
35
*/
30
36
public abstract class BaseElasticsearchConfig extends ReferencePluginConfig {
37
+
31
38
public static final String INDEX_NAME = "es.index" ;
32
39
public static final String TYPE_NAME = "es.type" ;
33
40
public static final String HOST = "es.host" ;
41
+ public static final String ADDITIONAL_PROPERTIES = "additionalProperties" ;
34
42
35
43
private static final String HOST_DESCRIPTION = "The hostname and port for the Elasticsearch instance; " +
36
- "for example, localhost:9200." ;
44
+ "for example, localhost:9200 or https://remote.region.gcp.cloud.es.io:9243 ." ;
37
45
private static final String INDEX_DESCRIPTION = "The name of the index to query." ;
38
46
private static final String TYPE_DESCRIPTION = "The name of the type where the data is stored." ;
47
+ private static final String ADDITIONAL_PROPERTIES_DESCRIPTION = "Additional client properties for ES-Hadoop" ;
39
48
40
49
@ Name (HOST )
41
50
@ Description (HOST_DESCRIPTION )
@@ -52,11 +61,19 @@ public abstract class BaseElasticsearchConfig extends ReferencePluginConfig {
52
61
@ Macro
53
62
private final String type ;
54
63
55
- public BaseElasticsearchConfig (String referenceName , String hostname , String index , String type ) {
64
+ @ Nullable
65
+ @ Name (ADDITIONAL_PROPERTIES )
66
+ @ Description (ADDITIONAL_PROPERTIES_DESCRIPTION )
67
+ @ Macro
68
+ private final String additionalProperties ;
69
+
70
+ public BaseElasticsearchConfig (String referenceName , String hostname , String index , String type ,
71
+ String additionalProperties ) {
56
72
super (referenceName );
57
73
this .hostname = hostname ;
58
74
this .index = index ;
59
75
this .type = type ;
76
+ this .additionalProperties = additionalProperties ;
60
77
}
61
78
62
79
public String getHostname () {
@@ -75,6 +92,28 @@ public String getResource() {
75
92
return String .format ("%s/%s" , index , type );
76
93
}
77
94
95
+ @ Nullable
96
+ public String getAdditionalProperties () {
97
+ return additionalProperties ;
98
+ }
99
+
100
+ public Map <String , String > getAdditionalPropertiesMap () {
101
+ Map <String , String > propertiesMap = new HashMap <>();
102
+ if (additionalProperties == null || additionalProperties .trim ().isEmpty ()) {
103
+ return propertiesMap ;
104
+ }
105
+
106
+ KeyValueListParser parser = new KeyValueListParser ("\n " , "=" );
107
+ parser .parse (additionalProperties ).forEach (kv -> {
108
+ if (kv .getKey ().trim ().isEmpty ()) {
109
+ throw new IllegalArgumentException ("Key should not be empty" );
110
+ } else {
111
+ propertiesMap .put (kv .getKey ().trim (), kv .getValue ().trim ());
112
+ }
113
+ });
114
+ return propertiesMap ;
115
+ }
116
+
78
117
public void validate (FailureCollector collector ) {
79
118
IdUtils .validateReferenceName (referenceName , collector );
80
119
@@ -93,20 +132,33 @@ public void validate(FailureCollector collector) {
93
132
if (!containsMacro (TYPE_NAME ) && Strings .isNullOrEmpty (type )) {
94
133
collector .addFailure ("Type must be specified." , null ).withConfigProperty (TYPE_NAME );
95
134
}
135
+
136
+ if (!containsMacro (ADDITIONAL_PROPERTIES )) {
137
+ try {
138
+ getAdditionalPropertiesMap ();
139
+ } catch (Exception e ) {
140
+ collector .addFailure ("Additional properties must be a valid KV map" , null )
141
+ .withConfigProperty (ADDITIONAL_PROPERTIES ).withStacktrace (e .getStackTrace ());
142
+ }
143
+ }
96
144
}
97
145
98
146
private void validateHost (FailureCollector collector ) {
99
147
String [] hostParts = hostname .split (":" );
100
148
101
149
// Elasticsearch Hadoop does not support IPV6 https://github.com/elastic/elasticsearch-hadoop/issues/1105
102
- if (hostParts .length != 2 ) {
150
+ // Length range [2,3] allowed for https hosts
151
+ if ((hostParts .length < 2 ) || (hostParts .length > 3 ) || (hostParts .length == 3
152
+ && !(hostParts [0 ].equalsIgnoreCase ("https" ) || hostParts [0 ].equalsIgnoreCase ("http" )))) {
153
+
103
154
collector .addFailure (
104
155
"Invalid format of hostname" ,
105
- "Hostname and port must be specified for the Elasticsearch instance, for example: 'localhost:9200'"
156
+ "Hostname and port must be specified for the Elasticsearch instance, " +
157
+ "for example: 'localhost:9200' or https://remote.region.gcp.cloud.es.io:9243"
106
158
).withConfigProperty (HOST );
107
159
} else {
108
- String host = hostParts [ 0 ] ;
109
- String port = hostParts [1 ];
160
+ String host = String . join ( ":" , Arrays . asList ( hostParts ). subList ( 0 , hostParts . length - 1 )) ;
161
+ String port = hostParts [hostParts . length - 1 ];
110
162
111
163
if (host .isEmpty ()) {
112
164
collector .addFailure ("Host should not be empty." , null )
0 commit comments