Merge branch 'master' into immutable_set_be_gone

Original commit: elastic/x-pack-elasticsearch@faa212ffbd
This commit is contained in:
Nik Everett 2015-09-25 10:47:16 -04:00
commit c6e7c9c1d6
59 changed files with 322 additions and 1182 deletions

View File

@ -1,6 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -1,18 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nullable=org.elasticsearch.common.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.lineSplit=140
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4

File diff suppressed because one or more lines are too long

View File

@ -43,7 +43,7 @@ public class MarvelSettingTests extends ESTestCase {
String description = randomAsciiOfLength(20);
TimeValue defaultValue = null;
if (randomBoolean()) {
defaultValue = randomTimeValue();
defaultValue = randomParsedTimeValue();
}
boolean dynamic = randomBoolean();
@ -59,11 +59,11 @@ public class MarvelSettingTests extends ESTestCase {
setting.onRefresh(settingsBuilder().put(name, 15000L).build());
assertThat(setting.getValue().millis(), equalTo(15000L));
TimeValue updated = randomTimeValue();
TimeValue updated = randomParsedTimeValue();
setting.onRefresh(settingsBuilder().put(name, updated.toString()).build());
assertThat(setting.getValue().millis(), equalTo(updated.millis()));
updated = randomTimeValue();
updated = randomParsedTimeValue();
setting.onRefresh(settingsBuilder().put(name, updated.toString()).build());
assertThat(setting.getValue().millis(), equalTo(updated.millis()));
}
@ -130,7 +130,7 @@ public class MarvelSettingTests extends ESTestCase {
assertArrayEquals(setting.getValue(), updated);
}
private TimeValue randomTimeValue() {
private TimeValue randomParsedTimeValue() {
return TimeValue.parseTimeValue(randomFrom("10ms", "1.5s", "1.5m", "1.5h", "1.5d", "1000d"), null, getClass().getSimpleName() + ".unit");
}

View File

@ -24,13 +24,13 @@ import static org.hamcrest.Matchers.*;
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 1)
public class MarvelSettingsTests extends ESIntegTestCase {
private final TimeValue startUp = randomTimeValue();
private final TimeValue interval = randomTimeValue();
private final TimeValue indexStatsTimeout = randomTimeValue();
private final TimeValue startUp = randomParsedTimeValue();
private final TimeValue interval = randomParsedTimeValue();
private final TimeValue indexStatsTimeout = randomParsedTimeValue();
private final String[] indices = randomStringArray();
private final TimeValue clusterStateTimeout = randomTimeValue();
private final TimeValue clusterStatsTimeout = randomTimeValue();
private final TimeValue recoveryTimeout = randomTimeValue();
private final TimeValue clusterStateTimeout = randomParsedTimeValue();
private final TimeValue clusterStatsTimeout = randomParsedTimeValue();
private final TimeValue recoveryTimeout = randomParsedTimeValue();
private final Boolean recoveryActiveOnly = randomBoolean();
private final String[] collectors = randomStringArray();
private final TimeValue licenseGracePeriod = randomExpirationDelay();
@ -99,7 +99,7 @@ public class MarvelSettingsTests extends ESIntegTestCase {
Object updated = null;
Settings.Builder transientSettings = Settings.builder();
if (setting instanceof MarvelSetting.TimeValueSetting) {
updated = randomTimeValue();
updated = randomParsedTimeValue();
transientSettings.put(setting.getName(), updated);
} else if (setting instanceof MarvelSetting.BooleanSetting) {
@ -156,7 +156,7 @@ public class MarvelSettingsTests extends ESIntegTestCase {
return requestBuilder;
}
private TimeValue randomTimeValue() {
private TimeValue randomParsedTimeValue() {
return TimeValue.parseTimeValue(randomFrom("30m", "1h", "3h", "5h", "7h", "10h", "1d"), null, getClass().getSimpleName());
}
@ -171,6 +171,6 @@ public class MarvelSettingsTests extends ESIntegTestCase {
}
private TimeValue randomExpirationDelay() {
return randomBoolean() ? randomTimeValue() : TimeValue.timeValueHours(randomIntBetween(-10, 10) * 24);
return randomBoolean() ? randomParsedTimeValue() : TimeValue.timeValueHours(randomIntBetween(-10, 10) * 24);
}
}

View File

@ -1,6 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -1,18 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nullable=org.elasticsearch.common.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.lineSplit=140
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,7 @@ import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.indices.cache.query.terms.TermsLookup;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.Template;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
@ -77,11 +78,7 @@ public class ShieldCachePermissionTests extends ShieldIntegTestCase {
@Test
public void testThatTermsFilterQueryDoesntLeakData() {
SearchResponse response = client().prepareSearch("data").setTypes("a").setQuery(QueryBuilders.constantScoreQuery(
QueryBuilders.termsLookupQuery("token")
.lookupIndex("tokens")
.lookupType("tokens")
.lookupId("1")
.lookupPath("tokens")))
QueryBuilders.termsLookupQuery("token", new TermsLookup("tokens", "tokens", "1", "tokens"))))
.execute().actionGet();
assertThat(response.isTimedOut(), is(false));
assertThat(response.getHits().hits().length, is(1));
@ -89,11 +86,7 @@ public class ShieldCachePermissionTests extends ShieldIntegTestCase {
// Repeat with unauthorized user!!!!
try {
response = client().prepareSearch("data").setTypes("a").setQuery(QueryBuilders.constantScoreQuery(
QueryBuilders.termsLookupQuery("token")
.lookupIndex("tokens")
.lookupType("tokens")
.lookupId("1")
.lookupPath("tokens")))
QueryBuilders.termsLookupQuery("token", new TermsLookup("tokens", "tokens", "1", "tokens"))))
.putHeader("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER, new SecuredString("changeme".toCharArray())))
.execute().actionGet();
fail("search phase exception should have been thrown! response was:\n" + response.toString());

View File

@ -4,40 +4,7 @@ This document details the steps used to create the certificate and keystore file
== Instructions on generating self-signed certificates
The certificates in this directory have been generated using the following openssl configuration and commands.
OpenSSL Configuration File
[source,shell]
-----------------------------------------------------------------------------------------------------------
[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha256 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
#subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
IP.2 = ::2
-----------------------------------------------------------------------------------------------------------
OpenSSL Configuration File is located in this directory as `openssl_config.cnf`.
NOTE: The `alt_names` section provides the Subject Alternative Names for each certificate. This is necessary for testing
with hostname verification enabled.

View File

@ -0,0 +1,35 @@
[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha256 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = localhost.localdomain
DNS.3 = localhost4
DNS.4 = localhost4.localdomain4
DNS.5 = localhost6
DNS.6 = localhost6.localdomain6
IP.1 = 127.0.0.1
IP.2 = ::1

View File

@ -1,19 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDATCCAemgAwIBAgIJAKpUXNetXSgGMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
BAoTB1Vua25vd24wHhcNMTQxMjE2MTY0OTE1WhcNMTgxMjE1MTY0OTE1WjASMRAw
DgYDVQQKEwdVbmtub3duMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
ud/8Cbdao73CWXX4hP5yIOAvxOz1CSJN4RukrZz8EDqf2ZO5dcsceA0hSNbjjuxI
6sck8BlbAWGRLpg0RK6ObzyrQi6O56NxQlAazl95dE5to2rD4rcoWzp8uncfXjH/
6ix1z1Ph8HUJyWpZrciZa1KEotyElUhoVRkI8n956ayi6VFejRQOVFcByozr8jyM
bgnvVUnaitkAipohNiOybrSgz/rNI+fZykoOz0OcmNGJ4saDuaIn/EW8ZazUUxPL
Z7CsuLe3a7cIe4aK7vgSGP67EDX9ORTakABwMhmoPPNh2oroRrnJQmEQcbAFnIgO
qt0xP/pldehgPBLBt9SHKQIDAQABo1owWDAJBgNVHRMEAjAAMB0GA1UdDgQWBBT/
avMSDSZe+l3YAR2lvD86cET4/TAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGH
EAAAAAAAAAAAAAAAAAAAAAIwDQYJKoZIhvcNAQELBQADggEBAJMF8pEdDAkJlQ8g
E3BC41JcmkXYZbv7uieF7088kW13UzJhKMS1c0GOyMM0QKqj+Xt7WMcv0TjNPGtk
xs4kmcgyQzITdbu3Wri9xARdgtl2roC/KUzqygLk6h+yKECpDBEMRSgR9eO+Kha2
EJo0kr4IW4hqKrhncxM7YKKjSMgGcD+QdZNAQkY0Jk7JvzDzvGxiBYzJbHB3Ye6c
cb/Uz5ydk0unCACOlrPjOLRBY4EW08tCgFJBUSTjWJjSnrJxvo6kr/dFq2YksfUs
c6a3e6vUoG5JXqIK8iIn3MnF5RLwQjMG0KSUCMRnH8wkzWx2yPv+urvUixIs+vbV
hTWLIhU=
MIIDizCCAnOgAwIBAgIJANif+/9AeRBYMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV
BAMTGXRlc3RjbGllbnQtY2xpZW50LXByb2ZpbGUwHhcNMTUwOTIzMTg1MjU0WhcN
MTkwOTIyMTg1MjU0WjAkMSIwIAYDVQQDExl0ZXN0Y2xpZW50LWNsaWVudC1wcm9m
aWxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g9jTDeAZMjXygm4
Cb9CkBhSGN738ZOBiTGDH0q/3inE/qKJj/SF6RjHrVx5v9QUlqVTBX/NPd0VSFy7
jbYtab8mlaYEAhatYQhHlEjcre1hjK3MW2oHhk+T9ScnIBeArBjUSUzwPAUM8FOj
0qGSK6QifrCf/5dQyq9D1WynwhGwUqp3WcZEvvaEl66QnBugViY7JRsuWOfIiJ7j
xkFv74Qm3yfCpQR+5TPAWd2ipRZZinwn9M0u0txiffZo7jemdpK5aiNAgJCGn/Sw
jlOzFU5pKxIIHeaR3rLWZ4P0WgMu+kqVPoy66UKBA6kXK4eMk1Wla7dG1gtp+OmQ
TQGqhwIDAQABo4G/MIG8MAkGA1UdEwQCMAAwHQYDVR0OBBYEFGgAgQUFrcvEOeed
swWf+D5DRoj9MIGPBgNVHREEgYcwgYSCCWxvY2FsaG9zdIIVbG9jYWxob3N0Lmxv
Y2FsZG9tYWluggpsb2NhbGhvc3Q0ghdsb2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIK
bG9jYWxob3N0NoIXbG9jYWxob3N0Ni5sb2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAA
AAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggEBAKrKuUTmZ3WymiG6jRhLA5DA
36k7Hey8rvHZ6wbdnUseO+JJbItGEoEd0Js2syjghOnMf+M686prv0tWpaqA3ySh
uEcKSwy063eMmmTPXR9HfEK/QkdfC6otOvR/elgs1t0R45JFbHWSS1tJLOU/HU2i
3jwqy8Gwp+XJG9yrwC4OsJ1pAp7vCIoXrcq6glueiq9vjdAMYCtlrNIlDhmB+rYD
K8mf4S1AygSsZNUmh04oj8kBRacH4vdoKYkxvixPvo1F5VaoJcr+hh2xL4AyuqLc
gdoJmOv6Fk2UCUI2aI4nn0pXwkyOlx0t8B3Hp/TZY2Yn0x+uIIkKGJRm0CuKzNQ=
-----END CERTIFICATE-----

View File

@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,02BA9C3E433F0711
M3Ds1K8/cp5v9BKj9SstoXWlyj+CmasLfvPlz6O5Ootdai/wTirhxyAcYcsgjuQA
FIMuQiAaKC+W/DOP52+ilY3FZKw09DptdkaU7IFvSQvJ5SeiJIGLZ9REUWIPwRKV
qCHpKFCS4//mitnykjSu2HhTM+BjbXuytLJtxFJuodr8YhJGgtwfETAmbVlwWG3M
mhEsfdr0kOJGwT/z3dZbCxnGkjOY1FZCdMU/ggeYx93NP0c4yzNU6/A0idZRMlHE
BuSIkDhn3BXxgxYxTOgHzCkxaZ0T7kNv0MvTXrrcQf2WrMaG1FfTzCzF78YDBn7+
kg5HI8wfxjGjDTnHH9KSuN5gi14DiEEUN45Ba3ChH75SjGwBbUjnHsGIp6Ch8mh8
5ZgldgUOff0atEBaMpvoZAzxGbY5PhC5/Pfiq+enzvmICxszFNIRMhhLxWWBWuH9
v04OOKZJ4v+ygZHvPJEFNc/XznGb39ELn4Y6P26fqNfPmv5/yHcenQPNZgGkKQEJ
SYTPxct+yDi3lul1WBPrvZwCOAjUtcCf4tBC6uOqlRjd7VREk5hKUlXTtxJLbaoB
FH1VKn9xZITBqk3g292KGbpZsGP5HtYAbB/gJUcOXZZbr8blMmpeIXXFWfPbvUcv
d1fokqHSrlclNt+h2pENqjJTc2iKKKlkNY0ol+cDej7fOgNH0sNOjuESrofdaXfa
4CPuvMxeQFKnjQFBLM14CFUyseZsAqnLjneUnk5qTPE5twCN0pkJx0y095pEGdrF
2UQ4HfdghnKxWQK50iGUhCgBfqeI3O3cfi76ZdeJYM+7CluGNb/0sybjF6kNiAME
m5PfaSXk7A+a/FteFThW52E8W8Sekf2/lOMdbdQa26/oUfcMWzBj+aMcJBwcOaq4
lIY6IPHySQIakLGCLLOkYHAG+Kp8AldjcwfpOZ3Jk1HrjOmx9CfonXvdVQmS2BQZ
8+V2ECd0uw9EbD+i4VIIHy6H1a57W9gikshXsv4K5vQsl0s6GjbioN1JFFC78XKS
XohDMDmR2Ty3LU9TLoS9K2fLcgtoJmnEtJ1cs5Cw9+T1s+ILFgoBTXzePnDKK78T
4uNw7a8CRAKW++dHtwHEnHOIDJ0rx+4Y+V7e5Cr0nT4Idv5P9xe9knTghb34vwBw
SBfEn0sCQoly4DGsKlPz8xhLRCX7euXsbPcTy3owpTFywJsfjR5e/jtxa6C5NmNI
LmGJb6TpsAl9mULfSRlGjynqU9T0EzOdcbPs8z1cLFQl7QRi63tlZ9jWh+7eV+dR
NaN6f0jY0me0D7OzvoD19e3ESFARV7MGQ5U0OaZOAcLdx3CYjs777AQ1S2q6ra+p
gr4oqenWqYkbY8/z8AALiWPO59Rl00GcUJqwYXlJANCtK4ikwQPG2+YIYrclBW/d
ZQplHShy0AayYPguLI9ts0XLulIrcsJ0zlEDPf3b8+Gr6yONiYpOtA0ZtwE3w+Q5
5byhoYoBQPtLXyLff31ozRs/MhJd8+gIIReKSE5sGMwbVX2ZfjWOXzDHp6+CQIKD
OhIfgnyG6tPQ2N4DhSrE/cEITPlSOv55NUnLQUCgfAHvAslgWwmVDk1ikznij/Zj
-----END RSA PRIVATE KEY-----

View File

@ -1,21 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDcTCCAlmgAwIBAgIJANA/+zUU47fOMA0GCSqGSIb3DQEBCwUAMEoxDDAKBgNV
MIID1zCCAr+gAwIBAgIJALnUl/KSS74pMA0GCSqGSIb3DQEBCwUAMEoxDDAKBgNV
BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEiMCAGA1UEAxMZRWxhc3Rp
Y3NlYXJjaCBUZXN0IENsaWVudDAeFw0xNDEyMTYxNzAyNTRaFw0xODEyMTUxNzAy
NTRaMEoxDDAKBgNVBAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEiMCAG
Y3NlYXJjaCBUZXN0IENsaWVudDAeFw0xNTA5MjMxODUyNTVaFw0xOTA5MjIxODUy
NTVaMEoxDDAKBgNVBAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEiMCAG
A1UEAxMZRWxhc3RpY3NlYXJjaCBUZXN0IENsaWVudDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBALceMGq3C3QP6uuCE/93MlwDP3NBVwl5eNL3JvygwQoU
YpoABTU51+3JWjHkWxMbinUFEQV67EMa+5Uja8m39MoHC2hlTuECufe17bAFN23I
SE/x8qaBPECvjR1Rf3Dt+rfJ7/n76aObIt7exsR1uxB/O2eRMNGXZSCsQrQy+n/o
T45gFDkY1CeMthsUxj4TkmeHK+wcDx00Te1mfA4J3Ef5ykIxAwDJxEBIaqGAv077
+02RdG1IHGEvJeTGwZ+GFem9U8zF3UVBX/jyqHY82YyBaXrwjlhDz4dmHVqTVQYC
Qn/SkrQyJknggnWCrCoGS31GfKyFbmrUWjhAtVkreRkCAwEAAaNaMFgwCQYDVR0T
BAIwADAdBgNVHQ4EFgQU4QdRaaIGD6uyQk/WiwEtExBI7hgwLAYDVR0RBCUwI4IJ
bG9jYWxob3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAACMA0GCSqGSIb3DQEBCwUA
A4IBAQAexhtJBZ2jQrJ1M7HRFCFRVP6oi/5D139/0t8qG9KL9oQXlY//gQweSPk9
gCPywfQjBfY6Fck2iliCw6YR3K/Bax9lOX/rKJ/jWrcUUBKzP9ap8ijKa/1EJchp
VVf7M2g7V00pSR63fl+EnMzv8H/uTK4BMWiE9sl01oK/kyVDR/wd/GktnQpZYF5B
5FvuMi2ocM+hSpbejLVi4yW6/wN6rcjofon/u3ngzicwou59r99IavlW/qk5DHbI
HD2pK4tOqQX06pzdc8MHKQ16JxSt3dk/aljmvDUf93e/KNI9RSoZpydBqXlpaACi
52lEcHwQJVoe6L5VdHc6090U09K7
BQADggEPADCCAQoCggEBAMKm+P6vDAff0c6BWKGdhnYoNl9HijLIgfU3d9CQcqKt
wT+yUW3DPSVjIfaLmDIGj6Hl8jTHWPB7ZP4fzhrPi6m4qlRGclJMECBuNASZFiPD
tEDv3msoeqOKQet6n7PZvgpWM7hxYZO4P1aMKJtRsFAdvBAdZUnv0spR5G4UZTHz
SKmMeanIKFkLaD0XVKiLQu9/z9M6roDQeAEoCJ/8JsanG8ih2ymfPHIZuNyYIOrV
ekHN2zU6bnVn8/PCeZSjS6h5xYw+Jl5gzGI/n+F5CZ+THoH8pM4pGp6xRVzpiH12
gvERGwgSIDXdn/+uZZj+4lE7n2ENRSOt5KcOGG99r60CAwEAAaOBvzCBvDAJBgNV
HRMEAjAAMB0GA1UdDgQWBBSSFhBXNp7AaNrHdlgCV0mCEzt7ajCBjwYDVR0RBIGH
MIGEgglsb2NhbGhvc3SCFWxvY2FsaG9zdC5sb2NhbGRvbWFpboIKbG9jYWxob3N0
NIIXbG9jYWxob3N0NC5sb2NhbGRvbWFpbjSCCmxvY2FsaG9zdDaCF2xvY2FsaG9z
dDYubG9jYWxkb21haW42hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3
DQEBCwUAA4IBAQANvAkddfLxn4/BCY4LY/1ET3d7ZRldjFTyjjHRYJ3CYBXWVahM
skLxIcFNca8YjKfXoX8mcK+NQK/dAbGHXqk76yMlkrKjh1OQiZ1YAX5ryYerGrZ9
9N3E9wnbn72bW3iumoLlqmTWlHEpMI0Ql6J75BQLTgKHxCPupVA5sTbWkKwGjXXA
i84rUlzhDJOR8jk3/7ct0iZO8Hk6AWMcNix5Wka3IDGUXuEVevYRlxgVyCxcnZWC
7JWREpar5aIPQFkY6VCEglxwUyXbHZw5T/u6XaKKnS7gz8RiwRh68ddSQJeEHi5e
4onUD7bOCJgfsiUwdiCkDbfN9Yum8OIpmBRs
-----END CERTIFICATE-----

View File

@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,C98A45E4AFC263C2
wLuUEXldYc54r4ryWd6jw6UMGYwn6+ibGKHp4sD92l42lmI2UrCT/Mb/E0O+KMMy
pHgc5/dBWkXgMiqDyLIhHk4kgT40rdw5W5lZkAA4Qt/Yzd+rbscTvzp09zrF6Fll
czgoE7FrvhOKiEOakerTit4pIPYosdX606cpVQE2lq9oZs9HVMcLzdAZj8A/P/4g
fo4X3+zqVYC/LH4n00bhNoeeej2o1lEJ+l9u9hptT2ATXle6pANa83Ldg4OxJyj8
dkR9ahnAMCvYTSjEU7nwmGNPeFX0PIUjJKQivr410cYG104DC30Yy+XrIUfjTVUi
agwlMpHoBq79/ZRUJR3xPLkIGgw4g+RPt45D9eKsEsV4vqy8SFlgaoJ2mKUKleZy
i7D9ouzMKQ3sYE4eQVQ5o3K8ZPn5eozCwCVIp7jGSsuvDpLA9peZSwWPfc5y8JFD
/64usCt1J8Mv/e9NVllC8ZA+ZmDitTiwLZysczpMOaFqqeUbk9EJst38n4nBzRV2
quxvg9W/iveQIydFyftCtNfRkpbp0NCsLz293dBYwZacHsPcY27IBCwXHiICjiAW
q7bnisXsgSaQMhMNRGW9YElZGb7ZWxoIzcyNBisGI8zxn48ObERVOmkOFxY/gs9T
YmpVMliWtmRG6hb6iCh9b7z8THRquxgTGE9ZFBwtLUKg33aubtgAfnUh/Xq2Ue5K
l+ZCqDGEi/FSIjVENUNNntAx/vXeNPbkoGLb/HSJwAh+sjpaLGQ54xixCtE9l3NY
o2QAiZ804KLPaGtbbOv7wPumxQ+8mxG5FN0hTRrsMW9t8pBXw47iMy/T2H21TD5D
E5XbM6kFeBrnsWnZJ2/ieXqDE4SX0tm3WEvZlDg7N7jV8QDM/D3Xdkb/sqJRabMG
tQRgwkLiB+mZ5MAfGLogI2/lOEayrBVz4qYdXojewxY4LtaZ5HiUIlyA9CJelMvD
nS52I6+FpaFhvuZC10qaM9Ph9TNyx+XKRUsPILuDiBRnYiHUKs1qASl5tjn2yyjM
71WSo7A7btOckzhDZdMVf1T472f0LGsRYoQebMhotqCuR7yArZHzTeWB0CjL3tOz
j3QlhKt2E1jx43bSK5tBasd9Bpmn2onvdwu1RRP8cyQBsXJSDy4/8t/g63+C3wod
8VPrlKhK+TenK9EoEqJ2mNuNq+duOjTXfK/7GM5s0BFKv+i2ckpDi1NPckd2gXjF
yUFZhmK6k0WC4jjWloMt+WQpi1rXMEXwCypgTrqWbvD0p6+X3uQmP57L4yHQcZoW
Qcs5GnihJ0DIhw9vYDhBhNo0WY1oBO20nVCN3R/JIpp3uDtg64WvfvMSXzJIPBCY
s+/GM5TtuD6mERDu3+qXxWwiy4PMQRcgjRTMEZ3A4Iv77YfQRkcd6S9qjUUuR/5D
xs+J4ryb1biz9ofW7I+Dbz4SArWSgwcuh14AV9RBv6Rh9m83rjT2K0yvbe/+7hHW
R8nzRMqJcGNGCHmRjA/cwoiv6+k2J/RbCJqnR3RmNex/85XaXBfZwRfHXVbzZQfa
SrFaaNLf1hMwGLAJjIcQRxa3yZbjFXVx1Bp4hh8rKNWaOItjavNtNg==
-----END RSA PRIVATE KEY-----

View File

@ -1,19 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDATCCAemgAwIBAgIJAJeYaRLTW4+8MA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
BAoTB1Vua25vd24wHhcNMTQxMjE2MTY1NTUyWhcNMTgxMjE1MTY1NTUyWjASMRAw
DgYDVQQKEwdVbmtub3duMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
rQJqeEjkzz0VaxzvApx5CFTFNm31tKtYQrs3hKJmuVNBKOmj6NpKN3e/JSp9e9YA
N8cylF5btGGEDQLufWdiwmPcWMH5yFBiMQZqAMPIseO5XSkqIf2QB6VJ676JiwSL
Hi2mfeoX8l8Kor2ZKaoUNQMHBUIupyBWUyXq6d9Xxtq/P2IGtbOABPzxQDjCvwFs
wGZtkDMsYCaMsHlMNBbc1JhX9pKRmbUHCMOnoQpxSJdEbi8radH+6SPRE0Hjf1Sh
eki4l7dpI7Za599ffR5XZXtddPswK3yUDxJ7Ci1WzUeVoj5eeWoPUpSs6vdp671I
ysuklEop7h2h9nTQ4psj7wIDAQABo1owWDAJBgNVHRMEAjAAMB0GA1UdDgQWBBT4
fb9ffBf0NdyQzDzzaQk97cFceDAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGH
EAAAAAAAAAAAAAAAAAAAAAIwDQYJKoZIhvcNAQELBQADggEBAAv4PFpgJnzNm/38
6ps1e8tdMMW+Luoz58UJpax5ysKfFdAkinKiR5YbUIFouLXHUHWvTVOUcUkGRkxy
ge2alErk1ai7xvqGR+GwweoF52yAI/P6fBcStll1ZcjtfRxWyyLceBkctIbftosb
+l6IfWNlScR71R/BtlZ+3SVpBfxHGf/SKjyrt4zUb/8DHmGhNJYwaKCNqOS6rRlO
DzKpysVXjcbWS3ljf9ZIxOhEoERc1RLhkcvjHz49UOw2F3o21529wlB08pDumr6W
TvJY9lB5b1mJ+MoHFxudDoiA0iqNPVMHWJz2EJrJX9skCLZRJSkPzQIG3IIeVxRO
dF+PXJw=
MIIDhzCCAm+gAwIBAgIJAMDqQhbo/w/YMA0GCSqGSIb3DQEBCwUAMCIxIDAeBgNV
BAMTF3Rlc3Rub2RlLWNsaWVudC1wcm9maWxlMB4XDTE1MDkyMzE4NTI1NloXDTE5
MDkyMjE4NTI1NlowIjEgMB4GA1UEAxMXdGVzdG5vZGUtY2xpZW50LXByb2ZpbGUw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDh9VWS5kI7Sf1tJSCP3F+l
F1Ve2w9GgoRYjOz7jTWm8h8WPoMSGoCIEQqxm+Eo+AGCd58tacKO4ANxZbjh33hP
7bh7jYmj3qDZlwnTaM4RIvzPSgYzlgx7iBWXJZoxWi9jlEBehg/bB6+2tK0/4CJJ
27Xi2cjJDTcctyLEhuQEH6oLf0pBfK2UXv9LkoOkrnRzY+x4YBOlrPmho+5jU2iw
5DnFNKw4Cxdd9XnDpAprU2E02pCXN3mpcvDk2MdnzWvDh14j1eisxmAl7wbU5fdF
P50v5m8cOPreWUlS2WYIJ+nHLnbnmVE8F2FpXDupF5WK5BU/QHVnE6i5kwvMITsJ
AgMBAAGjgb8wgbwwCQYDVR0TBAIwADAdBgNVHQ4EFgQU08G5lM8hL/8f61uAkl3n
vJzyEv4wgY8GA1UdEQSBhzCBhIIJbG9jYWxob3N0ghVsb2NhbGhvc3QubG9jYWxk
b21haW6CCmxvY2FsaG9zdDSCF2xvY2FsaG9zdDQubG9jYWxkb21haW40ggpsb2Nh
bGhvc3Q2ghdsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNocEfwAAAYcQAAAAAAAAAAAA
AAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAq84Eku8yLOcaxfBb7pHWaHHsaxXZ
k1lK3SZm49VTuwtMrGCYY7TBt4Kz1mnpQZd9KVyE4BzhpvUmD2ybSsyK/w1nYGVw
VyFEnutlIsYWs4rWwrvYoX1/B86WvNMBa+XFBnlO0HR5yTc/m5LKkNsZ3p2CGPfN
PCaok0NwS7cKIsWIgBaFlIYMYjZM+cL5qAWeOOgQoxPKi5uzZ/YqJbWf0jwpA/8s
M9QuqJzJMSGvwn0i74ulbubjnit2dMbrUUm6W65snw5qLDSqZzDH02EYYG4yMkmP
/S/SZFvw7fuOHFeJBoO3oej+ilEuYPkjkysr3Ys6xmprqExdDHUMElEycA==
-----END CERTIFICATE-----

View File

@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,AA1E05F81F24B5E3
Axn5ritl59GJQ4PLJDIk/IRvYSPsk+5JygqjZc4oeewhpbWqOjzVYROMD65DqN4k
sZw9vhDSm8TjhmuMWP+n1oJWZtAEKBcXbAhoG8lErsJPYx5xq9SYrbK6LWXYlVN2
fbf5o77vQDqLiZf2QeXyufgLbEZ7yslYPBSMiOQfp2jwpHOQrlWIg7awheTpd8Dv
PQ/Jy45mGJ2gl5n1Yn+nZbIO/S+3Wy0AX0MmS7nBU4ogOkIMq4ZBFALnfmcdGZHJ
pfi2riNF6lTeMgHrGtCRY3yp9Hyu0Ve/2fYdfECcG2BUQ0TweZynMqE3kJokwwC6
ua3T3WBnQws1MYxvYjy8WaSriuAfNvnu80rdiJRRcp8wBjbSYrxHq2BtYMrVuekt
lFdDCBAnmbTzYVFCez4K5l1Tbd0ilc7D8dFhHP07dkkcm57P2cm3u76O0pIqjzEx
DvYs33vdxiFq4Z4QPDbFh6Xz9uaDhy1gxlm8/giHd+JBPJlcoHD5C2Wtd0pI0tz/
5n1bdFeejqItmfy45IFFrRn/jb7Q59olVNSbWH9RojLx9HQct4w6MScmv8n8J/r9
PUrapSwwLEV6lYDBMsO5RXXDDUTJHcXVbr1nuU6BTCTTe1nMIK1+8pS1m4Cizjcg
9J3FWLktCqiCx8NI9O/QzIsbyA6R/NjmvYPOx0/nqtMCPNYJHuZyExMiVMMaPNly
Ic0HfnZyiwJPj52l67xzm4KwJH57piwldRGjVCj7IkVbHs2MRVsT0+j/QKGSU0uY
DTHIOSToCrzorh0j01fmG4zpMFkU/rtCmT3STkSFdsEsy9EORGx2C9t4mVth3V6e
Rc0y9TUcKGdtW13OiZN4o12aToC7yhg0aIpseWm8I0nnRg/TVtzoltOv85I0Lelr
vcQ8/jZ5Go8JZbTrMFmCdIPYvx+m7lL7kGx9Zt3hDpj+EBm0g5Gp44KUkxtI7Bs8
1sUvSTyNKW8mixkiS4Bq4dGDqHIuvwW1x9PVoJODbHzTip5aAzJWmXA5rOxVp2kz
keA73TUpJo2UZkME8SiDGVlcnZAGx0odxe1tMBkc2GPpQVmz8Xmi75aEuvzBlAEh
2LWGnBhgN1T6cwvkJKgdbVHUlt3fUIPHzZhItMKrPbATMl5Rtf8Fkj4TYGvoxJZh
QPLuD7ngTORv84W0xnxlt2KO8hEkpKjTImu20n4FIb/YPlVxbYULnt9xRl/QaEol
7jjpZJ7zmuZBAEevOlQk/Jc05TbdttPoWU6zVsSswjuAn3lVRIK9Ad0iXzPDWkWU
Du41QXpkCXCoIdky1WZjmZPqLd/nnSdKSBt52ZtMimFix7uer/u9f+933lETSK7U
ImUFAP/pnlmCzll1Rmublb+WDyFV2lIZ2rZURIQUuQMCCcAFo9XmWgdTjJAOUdwX
qLvYUNIVb2B5uAUgm8Wn/vxUW04Jn1aQrPSPGBCo9KSy16DbkslSWpJeCHwS+FBP
Z8CedsnajbUnAa3HebykjlhOkob7wTCogzLjaPj07XYa/O2Dwmiv1GOnXrdie9Wi
ul0/CAm53ZtLOrgHmi1cPq9FtYAYJLboLu7eW2jZz2MjcugGG+0eGdzSoKSfWfOX
-----END RSA PRIVATE KEY-----

View File

@ -1,21 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDbTCCAlWgAwIBAgIJAJ+K5mGS3n/AMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV
MIID0zCCArugAwIBAgIJALi5bDfjMszLMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV
BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp
Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTQxMjE2MTcwNDQ1WhcNMTgxMjE1MTcwNDQ1
Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTUwOTIzMTg1MjU3WhcNMTkwOTIyMTg1MjU3
WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV
BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAzhpW7iwkm+Og+HP7U00nbmh0Hy9Z2Ldp5i8tJSlSQwTxCCvO
rse6jwJQN98Dk1ApaSzimZrlKOotFyPV1L3fnOzJbTp1Yq/VsYP4zJkjWtID0qUf
8Rg8bLhjKAG+ZlLuai5XZqnLkdmqvQeR61VhpXWFm0Om153tWmAiHL18ywY71gXN
EnkeFo9OW4fDqkz6h7NJziYvU6URSKErZDEixk5GIPv9K9hiIfi0KQM6xaHp0d2w
VCyFVC0OUdugz6untURzJVx4U3X1bQcv/o2BoUotWh/5h8o5eeiiv2OGZ1XlO+33
1tweYI4wFjDwnAyHHRr/rk2ZIBiBYGaSzHnuhQIDAQABo1owWDAJBgNVHRMEAjAA
MB0GA1UdDgQWBBTwGg2LF8+mzsvBBWxJKv6VXv3dMTAsBgNVHREEJTAjgglsb2Nh
bGhvc3SHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAIwDQYJKoZIhvcNAQELBQADggEB
ABP4ufLToJhcUselVxV9LPD5VGPEHGLdIFqsUEix7DMsiNpR76X6a8qNQbZpdbd6
+qPKqoaMgC7znX7qZtCqRbIXTWbudZPxFkcHdiWx3SiALMQYabeUGetClX3sCndU
SUoV8f34i8dJxfNcqhLcsh4zpgxtmwsvs5OLMTBvm0Xo2zUFUjlmrt41pBrWEuq9
nkObc/cr6Syiz3sy4pYVJO1/YwHaZgE/URqjVlari70DR3ES4YnIUnLQajKx2Q0/
gXVgzjbe68KPOUGCz6GYiWq+d4tcWdHzLv1GsaqQ1MD9P21ArfrX4DpzgPDrO6MP
9Ppq5DQGa2q4mz3kipd5RIs=
AQ8AMIIBCgKCAQEA3rGZ1QbsW0+MuyrSLmMfDFKtLBkIFW8V0gRuurFg1PUKKNR1
Mq2tMVwjjYETAU/UY0iKZOzjgvYPKhDTYBTte/WHR1ZK4CYVv7TQX/gtFQG/ge/c
7u0sLch9p7fbd+/HZiLS/rBEZDIohvgUvzvnA8+OIYnw4kuxKo/5iboAIS41klMg
/lATm8V71LMY68inht71/ZkQoAHKgcR9z4yNYvQ1WqKG8DG8KROXltll3sTrKbl5
zJhn660es/1ZnR6nvwt6xnSTl/mNHMjkfv1bs4rJ/py3qPxicdoSIn/KyojUcgHV
F38fuAy2CQTdjVG5fWj9iz+mQvLm3+qsIYQdFwIDAQABo4G/MIG8MAkGA1UdEwQC
MAAwHQYDVR0OBBYEFEMMWLWQi/g83PzlHYqAVnty5L7HMIGPBgNVHREEgYcwgYSC
CWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghds
b2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5s
b2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQEL
BQADggEBAMjGGXT8Nt1tbl2GkiKtmiuGE2Ej66YuZ37WSJViaRNDVHLlg87TCcHe
k2rdO+6sFqQbbzEfwQ05T7xGmVu7tm54HwKMRugoQ3wct0bQC5wEWYN+oMDvSyO6
M28mZwWb4VtR2IRyWP+ve5DHwTM9mxWa6rBlGzsQqH6YkJpZojzqk/mQTug+Y8aE
mVoqRIPMHq9ob+S9qd5lp09+MtYpwPfTPx/NN+xMEooXWW/ARfpGhWPkg/FuCu4z
1tFmCqHgNcWirzMm3dQpF78muE9ng6OB2MXQwL4VgnVkxmlZNHbkR2v/t8MyZJxC
y4g6cTMM3S/UMt5/+aIB2JAuMKyuD+A=
-----END CERTIFICATE-----

View File

@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,9D867F7E0C94D013
dVoVCjPeg1wgS7rVtOvGfQcrZyLkx393aWRnFq45tbjKBVuITtJ9vI7o4QXOV/15
Gnb6WhXGIdWrzsxEAd46K6hIuNSISd4Emsx6c2Q5hTqWXXfexbOZBNfTtXtdJPnJ
1jAaikhtztLo3JSLTKNY5sNxd+XbaQyYVUWvueK6zOaIIMETvB+VPVFd9i1ROibk
Sgdtyj01KjkoalifqK/tA0CIYNKL0S6/eoK3UhAlpIprlpV+cnXa940C6bjLeJPt
PMAGGp5RrplxSgrSerw3I9DOWkHGtpqzIka3XneNUXJP8k4HUJ+aZkGH2ZILKS8d
4KMIb+KZSpHEGn+6uGccWLtZZmAjWJrDw56JbQtSHdRYLBRSOjLbTvQoPu/2Hpli
7HOxbotlvjptMunncq5aqK57SHA1dh0cwF7J3LUmGFJ67eoz+VV3b5qMn4MopSeI
mS16Ydd3nGpjSrln/elM0CQxqWfcOAXRZpDpFUQoXcBrLVzvz2DBl/0CrTRLhgzi
CO+5/IVcBWRlYpRNGgjjP7q0j6URID3jk5J06fYQXmBiwQT5j+GZqqzpMCJ9mIy2
1O9SN1hebJnIcEU+E0njn/MGjlYdPywhaCy8pqElp6Q8TUEJpwLRFO/owCoBet/n
ZmCXUjfCGhc1pWHufFcDEQ6xMgEWWY/tdwCZeSU7EhErTjCbfupg+55A5fpDml0m
3wH4CFcuRjlqyx6Ywixm1ATeitDtJl5HQTw6b8OtEXwSgRmZ0eSqSRVk9QbVS7gu
IpQe09/Zimb5HzjZqZ3fdqHlcW4xax8hyJeyIvF5ZJ57eY8CBvu/wP2GDn26QnvF
xQqdfDbq1H4JmpwUHpbFwBoQK4Q6WFd1z4EA9bRQeo3H9PoqoOwMDjzajwLRF7b7
q6tYH/n9PyHwdf1c4fFwgSmL1toXGfKlA9hjIaLsRSDD6srT5EdUk78bsnddwI51
tu7C7P4JG+h1VdRNMNTlqtileWsIE7Nn2A1OkcUxZdF5mamENpDpJcHePLto6c8q
FKiwyFMsxhgsj6HK2HqO+UA4sX5Ni4oHwiPmb//EZLn045M5i1AN26KosJmb8++D
sgR5reWRy+UqJCTYblVg+7Dx++ggUnfxVyQEsWmw5r5f4KU5wXBkvoVMGtPNa9DE
n/uLtObD1qkNL38pRsr2OGRchYCgEoKGqEISBP4knfGXLOlWiW/246j9QzI97r1u
tvy7fKg28G7AUz9l6bpewsPHefBUeRQeieP9eJINaEpxkF/w2RpKDLpQjWxwDDOM
s+D0mrBMJve17AmJ8rMw6dIQPZYNZ88/jz1uQuUwQ2YlbmtZbCG81k9YMFGEU9XS
cyhJxj8hvYnt2PR5Z9/cJPyWOs0m/ufOeeQQ8SnU/lzmrQnpzUd2Z6p5i/B7LdRP
n1kX+l1qynuPnjvBz4nJQE0p6nzW8RyCDSniC9mtYtZmhgC8icqxgbvS7uEOBIYJ
NbK+0bEETTO34iY/JVTIqLOw3iQZYMeUpxpj6Phgx/oooxMTquMecPKNgeVtaBst
qjTNPX0ti1/HYpZqzYi8SV8YjHSJWCVMsZjKPr3W/HIcCKqYoIfgzi83Ha2KMQx6
-----END RSA PRIVATE KEY-----

View File

@ -1,6 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -1,18 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nullable=org.elasticsearch.common.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.lineSplit=140
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4

File diff suppressed because one or more lines are too long

View File

@ -423,5 +423,3 @@ name in the `file` field. For example, the following snippet references the scri
}
}
--------------------------------------------------
include::how-watcher-works/dynamic-index-names.asciidoc[]

View File

@ -1,106 +0,0 @@
[[dynamic-index-names]]
=== Dynamic Index Names
Several watch constructs deal with indices, including <<actions-index, `index` action>>,
the <<transform-search, `search` transform>> and the <<input-search, `search` input>>.
When configuring these constructs you can set the index names to static values. In addition
to specifying static index names, Watcher enables you to specify indexes using dynamic
time-aware templates. These templates resolve to specific index names during the watch
execution according to the execution time.
Dynamic index name resolution enables you to search a range of time-series indices, rather
than searching all of your time-series indices and filtering the the results. Limiting the
number of indices that are searched reduces the load on the cluster and improves watch
execution performance. For example, if you are using a watch to monitor errors in your
daily logs, you can use a dynamic index name template to restrict the search to the past
two days.
A dynamic index name takes the following form:
[source,txt]
----------------------------------------------------------------------
<static_name{date_math_expr{date_format}}>
----------------------------------------------------------------------
Where:
* `static_name` is the static text part of the name
* `date_math_expr` is a dynamic date math expression that computes the date dynamically
* `date_format` is the format in which the computed date should be rendered
NOTE: You must enclose dynamic index name templates within angle brackets. For example,
`<logstash-{now/d-2d}>`
The following example shows different forms of dynamic index names and the final index names
they resolve to given the execution date is 22rd March 2024.
[options="header"]
|======
| Expression |Resolves to
| `<logstash-{now/d}>` | `logstash-2024.03.22`
| `<logstash-{now/M}>` | `logstash-2024.03.01`
| `<logstash-{now/M{YYYY.MM}}>` | `logstash-2024.03`
| `<logstash-{now/M-1M{YYYY.MM}}>` | `logstash-2024.02`
|======
To use the characters `{` and `}` in the static part of an index name template, escape them
with a backslash, `\`:
* `<elastic\\{ON\\}-{now/M}>` resolves to `elastic{ON}-2024.03.01`
The following example shows a search input that searches the Logstash indices for the past
three days, assuming the indices use the default Logstash index name format,
`logstash-YYYY.MM.dd`.
[source,json]
----------------------------------------------------------------------
{
...
"input" : {
"search" : {
"request" : {
"indices" : [
"<logstash-{now/d-2d}>",
"<logstash-{now/d-1d}>",
"<logstash-{now/d}>"
],
...
}
}
}
...
}
----------------------------------------------------------------------
[[dynamic-index-name-timezone]]
By default, the index names are resolved base on `UTC` time zone. You can change this default at
multiple levels:
Configuring the following setting set the default dynamic index name time zone in watcher:
[source,yaml]
--------------------------------------------------
watcher.dynamic_indices.time_zone: '+01:00'
--------------------------------------------------
You can also configure the default time zone separately on each of the construct that make
use of it (`search` input/transform and `index` action):
[source,yaml]
--------------------------------------------------
watcher.input.search.dynamic_indices.time_zone: '+01:00'
--------------------------------------------------
[source,yaml]
--------------------------------------------------
watcher.transform.search.dynamic_indices.time_zone: '+01:00'
--------------------------------------------------
[source,yaml]
--------------------------------------------------
watcher.actions.index.dynamic_indices.time_zone: '+01:00'
--------------------------------------------------
Alternatively, each of these construct can define their own time zone within the watch
definition.

View File

@ -33,7 +33,7 @@ The following snippet shows a simple `index` action definition:
|Name |Required | Default | Description
| `index` | yes | - | The Elasticsearch index to
index into. <<dynamic-index-names, Dynamic index names>>
index into.
are supported
| `doc_type` | yes | - | The type of the document
@ -51,10 +51,6 @@ The following snippet shows a simple `index` action definition:
the default internal index/bulk operations
<<default-internal-ops-timeouts, timeouts>>.
| `dynamic_name_timezone` | no | - | The time zone to use for resolving the index name based on
<<dynamic-index-names, Dynamic Index Names>>. The default
time zone also can be <<dynamic-index-name-timezone, configured>>
globally.
|======

View File

@ -128,7 +128,7 @@ holds an object where the keys serve as the header names and the values serve as
| `request.scheme` | no | http | The connection scheme. Valid values are: `http` or `https`.
| `request.host` | yes | - | The host to connect to.
| `request.port` | yes | - | The port the HTTP service is listening on.
| `request.path` | no | - | The URL path. The path can be static text or include Mustache <<templates, templates>>.
| `request.path` | no | - | The URL path. The path can be static text or include Mustache <<templates, templates>>. URL query string parameters must be specified via the `request.params` attribute.
| `request.method` | no | get | The HTTP method. Valid values are: `head`, `get`, `post`, `put` and `delete`.
| `request.headers` | no | - | The HTTP request headers. The header values can be static text or include Mustache <<templates, templates>>.
| `request.params` | no | - | The URL query string parameters. The parameter values can be static text or include Mustache <<templates, templates>>.

View File

@ -30,7 +30,7 @@ NOTE: If the body of the response from the HTTP endpoint is in the JSON or YAM
| `request.scheme` | no | http | Url scheme. Valid values are: `http` or `https`.
| `request.host` | yes | - | The host to connect to.
| `request.port` | yes | - | The port the http service is listening on.
| `request.path` | no | - | The URL path. The path can be static text or contain `mustache` <<templates, templates>>.
| `request.path` | no | - | The URL path. The path can be static text or contain `mustache` <<templates, templates>>. URL query string parameters must be specified via the `request.params` attribute.
| `request.method` | no | get | The HTTP method. Supported values are: `head`, `get`, `post`, `put` and `delete`.
| `request.headers` | no | - | The HTTP request headers. The header values can be static text or include `mustache` <<templates, templates>>.
| `request.params` | no | - | The URL query string parameters. The parameter values can be static text or contain `mustache` <<templates, templates>>.

View File

@ -19,7 +19,7 @@ example, to get the message field from the first hit, use `ctx.payload.hits.hits
|======
| Name |Required | Default | Description
| `request.search_type` | no | count | The {ref}/search-request-search-type.html#search-request-search-type[type] of search request to perform. Valid values are: `count`, `dfs_query_and_fetch`, `dfs_query_then_fetch`, `query_and_fetch`, `query_then_fetch`, and `scan`. The Elasticsearch default is `query_then_fetch`.
| `request.indices` | no | - | The indices to search. If omitted, all indices are searched, which is the default behaviour in Elasticsearch. <<dynamic-index-names, Dynamic index names>> are supported.
| `request.indices` | no | - | The indices to search. If omitted, all indices are searched, which is the default behaviour in Elasticsearch.
| `request.types` | no | - | The document types to search for. If omitted, all document types are are searched, which is the default behaviour in Elasticsearch.
| `request.body` | no | - | The body of the request. The {ref}/search-request-body.html[request body] follows the same structure you normally send in the body of a REST `_search` request. The body can be static text or include `mustache` <<templates, templates>>.
| `request.template` | no | - | The body of the search template. See <<templates, configure templates>> for more information.
@ -29,7 +29,6 @@ example, to get the message field from the first hit, use `ctx.payload.hits.hits
| `extract` | no | - | A array of JSON keys to extract from the search response and load as the payload. When a search generates a large response, you can use `extract` to select the relevant fields instead of loading the entire response.
| `timeout` | no | 30s | The timeout for waiting for the search api call to return. If no response is returned within this time, the search input times out and fails.
This setting overrides the default internal search operations <<default-internal-ops-timeouts, timeouts>>.
| `dynamic_name_timezone` | no | - | The time zone to use for resolving the index name based on <<dynamic-index-names, Dynamic Index Names>>. The default time zone also can be <<dynamic-index-name-timezone, configured>> globally.
|======
You can reference the following variables in the execution context when specifying the request `body`:

View File

@ -56,7 +56,7 @@ The following table lists all available settings for the search transform:
|======
| Name |Required | Default | Description
| `request.search_type` | no | {ref}/search-request-search-type.html#query-then-fetch[query_then_fetch] | The search {ref}/search-request-search-type.html[search type]
| `request.indices` | no | all indices | One or more indices to search on (may be a comma-delimited string or an array of indices names). <<dynamic-index-names, Dynamic index names>> are supported.
| `request.indices` | no | all indices | One or more indices to search on (may be a comma-delimited string or an array of indices names).
| `request.types` | no | all types | One or more document types to search on (may be a comma-delimited string or an array of document types names)
| `request.body` | no | `match_all` query | The body of the request. The {ref}/search-request-body.html[request body] follows the same structure you normally send in the body of a REST `_search` request. The body can be static text or include `mustache` <<templates, templates>>.
| `request.indices_options.expand_wildcards` | no | `open` | Determines how to expand indices wildcards. Can be one of `open`, `closed`, `none` or `all` (see {ref}/multi-index.html[multi-index support])
@ -65,7 +65,6 @@ The following table lists all available settings for the search transform:
| `request.template` | no | - | The body of the search template. See <<templates, configure templates>> for more information.
| `timeout` | no | 30s | The timeout for waiting for the search api call to return. If no response is returned within this time, the search transform times out and fails.
This setting overrides the default internal search operations <<default-internal-ops-timeouts, timeouts>>.
| `dynamic_name_timezone` | no | - | The time zone to use for resolving the index name based on <<dynamic-index-names, Dynamic Index Names>>. The default time zone also can be <<dynamic-index-name-timezone, configured>> globally.
|======
[[transform-search-template]]

View File

@ -36,6 +36,21 @@ bin/plugin remove watcher
[[change-list]]
=== Change List
[float]
==== 2.0.0-rc1
.Breaking
* The dynamic index names support has been removed and Elasticsearch's date math index names support should be used instead.
The only difference between Watcher's dynamic index names support and Elasticsearch's date math index names support is
how timezones are expressed. In Watcher this is done via node settings, in Elasticsearch the timezone is part of the
date math index names support. Only if you're using dynamic index names with timezones in Watcher then you need to
upgrade your watches after the upgrade, otherwise your watches will work as they did before the upgrade. For example if
`watcher.dynamic_indices.time_zone` setting was set to `+01:00` and a watch has the following index name `<logstash-{now/d}>`
then after the upgrade you need to update this watch to use the following index name `<logstash-{now/d{YYYY.MM.dd|+01:00}}>`.
.Bug Fixes
* Fixed url encoding issue in http input and webhook output. The url params were url encoded twice.
[float]
==== 2.0.0-beta2
@ -73,7 +88,7 @@ been aligned with the Elasticsearch versioning.
==== 1.0.0
.Enhancements
* Added execution time aware <<dynamic-index-names, dynamic index names>> support to `index`
* Added execution time aware dynamic index names support to `index`
action, `search` input, and `search` transform.
* You must now explicitly specify the unit when configuring any time value. (Numeric-only
values are no longer supported.)

View File

@ -20,7 +20,6 @@ import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.actions.ExecutableAction;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.support.ArrayObjectIterator;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.support.xcontent.XContentSource;
@ -37,17 +36,11 @@ public class ExecutableIndexAction extends ExecutableAction<IndexAction> {
private final ClientProxy client;
private final TimeValue timeout;
private final DynamicIndexName indexName;
public ExecutableIndexAction(IndexAction action, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout, DynamicIndexName.Parser indexNameParser) {
public ExecutableIndexAction(IndexAction action, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout) {
super(action, logger);
this.client = client;
this.timeout = action.timeout != null ? action.timeout : defaultTimeout;
this.indexName = indexNameParser.parse(action.index, action.dynamicNameTimeZone);
}
DynamicIndexName indexName() {
return indexName;
}
@Override
@ -71,7 +64,7 @@ public class ExecutableIndexAction extends ExecutableAction<IndexAction> {
IndexRequest indexRequest = new IndexRequest();
indexRequest.index(indexName.name(ctx.executionTime()));
indexRequest.index(action.index);
indexRequest.type(action.docType);
if (action.executionTimeField != null && !TimestampFieldMapper.NAME.equals(action.executionTimeField)) {
@ -104,7 +97,7 @@ public class ExecutableIndexAction extends ExecutableAction<IndexAction> {
}
Map<String, Object> doc = (Map<String, Object>) item;
IndexRequest indexRequest = new IndexRequest();
indexRequest.index(indexName.name(ctx.executionTime()));
indexRequest.index(action.index);
indexRequest.type(action.docType);
if (action.executionTimeField != null && !TimestampFieldMapper.NAME.equals(action.executionTimeField)) {
if (!(doc instanceof HashMap)) {

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.watcher.actions.ActionFactory;
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import java.io.IOException;
@ -23,14 +22,12 @@ import java.io.IOException;
public class IndexActionFactory extends ActionFactory<IndexAction, ExecutableIndexAction> {
private final ClientProxy client;
private final DynamicIndexName.Parser indexNamesParser;
private final TimeValue defaultTimeout;
@Inject
public IndexActionFactory(Settings settings, ClientProxy client) {
super(Loggers.getLogger(ExecutableEmailAction.class, settings));
this.client = client;
this.indexNamesParser = new DynamicIndexName.Parser(settings, "watcher.actions.index");
this.defaultTimeout = settings.getAsTime("watcher.actions.index.default_timeout", null);
}
@ -46,6 +43,6 @@ public class IndexActionFactory extends ActionFactory<IndexAction, ExecutableInd
@Override
public ExecutableIndexAction createExecutable(IndexAction action) {
return new ExecutableIndexAction(action, actionLogger, client, defaultTimeout, indexNamesParser);
return new ExecutableIndexAction(action, actionLogger, client, defaultTimeout);
}
}

View File

@ -18,7 +18,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.input.ExecutableInput;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.XContentFilterKeysUtils;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
@ -37,24 +36,17 @@ public class ExecutableSearchInput extends ExecutableInput<SearchInput, SearchIn
private final ClientProxy client;
private final @Nullable TimeValue timeout;
private final @Nullable DynamicIndexName[] indexNames;
public ExecutableSearchInput(SearchInput input, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout, DynamicIndexName.Parser indexNameParser) {
public ExecutableSearchInput(SearchInput input, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout) {
super(input, logger);
this.client = client;
this.timeout = input.getTimeout() != null ? input.getTimeout() : defaultTimeout;
String[] indices = input.getSearchRequest().indices();
indexNames = indices != null ? indexNameParser.parse(indices, input.getDynamicNameTimeZone()) : null;
}
DynamicIndexName[] indexNames() {
return indexNames;
}
public SearchInput.Result execute(WatchExecutionContext ctx) {
SearchRequest request = null;
try {
request = WatcherUtils.createSearchRequestFromPrototype(input.getSearchRequest(), indexNames, ctx, null);
request = WatcherUtils.createSearchRequestFromPrototype(input.getSearchRequest(), ctx, null);
return doExecute(ctx, request);
} catch (Exception e) {
logger.error("failed to execute [{}] input for [{}]", e, SearchInput.TYPE, ctx.watch());

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.watcher.input.InputFactory;
import org.elasticsearch.watcher.input.simple.ExecutableSimpleInput;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import java.io.IOException;
@ -23,14 +22,12 @@ import java.io.IOException;
public class SearchInputFactory extends InputFactory<SearchInput, SearchInput.Result, ExecutableSearchInput> {
private final ClientProxy client;
private final DynamicIndexName.Parser indexNameParser;
private final TimeValue defaultTimeout;
@Inject
public SearchInputFactory(Settings settings, ClientProxy client) {
super(Loggers.getLogger(ExecutableSimpleInput.class, settings));
this.client = client;
this.indexNameParser = new DynamicIndexName.Parser(settings, "watcher.input.search");
this.defaultTimeout = settings.getAsTime("watcher.input.search.default_timeout", null);
}
@ -46,6 +43,6 @@ public class SearchInputFactory extends InputFactory<SearchInput, SearchInput.Re
@Override
public ExecutableSearchInput createExecutable(SearchInput input) {
return new ExecutableSearchInput(input, inputLogger, client, defaultTimeout, indexNameParser);
return new ExecutableSearchInput(input, inputLogger, client, defaultTimeout);
}
}

View File

@ -1,339 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.watcher.support;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.joda.DateMathParser;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Callable;
/**
*
*/
public class DynamicIndexName implements ToXContent {
public static final String DEFAULT_DATE_FORMAT = "YYYY.MM.dd";
private static final String EXPRESSION_LEFT_BOUND = "<";
private static final String EXPRESSION_RIGHT_BOUND = ">";
private static final char LEFT_BOUND = '{';
private static final char RIGHT_BOUND = '}';
private static final char ESCAPE_CHAR = '\\';
private final String text;
private final Expression expression;
private DynamicIndexName(String text, Expression expression) {
this.text = text;
this.expression = expression;
}
public String text() {
return text;
}
public String name(DateTime now) {
return expression.eval(now);
}
public static String[] names(DynamicIndexName[] indexNames, DateTime now) {
String[] names = new String[indexNames.length];
for (int i = 0; i < names.length; i++) {
names[i] = indexNames[i].name(now);
}
return names;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DynamicIndexName that = (DynamicIndexName) o;
return text.equals(that.text);
}
@Override
public int hashCode() {
return text.hashCode();
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.value(text);
}
public static String defaultDateFormat(Settings settings, String componentPrefix) {
if (componentPrefix == null) {
return defaultDateFormat(settings);
}
return settings.get(componentPrefix + ".dynamic_indices.default_date_format", defaultDateFormat(settings));
}
public static String defaultDateFormat(Settings settings) {
return settings.get("watcher.dynamic_indices.default_date_format", DEFAULT_DATE_FORMAT);
}
public static DateTimeZone timeZone(Settings settings, String componentPrefix) {
if (componentPrefix == null) {
return timeZone(settings);
}
String timeZoneId = settings.get(componentPrefix + ".dynamic_indices.time_zone", DateTimeZone.UTC.getID());
return DateTimeZone.forID(timeZoneId);
}
public static DateTimeZone timeZone(Settings settings) {
String timeZoneId = settings.get("watcher.dynamic_indices.time_zone", DateTimeZone.UTC.getID());
return DateTimeZone.forID(timeZoneId);
}
interface Expression {
String eval(DateTime now);
}
static class StaticExpression implements Expression {
private final String value;
public StaticExpression(String value) {
this.value = value;
}
@Override
public String eval(DateTime now) {
return value;
}
}
static class DateMathExpression implements Expression {
private final DateMathParser dateMathParser;
private final String mathExpression;
private final FormatDateTimeFormatter formatter;
private final DateTimeZone timeZone;
public DateMathExpression(String defaultFormat, DateTimeZone timeZone, String expression) {
this.timeZone = timeZone;
int i = expression.indexOf(LEFT_BOUND);
String format;
if (i < 0) {
mathExpression = expression;
format = defaultFormat;
} else {
if (expression.lastIndexOf(RIGHT_BOUND) != expression.length() - 1) {
throw new ElasticsearchParseException("invalid dynamic name expression [{}]. missing closing `}` for date math format", expression);
}
if (i == expression.length() - 2) {
throw new ElasticsearchParseException("invalid dynamic name expression [{}]. missing date format", expression);
}
mathExpression = expression.substring(0, i);
format = expression.substring(i + 1, expression.length() - 1);
}
DateTimeFormatter parser = DateTimeFormat.forPattern(format).withZone(timeZone);
formatter = new FormatDateTimeFormatter(defaultFormat, parser, Locale.ROOT);
dateMathParser = new DateMathParser(formatter);
}
@Override
public String eval(final DateTime now) {
long millis = dateMathParser.parse(mathExpression, new Callable<Long>() {
@Override
public Long call() throws Exception {
return now.getMillis();
}
}, false, timeZone);
return formatter.printer().print(millis);
}
}
static class CompoundExpression implements Expression {
private final Expression[] parts;
public CompoundExpression(Expression[] parts) {
this.parts = parts;
}
@Override
public String eval(DateTime now) {
StringBuilder sb = new StringBuilder();
for (Expression part : parts) {
sb.append(part.eval(now));
}
return sb.toString();
}
static Expression parse(String defaultDateFormat, DateTimeZone timeZone, char[] text, int from, int length) {
boolean dynamic = false;
List<Expression> expressions = new ArrayList<>();
StringBuilder sb = new StringBuilder();
boolean inPlaceHolder = false;
boolean inDateFormat = false;
boolean escape = false;
for (int i = from; i < length; i++) {
boolean escapedChar = escape;
if (escape) {
escape = false;
}
char c = text[i];
if (c == ESCAPE_CHAR) {
if (escapedChar) {
sb.append(c);
escape = false;
} else {
escape = true;
}
continue;
}
if (inPlaceHolder) {
switch (c) {
case LEFT_BOUND:
if (inDateFormat && escapedChar) {
sb.append(c);
} else if (!inDateFormat) {
inDateFormat = true;
sb.append(c);
} else {
throw new ElasticsearchParseException("invalid dynamic name expression [{}]. invalid character in placeholder at position [{}]", new String(text, from, length), i);
}
break;
case RIGHT_BOUND:
if (inDateFormat && escapedChar) {
sb.append(c);
} else if (inDateFormat) {
inDateFormat = false;
sb.append(c);
} else {
expressions.add(new DateMathExpression(defaultDateFormat, timeZone, sb.toString()));
sb = new StringBuilder();
inPlaceHolder = false;
dynamic = true;
}
break;
default:
sb.append(c);
}
} else {
switch (c) {
case LEFT_BOUND:
if (escapedChar) {
sb.append(c);
} else {
expressions.add(new StaticExpression(sb.toString()));
sb = new StringBuilder();
inPlaceHolder = true;
}
break;
case RIGHT_BOUND:
if (!escapedChar) {
throw new ElasticsearchParseException("invalid dynamic name expression [{}]. invalid character at position [{}]. " +
"`{` and `}` are reserved characters and should be escaped when used as part of the index name using `\\` (e.g. `\\{text\\}`)", new String(text, from, length), i);
}
sb.append(c);
break;
default:
sb.append(c);
}
}
}
if (inPlaceHolder) {
throw new ElasticsearchParseException("invalid dynamic name expression [{}]. date math placeholder is open ended", new String(text, from, length));
}
if (sb.length() > 0) {
expressions.add(new StaticExpression(sb.toString()));
}
if (!dynamic) {
// if all the expressions are static... lets optimize to a single static expression
sb = new StringBuilder();
for (Expression expression : expressions) {
sb.append(((StaticExpression) expression).value);
}
return new StaticExpression(sb.toString());
}
if (expressions.size() == 1) {
return expressions.get(0);
}
return new CompoundExpression(expressions.toArray(new Expression[expressions.size()]));
}
}
public static class Parser {
private final String defaultDateFormat;
private final DateTimeZone timeZone;
public Parser() {
this(DEFAULT_DATE_FORMAT, DateTimeZone.UTC);
}
public Parser(String defaultDateFormat, DateTimeZone timeZone) {
this.defaultDateFormat = defaultDateFormat;
this.timeZone = timeZone;
}
public Parser(Settings settings, String componentPrefix) {
this(defaultDateFormat(settings, componentPrefix), timeZone(settings, componentPrefix));
}
public DynamicIndexName parse(String template) {
return parse(template, null);
}
public DynamicIndexName parse(String template, @Nullable DateTimeZone timeZone) {
DateTimeZone tz = timeZone != null ? timeZone : this.timeZone;
if (template == null) {
return null;
}
if (!template.startsWith(EXPRESSION_LEFT_BOUND) || !template.endsWith(EXPRESSION_RIGHT_BOUND)) {
return new DynamicIndexName(template, new StaticExpression(template));
}
return new DynamicIndexName(template, CompoundExpression.parse(defaultDateFormat, tz, template.toCharArray(), 1, template.length() - 1));
}
public DynamicIndexName[] parse(String[] templates) {
return parse(templates, null);
}
public DynamicIndexName[] parse(String[] templates, @Nullable DateTimeZone timeZone) {
if (templates.length == 0) {
return null;
}
DynamicIndexName[] dynamicIndexNames = new DynamicIndexName[templates.length];
for (int i = 0; i < dynamicIndexNames.length; i++) {
dynamicIndexNames[i] = parse(templates[i], timeZone);
}
return dynamicIndexNames;
}
}
}

View File

@ -53,16 +53,11 @@ public final class WatcherUtils {
return XContentHelper.convertToMap(builder.bytes(), false).v2();
}
public static SearchRequest createSearchRequestFromPrototype(SearchRequest requestPrototype, @Nullable DynamicIndexName[] dynamicIndexNames, WatchExecutionContext ctx, Payload payload) throws IOException {
String[] indices = dynamicIndexNames == null ?
requestPrototype.indices() :
DynamicIndexName.names(dynamicIndexNames, ctx.executionTime());
public static SearchRequest createSearchRequestFromPrototype(SearchRequest requestPrototype, WatchExecutionContext ctx, Payload payload) throws IOException {
SearchRequest request = new SearchRequest(requestPrototype)
.indicesOptions(requestPrototype.indicesOptions())
.searchType(requestPrototype.searchType())
.indices(indices)
.indices(requestPrototype.indices())
.types(requestPrototype.types());
// TODO: Revise this search template conversion code once search templates in core have been refactored once ES 2.0 is released.

View File

@ -107,9 +107,9 @@ public class HttpClient extends AbstractLifecycleComponent<HttpClient> {
if (builder.length() != 0) {
builder.append('&');
}
builder.append(URLEncoder.encode(entry.getKey(), "utf-8"))
builder.append(entry.getKey())
.append('=')
.append(URLEncoder.encode(entry.getValue(), "utf-8"));
.append(entry.getValue());
}
queryString = builder.toString();
}

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.transform.ExecutableTransform;
@ -27,25 +26,18 @@ public class ExecutableSearchTransform extends ExecutableTransform<SearchTransfo
protected final ClientProxy client;
protected final @Nullable TimeValue timeout;
private final @Nullable DynamicIndexName[] indexNames;
public ExecutableSearchTransform(SearchTransform transform, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout, DynamicIndexName.Parser indexNameParser) {
public ExecutableSearchTransform(SearchTransform transform, ESLogger logger, ClientProxy client, @Nullable TimeValue defaultTimeout) {
super(transform, logger);
this.client = client;
this.timeout = transform.getTimeout() != null ? transform.getTimeout() : defaultTimeout;
String[] indices = transform.getRequest().indices();
this.indexNames = indices != null ? indexNameParser.parse(indices, transform.getDynamicNameTimeZone()) : null;
}
DynamicIndexName[] indexNames() {
return indexNames;
}
@Override
public SearchTransform.Result execute(WatchExecutionContext ctx, Payload payload) {
SearchRequest request = null;
try {
request = WatcherUtils.createSearchRequestFromPrototype(transform.getRequest(), indexNames, ctx, payload);
request = WatcherUtils.createSearchRequestFromPrototype(transform.getRequest(), ctx, payload);
SearchResponse resp = client.search(request, timeout);
return new SearchTransform.Result(request, new Payload.XContent(resp));
} catch (Exception e) {

View File

@ -10,7 +10,6 @@ import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.transform.TransformFactory;
@ -22,14 +21,12 @@ import java.io.IOException;
public class SearchTransformFactory extends TransformFactory<SearchTransform, SearchTransform.Result, ExecutableSearchTransform> {
protected final ClientProxy client;
protected final DynamicIndexName.Parser indexNameParser;
private final TimeValue defaultTimeout;
@Inject
public SearchTransformFactory(Settings settings, ClientProxy client) {
super(Loggers.getLogger(ExecutableSearchTransform.class, settings));
this.client = client;
this.indexNameParser = new DynamicIndexName.Parser(settings, "watcher.transform.search");
this.defaultTimeout = settings.getAsTime("watcher.transform.search.default_timeout", null);
}
@ -45,6 +42,6 @@ public class SearchTransformFactory extends TransformFactory<SearchTransform, Se
@Override
public ExecutableSearchTransform createExecutable(SearchTransform transform) {
return new ExecutableSearchTransform(transform, transformLogger, client, defaultTimeout, indexNameParser);
return new ExecutableSearchTransform(transform, transformLogger, client, defaultTimeout);
}
}

View File

@ -21,15 +21,12 @@ import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.actions.Action.Result.Status;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.support.xcontent.XContentSource;
import org.elasticsearch.watcher.test.WatcherTestUtils;
import org.elasticsearch.watcher.watch.Payload;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import java.util.Arrays;
@ -80,7 +77,7 @@ public class IndexActionTests extends ESIntegTestCase {
}
IndexAction action = new IndexAction("test-index", "test-type", timestampField, null, null);
ExecutableIndexAction executable = new ExecutableIndexAction(action, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableIndexAction executable = new ExecutableIndexAction(action, logger, ClientProxy.of(client()), null);
DateTime executionTime = DateTime.now(UTC);
Payload payload = randomBoolean() ? new Payload.Simple("foo", "bar") : new Payload.Simple("_doc", ImmutableMap.of("foo", "bar"));
WatchExecutionContext ctx = WatcherTestUtils.mockExecutionContext("_id", executionTime, payload);
@ -143,7 +140,7 @@ public class IndexActionTests extends ESIntegTestCase {
);
IndexAction action = new IndexAction("test-index", "test-type", timestampField, null, null);
ExecutableIndexAction executable = new ExecutableIndexAction(action, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableIndexAction executable = new ExecutableIndexAction(action, logger, ClientProxy.of(client()), null);
DateTime executionTime = DateTime.now(UTC);
WatchExecutionContext ctx = WatcherTestUtils.mockExecutionContext("_id", executionTime, new Payload.Simple("_doc", list));
@ -224,47 +221,6 @@ public class IndexActionTests extends ESIntegTestCase {
assertThat(executable.action().timeout, equalTo(writeTimeout));
}
@Test
public void testParser_DynamicIndex() throws Exception {
DateTime now = DateTime.now(UTC);
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.forOffsetHours(-2) : null;
if (timeZone != null) {
now = now.withHourOfDay(0).withMinuteOfHour(0);
}
XContentBuilder builder = jsonBuilder();
builder.startObject()
.field(IndexAction.Field.INDEX.getPreferredName(), "<idx-{now/d}>")
.field(IndexAction.Field.DOC_TYPE.getPreferredName(), "test-type");
boolean timeZoneInWatch = randomBoolean();
if (timeZone != null && timeZoneInWatch) {
builder.field(IndexAction.Field.DYNAMIC_NAME_TIMEZONE.getPreferredName(), timeZone);
}
builder.endObject();
Settings.Builder settings = Settings.builder();
if (timeZone != null && !timeZoneInWatch) {
settings.put("watcher.actions.index.dynamic_indices.time_zone", timeZone);
}
IndexActionFactory actionParser = new IndexActionFactory(settings.build(), ClientProxy.of(client()));
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
parser.nextToken();
ExecutableIndexAction executable = actionParser.parseExecutable(randomAsciiOfLength(5), randomAsciiOfLength(3), parser);
assertThat(executable, notNullValue());
assertThat(executable.action().index, is("<idx-{now/d}>"));
String indexName = executable.indexName().name(now);
if (timeZone != null) {
now = now.withZone(timeZone);
}
assertThat(indexName, is("idx-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now)));
}
@Test
public void testParser_Failure() throws Exception {
XContentBuilder builder = jsonBuilder();

View File

@ -7,7 +7,6 @@ package org.elasticsearch.watcher.input.search;
import com.google.common.collect.ImmutableMap;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.indexedscripts.put.PutIndexedScriptRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchType;
@ -20,7 +19,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.watcher.actions.ActionStatus;
@ -31,7 +29,6 @@ import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.input.simple.ExecutableSimpleInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.support.text.TextTemplate;
import org.elasticsearch.watcher.trigger.schedule.IntervalSchedule;
@ -41,8 +38,6 @@ import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.watch.WatchStatus;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import java.io.IOException;
@ -116,7 +111,7 @@ public class SearchInputTests extends ESIntegTestCase {
.request()
.source(searchSourceBuilder);
ExecutableSearchInput searchInput = new ExecutableSearchInput(new SearchInput(request, null, null, null), logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchInput searchInput = new ExecutableSearchInput(new SearchInput(request, null, null, null), logger, ClientProxy.of(client()), null);
WatchExecutionContext ctx = new TriggeredExecutionContext(
new Watch("test-watch",
new ScheduleTrigger(new IntervalSchedule(new IntervalSchedule.Interval(1, IntervalSchedule.Interval.Unit.MINUTES))),
@ -223,7 +218,7 @@ public class SearchInputTests extends ESIntegTestCase {
.request()
.source(searchSourceBuilder);
ExecutableSearchInput searchInput = new ExecutableSearchInput(new SearchInput(request, null, null, null), logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchInput searchInput = new ExecutableSearchInput(new SearchInput(request, null, null, null), logger, ClientProxy.of(client()), null);
WatchExecutionContext ctx = new TriggeredExecutionContext(
new Watch("test-watch",
new ScheduleTrigger(new IntervalSchedule(new IntervalSchedule.Interval(1, IntervalSchedule.Interval.Unit.MINUTES))),
@ -266,57 +261,6 @@ public class SearchInputTests extends ESIntegTestCase {
assertThat(searchInput.getTimeout(), equalTo(timeout));
}
@Test
public void testParser_IndexNames() throws Exception {
SearchRequest request = client().prepareSearch()
.setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
.setIndices("test", "<test-{now/d-1d}>")
.request()
.source(searchSource()
.query(boolQuery().must(matchQuery("event_type", "a")).filter(rangeQuery("_timestamp").from("{{ctx.trigger.scheduled_time}}||-30s").to("{{ctx.trigger.triggered_time}}"))));
DateTime now = DateTime.now(UTC);
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.forOffsetHours(-2) : null;
if (timeZone != null) {
now = now.withHourOfDay(0).withMinuteOfHour(0);
}
boolean timeZoneInWatch = randomBoolean();
SearchInput input = timeZone != null && timeZoneInWatch ?
new SearchInput(request, null, null, timeZone) :
new SearchInput(request, null, null, null);
XContentBuilder builder = jsonBuilder().value(input);
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
parser.nextToken();
String dateFormat;
Settings.Builder settingsBuilder = Settings.builder();
if (randomBoolean()) {
dateFormat = DynamicIndexName.DEFAULT_DATE_FORMAT;
} else {
dateFormat = "YYYY-MM-dd";
settingsBuilder.put("watcher.input.search.dynamic_indices.default_date_format", dateFormat);
}
if (timeZone != null && !timeZoneInWatch) {
settingsBuilder.put("watcher.input.search.dynamic_indices.time_zone", timeZone);
}
SearchInputFactory factory = new SearchInputFactory(settingsBuilder.build(), ClientProxy.of(client()));
ExecutableSearchInput executable = factory.parseExecutable("_id", parser);
DynamicIndexName[] indexNames = executable.indexNames();
assertThat(indexNames, notNullValue());
String[] names = DynamicIndexName.names(indexNames, now);
assertThat(names, notNullValue());
assertThat(names.length, is(2));
if (timeZone != null) {
now = now.withZone(timeZone);
}
assertThat(names, arrayContaining("test", "test-" + DateTimeFormat.forPattern(dateFormat).print(now.minusDays(1))));
}
private WatchExecutionContext createContext() {
return new TriggeredExecutionContext(
new Watch("test-watch",
@ -340,7 +284,7 @@ public class SearchInputTests extends ESIntegTestCase {
SearchInput si = siBuilder.build();
ExecutableSearchInput searchInput = new ExecutableSearchInput(si, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchInput searchInput = new ExecutableSearchInput(si, logger, ClientProxy.of(client()), null);
return searchInput.execute(ctx);
}

View File

@ -83,11 +83,12 @@ public class DynamicIndexNameIntegrationTests extends AbstractWatcherIntegration
flush();
refresh();
String indexNameDateMathExpressions = "<idx-{now/d}>";
WatcherClient watcherClient = watcherClient();
PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("_id")
.setSource(watchBuilder()
.trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS)))
.input(searchInput(new SearchRequest("<idx-{now/d}>").types("type"))))
.input(searchInput(new SearchRequest(indexNameDateMathExpressions).types("type"))))
.get();
assertThat(putWatchResponse.isCreated(), is(true));
@ -96,23 +97,24 @@ public class DynamicIndexNameIntegrationTests extends AbstractWatcherIntegration
flush();
refresh();
SearchResponse response = searchHistory(searchSource().query(matchQuery("result.input.search.request.indices", indexName)));
SearchResponse response = searchHistory(searchSource().query(matchQuery("result.input.search.request.indices", indexNameDateMathExpressions)));
assertThat(response.getHits().getTotalHits(), is(1L));
}
@Test
public void testDynamicIndexSearchTransform() throws Exception {
final String indexName = "idx-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(timeWarp().clock().nowUTC());
String indexName = "idx-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(timeWarp().clock().nowUTC());
createIndex(indexName);
index(indexName, "type", "1", "key", "value");
flush();
refresh();
final String indexNameDateMathExpressions = "<idx-{now/d}>";
WatcherClient watcherClient = watcherClient();
PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("_id")
.setSource(watchBuilder()
.trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS)))
.transform(searchTransform(new SearchRequest("<idx-{now/d}>").types("type")))
.transform(searchTransform(new SearchRequest(indexNameDateMathExpressions).types("type")))
.addAction("log", loggingAction("heya")))
.get();
@ -125,7 +127,7 @@ public class DynamicIndexNameIntegrationTests extends AbstractWatcherIntegration
SearchResponse response = searchWatchRecords(new Callback<SearchRequestBuilder>() {
@Override
public void handle(SearchRequestBuilder builder) {
builder.setQuery(matchQuery("result.transform.search.request.indices", indexName));
builder.setQuery(matchQuery("result.transform.search.request.indices", indexNameDateMathExpressions));
}
});
assertThat(response.getHits().getTotalHits(), is(1L));

View File

@ -1,266 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.watcher.support;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.*;
/**
*
*/
public class DynamicIndexNameTests extends ESTestCase {
@Test
public void testNormal() throws Exception {
String indexName = randomAsciiOfLength(10);
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse(indexName);
String name = indexNames.name(now);
assertThat(name, equalTo(indexName));
}
@Test
public void testExpression() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.marvel-{now}>");
String name = indexNames.name(now);
assertThat(name, equalTo(".marvel-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now)));
}
@Test
public void testNullOrEmpty() throws Exception {
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexName = parser.parse((String) null);
assertThat(indexName, nullValue());
DynamicIndexName[] indexNames = parser.parse(Strings.EMPTY_ARRAY);
assertThat(indexNames, nullValue());
}
@Test
public void testExpression_Static() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.marvel-test>");
String name = indexNames.name(now);
assertThat(name, equalTo(".marvel-test"));
}
@Test
public void testExpression_MultiParts() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.text1-{now/d}-text2-{now/M}>");
String name = indexNames.name(now);
assertThat(name, equalTo(".text1-"
+ DateTimeFormat.forPattern("YYYY.MM.dd").print(now)
+ "-text2-"
+ DateTimeFormat.forPattern("YYYY.MM.dd").print(now.withDayOfMonth(1))));
}
@Test
public void testExpression_CustomFormat() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.marvel-{now/d{YYYY.MM.dd}}>");
String name = indexNames.name(now);
assertThat(name, equalTo(".marvel-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now)));
}
@Test
public void testExpression_CustomTimeZone() throws Exception {
DateTimeZone timeZone;
int hoursOffset;
int minutesOffset = 0;
if (randomBoolean()) {
hoursOffset = randomIntBetween(-12, 14);
timeZone = DateTimeZone.forOffsetHours(hoursOffset);
} else {
hoursOffset = randomIntBetween(-11, 13);
minutesOffset = randomIntBetween(0, 59);
timeZone = DateTimeZone.forOffsetHoursMinutes(hoursOffset, minutesOffset);
}
DateTime now;
if (hoursOffset >= 0) {
// rounding to next day 00:00
now = DateTime.now(DateTimeZone.UTC).plusHours(hoursOffset).plusMinutes(minutesOffset).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0);
} else {
// rounding to today 00:00
now = DateTime.now(DateTimeZone.UTC).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0);
}
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", timeZone);
DynamicIndexName indexNames = parser.parse("<.marvel-{now/d{YYYY.MM.dd}}>");
String name = indexNames.name(now);
logger.info("timezone: [{}], now [{}], name: [{}]", timeZone, now, name);
assertThat(name, equalTo(".marvel-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now.withZone(timeZone))));
}
@Test
public void testExpression_CustomTimeZone_OnParse() throws Exception {
DateTimeZone timeZone;
int hoursOffset;
int minutesOffset = 0;
if (randomBoolean()) {
hoursOffset = randomIntBetween(-12, 14);
timeZone = DateTimeZone.forOffsetHours(hoursOffset);
} else {
hoursOffset = randomIntBetween(-11, 13);
minutesOffset = randomIntBetween(0, 59);
timeZone = DateTimeZone.forOffsetHoursMinutes(hoursOffset, minutesOffset);
}
DateTime now;
if (hoursOffset >= 0) {
// rounding to next day 00:00
now = DateTime.now(DateTimeZone.UTC).plusHours(hoursOffset).plusMinutes(minutesOffset).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0);
} else {
// rounding to today 00:00
now = DateTime.now(DateTimeZone.UTC).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0);
}
Settings settings = Settings.builder()
.put("watcher.dynamic_indices.default_date_format", "YYYY.MM.dd")
.put("watcher.dynamic_indices.time_zone", "-12")
.put("watcher.foo.dynamic_indices.time_zone", "-12")
.build();
DynamicIndexName.Parser parser = new DynamicIndexName.Parser(settings, "watcher.foo");
DynamicIndexName indexNames = parser.parse("<.marvel-{now/d{YYYY.MM.dd}}>", timeZone);
String name = indexNames.name(now);
logger.info("timezone: [{}], now [{}], name: [{}]", timeZone, now, name);
assertThat(name, equalTo(".marvel-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now.withZone(timeZone))));
}
@Test
public void testExpression_EscapeStatic() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.mar\\{v\\}el-{now/d}>");
String name = indexNames.name(now);
assertThat(name, equalTo(".mar{v}el-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now)));
}
@Test
public void testExpression_EscapeDateFormat() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName indexNames = parser.parse("<.marvel-{now/d{'\\{year\\}'YYYY}}>");
String name = indexNames.name(now);
assertThat(name, equalTo(".marvel-" + DateTimeFormat.forPattern("'{year}'YYYY").print(now)));
}
@Test
public void testExpression_MixedArray() throws Exception {
DateTime now = DateTime.now(DateTimeZone.UTC);
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
DynamicIndexName[] indexNames = parser.parse(new String[] {
"name1",
"<.marvel-{now/d}>",
"name2",
"<.logstash-{now/M{YYYY.MM}}>"
});
String[] names = new String[indexNames.length];
for (int i = 0; i < names.length; i++) {
names[i] = indexNames[i].name(now);
}
assertThat(names.length, is(4));
assertThat(names, arrayContaining(
"name1",
".marvel-" + DateTimeFormat.forPattern("YYYY.MM.dd").print(now),
"name2",
".logstash-" + DateTimeFormat.forPattern("YYYY.MM").print(now.withDayOfMonth(1))));
}
@Test(expected = ElasticsearchParseException.class)
public void testExpression_Invalid_Unescaped() throws Exception {
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
parser.parse("<.mar}vel-{now/d}>");
}
@Test(expected = ElasticsearchParseException.class)
public void testExpression_Invalid_DateMathFormat() throws Exception {
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
parser.parse("<.marvel-{now/d{}>");
}
@Test(expected = ElasticsearchParseException.class)
public void testExpression_Invalid_EmptyDateMathFormat() throws Exception {
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
parser.parse("<.marvel-{now/d{}}>");
}
@Test(expected = ElasticsearchParseException.class)
public void testExpression_Invalid_OpenEnded() throws Exception {
DynamicIndexName.Parser parser = new DynamicIndexName.Parser("YYYY.MM.dd", DateTimeZone.UTC);
parser.parse("<.marvel-{now/d>");
}
@Test
public void testDefaultDateFormat_Default() throws Exception {
String dateFormat = DynamicIndexName.defaultDateFormat(Settings.EMPTY);
assertThat(dateFormat, is("YYYY.MM.dd"));
}
@Test
public void testDefaultDateFormat() throws Exception {
Settings settings = Settings.builder()
.put("watcher.dynamic_indices.default_date_format", "YYYY.MM")
.build();
String dateFormat = randomBoolean() ?
DynamicIndexName.defaultDateFormat(settings) :
DynamicIndexName.defaultDateFormat(settings, null);
assertThat(dateFormat, is("YYYY.MM"));
}
@Test
public void testDefaultDateFormat_Component() throws Exception {
Settings settings = Settings.builder()
.put("watcher.dynamic_indices.default_date_format", "YYYY.MM")
.put("watcher.foo.dynamic_indices.default_date_format", "YYY.MM")
.build();
String dateFormat = DynamicIndexName.defaultDateFormat(settings, "watcher.foo");
assertThat(dateFormat, is("YYY.MM"));
}
@Test
public void testTimeZone_Default() throws Exception {
DateTimeZone timeZone = DynamicIndexName.timeZone(Settings.EMPTY);
assertThat(timeZone, is(DateTimeZone.UTC));
}
@Test
public void testTimeZone() throws Exception {
DateTimeZone timeZone = DateTimeZone.forOffsetHours(randomIntBetween(-12, 14));
Settings settings = Settings.builder()
.put("watcher.dynamic_indices.time_zone", timeZone)
.build();
DateTimeZone resolvedTimeZone = randomBoolean() ?
DynamicIndexName.timeZone(settings) :
DynamicIndexName.timeZone(settings, null);
assertThat(timeZone, is(resolvedTimeZone));
}
@Test
public void testTimeZone_Component() throws Exception {
DateTimeZone timeZone = DateTimeZone.forOffsetHours(randomIntBetween(-11, 14));
Settings settings = Settings.builder()
.put("watcher.dynamic_indices.time_zone", "-12")
.put("watcher.foo.dynamic_indices.time_zone", timeZone)
.build();
DateTimeZone resolvedTimeZone = DynamicIndexName.timeZone(settings, "watcher.foo");
assertThat(resolvedTimeZone, is(timeZone));
}
}

View File

@ -74,7 +74,6 @@ public class HttpClientTests extends ESTestCase {
}
@Test
public void testBasics() throws Exception {
int responseCode = randomIntBetween(200, 203);
String body = randomAsciiOfLengthBetween(2, 8096);
@ -127,6 +126,23 @@ public class HttpClientTests extends ESTestCase {
assertThat(recordedRequest.getBody().readUtf8Line(), nullValue());
}
@Test
public void testUrlEncoding() throws Exception{
webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body"));
HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webPort)
.method(HttpMethod.GET)
.path("/test")
.setParam("key", "value 123:123");
HttpResponse response = httpClient.execute(requestBuilder.build());
assertThat(response.status(), equalTo(200));
assertThat(response.body().toUtf8(), equalTo("body"));
RecordedRequest recordedRequest = webServer.takeRequest();
assertThat(recordedRequest.getPath(), equalTo("/test?key=value%20123:123"));
assertThat(recordedRequest.getBody().readUtf8Line(), nullValue());
}
@Test
public void testBasicAuth() throws Exception {
webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body"));

View File

@ -41,7 +41,6 @@ import org.elasticsearch.watcher.input.search.ExecutableSearchInput;
import org.elasticsearch.watcher.input.simple.ExecutableSimpleInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import org.elasticsearch.watcher.license.LicenseService;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.Script;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.http.HttpClient;
@ -69,7 +68,6 @@ import org.joda.time.DateTime;
import javax.mail.internet.AddressException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.*;
@ -222,7 +220,7 @@ public final class WatcherTestUtils {
new ScheduleTrigger(new CronSchedule("0/5 * * * * ? *")),
new ExecutableSimpleInput(new SimpleInput(new Payload.Simple(inputData)), logger),
new ExecutableScriptCondition(new ScriptCondition(Script.inline("return true").build()), logger, scriptService),
new ExecutableSearchTransform(new SearchTransform(transformRequest, null, null), logger, client, null, new DynamicIndexName.Parser()),
new ExecutableSearchTransform(new SearchTransform(transformRequest, null, null), logger, client, null),
new TimeValue(0),
new ExecutableActions(actions),
metadata,

View File

@ -30,7 +30,6 @@ import org.elasticsearch.watcher.execution.TriggeredExecutionContext;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.input.simple.ExecutableSimpleInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.support.text.TextTemplate;
import org.elasticsearch.watcher.transform.Transform;
@ -42,8 +41,6 @@ import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.watch.WatchStatus;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import java.io.IOException;
@ -128,7 +125,7 @@ public class SearchTransformTests extends ESIntegTestCase {
.endObject()
.endObject().bytes());
SearchTransform searchTransform = TransformBuilders.searchTransform(request).build();
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null);
WatchExecutionContext ctx = mockExecutionContext("_name", EMPTY_PAYLOAD);
@ -165,7 +162,7 @@ public class SearchTransformTests extends ESIntegTestCase {
.endObject()
.endObject().bytes());
SearchTransform searchTransform = TransformBuilders.searchTransform(request).build();
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null);
WatchExecutionContext ctx = mockExecutionContext("_name", EMPTY_PAYLOAD);
@ -211,7 +208,7 @@ public class SearchTransformTests extends ESIntegTestCase {
.must(termQuery("value", "{{ctx.payload.value}}"))));
SearchTransform searchTransform = TransformBuilders.searchTransform(request).build();
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchTransform transform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null);
ScheduleTriggerEvent event = new ScheduleTriggerEvent("_name", parseDate("2015-01-04T00:00:00", UTC), parseDate("2015-01-01T00:00:00", UTC));
WatchExecutionContext ctx = mockExecutionContext("_name", parseDate("2015-01-04T00:00:00", UTC), event, EMPTY_PAYLOAD);
@ -303,68 +300,6 @@ public class SearchTransformTests extends ESIntegTestCase {
assertThat(executable.transform().getTimeout(), equalTo(readTimeout));
}
@Test
public void testParser_WithIndexNames() throws Exception {
SearchType searchType = getRandomSupportedSearchType();
XContentBuilder builder = jsonBuilder().startObject();
builder.startObject("request");
builder.array("indices", "idx", "<idx-{now/d-3d}>");
if (searchType != null) {
builder.field("search_type", searchType.name());
}
DateTime now = DateTime.now(UTC);
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.forOffsetHours(-2) : null;
if (timeZone != null) {
now = now.withHourOfDay(0).withMinuteOfHour(0);
}
builder.startObject("body")
.startObject("query")
.startObject("match_all")
.endObject()
.endObject()
.endObject();
builder.endObject();
boolean timeZoneInWatch = randomBoolean();
if (timeZone != null && timeZoneInWatch) {
builder.field(SearchTransform.Field.DYNAMIC_NAME_TIMEZONE.getPreferredName(), timeZone);
}
builder.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
parser.nextToken();
String dateFormat;
Settings.Builder settingsBuilder = Settings.builder();
if (randomBoolean()) {
dateFormat = DynamicIndexName.DEFAULT_DATE_FORMAT;
} else {
dateFormat = "YYYY-MM";
settingsBuilder.put("watcher.transform.search.dynamic_indices.default_date_format", dateFormat);
}
if (timeZone != null && !timeZoneInWatch) {
settingsBuilder.put("watcher.transform.search.dynamic_indices.time_zone", timeZone);
}
Settings settings = settingsBuilder.build();
SearchTransformFactory transformFactory = new SearchTransformFactory(settings, ClientProxy.of(client()));
ExecutableSearchTransform executable = transformFactory.parseExecutable("_id", parser);
DynamicIndexName[] indexNames = executable.indexNames();
assertThat(indexNames, notNullValue());
String[] names = DynamicIndexName.names(indexNames, now);
assertThat(names, notNullValue());
assertThat(names.length, is(2));
if (timeZone != null) {
now = now.withZone(timeZone);
}
assertThat(names, arrayContaining("idx", "idx-" + DateTimeFormat.forPattern(dateFormat).print(now.minusDays(3))));
}
@Test
public void testSearch_InlineTemplate() throws Exception {
WatchExecutionContext ctx = createContext();
@ -501,7 +436,7 @@ public class SearchTransformTests extends ESIntegTestCase {
ensureGreen("test-search-index");
SearchTransform searchTransform = TransformBuilders.searchTransform(request).build();
ExecutableSearchTransform executableSearchTransform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null, new DynamicIndexName.Parser());
ExecutableSearchTransform executableSearchTransform = new ExecutableSearchTransform(searchTransform, logger, ClientProxy.of(client()), null);
return executableSearchTransform.execute(ctx, Payload.Simple.EMPTY);
}

View File

@ -51,7 +51,7 @@ public class IntervalScheduleTests extends ESTestCase {
@Test
public void testParse_String() throws Exception {
IntervalSchedule.Interval value = randomTimeValue();
IntervalSchedule.Interval value = randomTimeInterval();
XContentBuilder builder = jsonBuilder().value(value);
BytesReference bytes = builder.bytes();
XContentParser parser = JsonXContent.jsonXContent.createParser(bytes);
@ -79,7 +79,7 @@ public class IntervalScheduleTests extends ESTestCase {
new IntervalSchedule.Parser().parse(parser);
}
private static IntervalSchedule.Interval randomTimeValue() {
private static IntervalSchedule.Interval randomTimeInterval() {
IntervalSchedule.Interval.Unit unit = IntervalSchedule.Interval.Unit.values()[randomIntBetween(0, IntervalSchedule.Interval.Unit.values().length - 1)];
return new IntervalSchedule.Interval(randomIntBetween(1, 100), unit);
}

View File

@ -64,7 +64,6 @@ import org.elasticsearch.watcher.input.simple.ExecutableSimpleInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import org.elasticsearch.watcher.input.simple.SimpleInputFactory;
import org.elasticsearch.watcher.license.LicenseService;
import org.elasticsearch.watcher.support.DynamicIndexName;
import org.elasticsearch.watcher.support.Script;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.clock.Clock;
@ -149,7 +148,6 @@ public class WatchTests extends ESTestCase {
private SecretService secretService;
private LicenseService licenseService;
private ESLogger logger;
private DynamicIndexName.Parser indexNameParser;
private Settings settings = Settings.EMPTY;
@Before
@ -164,7 +162,6 @@ public class WatchTests extends ESTestCase {
licenseService = mock(LicenseService.class);
authRegistry = new HttpAuthRegistry(ImmutableMap.of("basic", (HttpAuthFactory) new BasicAuthFactory(secretService)));
logger = Loggers.getLogger(WatchTests.class);
indexNameParser = new DynamicIndexName.Parser();
}
@Test
@ -339,7 +336,7 @@ public class WatchTests extends ESTestCase {
switch (type) {
case SearchInput.TYPE:
SearchInput searchInput = searchInput(WatcherTestUtils.newInputSearchRequest("idx")).build();
return new ExecutableSearchInput(searchInput, logger, client, null, indexNameParser);
return new ExecutableSearchInput(searchInput, logger, client, null);
default:
SimpleInput simpleInput = InputBuilders.simpleInput(ImmutableMap.<String, Object>builder().put("_key", "_val")).build();
return new ExecutableSimpleInput(simpleInput, logger);
@ -398,12 +395,12 @@ public class WatchTests extends ESTestCase {
case ScriptTransform.TYPE:
return new ExecutableScriptTransform(new ScriptTransform(Script.inline("_script").build()), logger, scriptService);
case SearchTransform.TYPE:
return new ExecutableSearchTransform(new SearchTransform(matchAllRequest(WatcherUtils.DEFAULT_INDICES_OPTIONS), timeout, timeZone), logger, client, null, indexNameParser);
return new ExecutableSearchTransform(new SearchTransform(matchAllRequest(WatcherUtils.DEFAULT_INDICES_OPTIONS), timeout, timeZone), logger, client, null);
default: // chain
ChainTransform chainTransform = new ChainTransform(Arrays.asList(
new SearchTransform(matchAllRequest(WatcherUtils.DEFAULT_INDICES_OPTIONS), timeout, timeZone), new ScriptTransform(Script.inline("_script").build())));
return new ExecutableChainTransform(chainTransform, logger, Arrays.<ExecutableTransform>asList(
new ExecutableSearchTransform(new SearchTransform(matchAllRequest(WatcherUtils.DEFAULT_INDICES_OPTIONS), timeout, timeZone), logger, client, null, indexNameParser),
new ExecutableSearchTransform(new SearchTransform(matchAllRequest(WatcherUtils.DEFAULT_INDICES_OPTIONS), timeout, timeZone), logger, client, null),
new ExecutableScriptTransform(new ScriptTransform(Script.inline("_script").build()), logger, scriptService)));
}
}
@ -430,7 +427,7 @@ public class WatchTests extends ESTestCase {
DateTimeZone timeZone = randomBoolean() ? DateTimeZone.UTC : null;
TimeValue timeout = randomBoolean() ? TimeValue.timeValueSeconds(30) : null;
IndexAction action = new IndexAction("_index", "_type", null, timeout, timeZone);
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomThrottler(), randomTransform(), new ExecutableIndexAction(action, logger, client, null, indexNameParser)));
list.add(new ActionWrapper("_index_" + randomAsciiOfLength(8), randomThrottler(), randomTransform(), new ExecutableIndexAction(action, logger, client, null)));
}
if (randomBoolean()) {
HttpRequestTemplate httpRequest = HttpRequestTemplate.builder("test.host", randomIntBetween(8000, 9000))