From 7f166e1927988f753dd9c56c72cd25c2acf2b2b0 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Fri, 23 Feb 2018 13:31:28 +0100 Subject: [PATCH] Cleanup: Move tests calling external services into QA projects (elastic/x-pack-elasticsearch#3869) This also moves the hipchat/pagerduty/slack tests to REST tests which put real watches and also check the history. Relates elastic/x-pack-elasticsearch#3800 Original commit: elastic/x-pack-elasticsearch@fce08d9cb7c3eb097a4102c58e2a9476cd4ad145 --- .../authc/ldap/LdapSessionFactoryTests.java | 27 -- .../LdapUserSearchSessionFactoryTests.java | 58 +--- .../test/integration/HipChatServiceTests.java | 226 -------------- .../integration/PagerDutyServiceTests.java | 96 ------ .../test/integration/SlackServiceTests.java | 136 --------- qa/smoke-test-watcher/build.gradle | 71 +---- .../smoketest/PreventFailingBuildIT.java | 19 -- ...SmokeTestWatcherClientYamlTestSuiteIT.java | 3 - qa/third-party/active-directory/build.gradle | 27 ++ .../ldap/ActiveDirectoryRunAsIT.java | 2 +- .../AbstractActiveDirectoryIntegTests.java | 0 .../ActiveDirectoryGroupsResolverTests.java | 1 + .../ActiveDirectorySessionFactoryTests.java | 30 +- ...irectoryUserSearchSessionFactoryTests.java | 138 +++++++++ .../authc/ldap/PreventFailingTests.java | 17 ++ .../UserAttributeGroupsResolverTests.java | 3 + qa/third-party/build.gradle | 0 qa/third-party/hipchat/build.gradle | 38 +++ ...SmokeTestWatcherClientYamlTestSuiteIT.java | 78 +++++ .../rest-api-spec/test/hipchat/10_hipchat.yml | 276 ++++++++++++++++++ qa/third-party/jira/build.gradle | 107 +++++++ ...SmokeTestWatcherClientYamlTestSuiteIT.java | 78 +++++ .../rest-api-spec/test/jira/10_jira.yml} | 0 qa/third-party/pagerduty/build.gradle | 39 +++ ...SmokeTestWatcherClientYamlTestSuiteIT.java | 78 +++++ .../test/pagerduty/10_pagerduty.yml | 103 +++++++ qa/third-party/slack/build.gradle | 26 ++ ...SmokeTestWatcherClientYamlTestSuiteIT.java | 78 +++++ .../rest-api-spec/test/slack/10_slack.yml | 109 +++++++ 29 files changed, 1215 insertions(+), 649 deletions(-) delete mode 100644 plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HipChatServiceTests.java delete mode 100644 plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/PagerDutyServiceTests.java delete mode 100644 plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SlackServiceTests.java delete mode 100644 qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/PreventFailingBuildIT.java create mode 100644 qa/third-party/active-directory/build.gradle rename plugin/security/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsTests.java => qa/third-party/active-directory/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsIT.java (97%) rename {plugin/security => qa/third-party/active-directory}/src/test/java/org/elasticsearch/xpack/security/authc/ldap/AbstractActiveDirectoryIntegTests.java (100%) rename {plugin/security => qa/third-party/active-directory}/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java (99%) rename {plugin/security => qa/third-party/active-directory}/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java (95%) create mode 100644 qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryUserSearchSessionFactoryTests.java create mode 100644 qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/PreventFailingTests.java rename {plugin/security => qa/third-party/active-directory}/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java (97%) create mode 100644 qa/third-party/build.gradle create mode 100644 qa/third-party/hipchat/build.gradle create mode 100644 qa/third-party/hipchat/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java create mode 100644 qa/third-party/hipchat/src/test/resources/rest-api-spec/test/hipchat/10_hipchat.yml create mode 100644 qa/third-party/jira/build.gradle create mode 100644 qa/third-party/jira/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java rename qa/{smoke-test-watcher/src/test/resources/rest-api-spec/test/actions/20_jira.yml => third-party/jira/src/test/resources/rest-api-spec/test/jira/10_jira.yml} (100%) create mode 100644 qa/third-party/pagerduty/build.gradle create mode 100644 qa/third-party/pagerduty/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java create mode 100644 qa/third-party/pagerduty/src/test/resources/rest-api-spec/test/pagerduty/10_pagerduty.yml create mode 100644 qa/third-party/slack/build.gradle create mode 100644 qa/third-party/slack/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java create mode 100644 qa/third-party/slack/src/test/resources/rest-api-spec/test/slack/10_slack.yml diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java index c9f46ebf319..8a31934f15c 100644 --- a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java +++ b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java @@ -81,33 +81,6 @@ public class LdapSessionFactoryTests extends LdapTestCase { } } - @Network - @AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2849") - public void testConnectTimeout() { - // Local sockets connect too fast... - String ldapUrl = "ldap://54.200.235.244:389"; - String groupSearchBase = "o=sevenSeas"; - String userTemplates = "cn={0},ou=people,o=sevenSeas"; - - Settings settings = Settings.builder() - .put(buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, LdapSearchScope.SUB_TREE)) - .put(SessionFactorySettings.TIMEOUT_TCP_CONNECTION_SETTING, "1ms") //1 millisecond - .build(); - - RealmConfig config = new RealmConfig("ldap_realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); - LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); - String user = "Horatio Hornblower"; - SecureString userPass = new SecureString("pass"); - - long start = System.currentTimeMillis(); - LDAPException expected = expectThrows(LDAPException.class, () -> session(sessionFactory, user, userPass)); - long time = System.currentTimeMillis() - start; - assertThat(time, lessThan(10000L)); - assertThat(expected, instanceOf(LDAPException.class)); - assertThat(expected.getCause().getMessage(), - anyOf(containsString("within the configured timeout of"), containsString("connect timed out"))); - } - public void testBindWithTemplates() throws Exception { String groupSearchBase = "o=sevenSeas"; String[] userTemplates = new String[] { diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java index d79474dadd9..d157a887c3f 100644 --- a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java +++ b/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java @@ -403,62 +403,6 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase { } } - @Network - public void testUserSearchWithActiveDirectory() throws Exception { - String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com"; - String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; - Settings settings = Settings.builder() - .put(LdapTestCase.buildLdapSettings( - new String[] { ActiveDirectorySessionFactoryTests.AD_LDAP_URL }, - Strings.EMPTY_ARRAY, groupSearchBase, LdapSearchScope.SUB_TREE, null, - true)) - .put("user_search.base_dn", userSearchBase) - .put("bind_dn", "ironman@ad.test.elasticsearch.com") - .put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD) - .put("user_search.filter", "(cn={0})") - .put("user_search.pool.enabled", randomBoolean()) - .build(); - Settings.Builder builder = Settings.builder() - .put(globalSettings); - settings.keySet().forEach(k -> { - builder.copy("xpack.security.authc.realms.ldap." + k, k, settings); - - }); - Settings fullSettings = builder.build(); - sslService = new SSLService(fullSettings, TestEnvironment.newEnvironment(fullSettings)); - RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); - LdapUserSearchSessionFactory sessionFactory = getLdapUserSearchSessionFactory(config, sslService, threadPool); - - String user = "Bruce Banner"; - try { - //auth - try (LdapSession ldap = session(sessionFactory, user, new SecureString(ActiveDirectorySessionFactoryTests.PASSWORD))) { - assertConnectionCanReconnect(ldap.getConnection()); - List groups = groups(ldap); - - assertThat(groups, containsInAnyOrder( - containsString("Avengers"), - containsString("SHIELD"), - containsString("Geniuses"), - containsString("Philanthropists"))); - } - - //lookup - try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) { - assertConnectionCanReconnect(ldap.getConnection()); - List groups = groups(ldap); - - assertThat(groups, containsInAnyOrder( - containsString("Avengers"), - containsString("SHIELD"), - containsString("Geniuses"), - containsString("Philanthropists"))); - } - } finally { - sessionFactory.close(); - } - } - public void testConnectionPoolDefaultSettings() throws Exception { String groupSearchBase = "o=sevenSeas"; String userSearchBase = "o=sevenSeas"; @@ -586,7 +530,7 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase { groupSearchBase, LdapSearchScope.SUB_TREE)) .put("user_search.base_dn", userSearchBase) .put("bind_dn", "ironman@ad.test.elasticsearch.com") - .put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD) + .put("bind_password", "password") .put("user_search.attribute", "cn") .put("timeout.tcp_connect", "500ms") .put("type", "ldap") diff --git a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HipChatServiceTests.java b/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HipChatServiceTests.java deleted file mode 100644 index 8f220e11a9a..00000000000 --- a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HipChatServiceTests.java +++ /dev/null @@ -1,226 +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.xpack.watcher.test.integration; - -import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.LicenseService; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.script.MockMustacheScriptEngine; -import org.elasticsearch.test.ESSingleNodeTestCase; -import org.elasticsearch.test.junit.annotations.Network; -import org.elasticsearch.test.junit.annotations.TestLogging; -import org.elasticsearch.xpack.core.XPackSettings; -import org.elasticsearch.xpack.core.watcher.WatcherState; -import org.elasticsearch.xpack.core.watcher.client.WatcherClient; -import org.elasticsearch.xpack.core.watcher.history.HistoryStoreField; -import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse; -import org.elasticsearch.xpack.watcher.WatcherService; -import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction; -import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition; -import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount; -import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage; -import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService; -import org.elasticsearch.xpack.watcher.notification.hipchat.SentMessages; -import org.elasticsearch.xpack.watcher.test.LocalStateWatcher; - -import java.util.Arrays; -import java.util.Collection; - -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.hipchatAction; -import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; -import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput; -import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; -import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.notNullValue; - -@Network -@TestLogging("org.elasticsearch.xpack.watcher.common.http:TRACE") -public class HipChatServiceTests extends ESSingleNodeTestCase { - - @Override - protected Collection> getPlugins() { - return Arrays.asList(LocalStateWatcher.class, MockMustacheScriptEngine.TestPlugin.class); - } - - @Override - protected Settings nodeSettings() { - return Settings.builder() - .put(super.nodeSettings()) - .put(XPackSettings.WATCHER_ENABLED.getKey(), true) - .put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial") - - // this is for the `test-watcher-integration` group level integration in HipChat - .put("xpack.notification.hipchat.account.integration_account.profile", "integration") - .put("xpack.notification.hipchat.account.integration_account.auth_token", - "huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU") - .put("xpack.notification.hipchat.account.integration_account.room", "test-watcher") - - // this is for the Watcher Test account in HipChat - .put("xpack.notification.hipchat.account.user_account.profile", "user") - .put("xpack.notification.hipchat.account.user_account.auth_token", "4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K") - - // this is for the `test-watcher-v1` notification token - .put("xpack.notification.hipchat.account.v1_account.profile", "v1") - .put("xpack.notification.hipchat.account.v1_account.auth_token", "a734baf62df618b96dda55b323fc30") - .build(); - } - - public void testSendMessageV1Account() throws Exception { - HipChatService service = getInstanceFromNode(HipChatService.class); - HipChatMessage hipChatMessage = new HipChatMessage( - "HipChatServiceTests#testSendMessage_V1Account", - new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" }, - null, // users are unsupported in v1 - "watcher-tests", - HipChatMessage.Format.TEXT, - randomFrom(HipChatMessage.Color.values()), - true); - - HipChatAccount account = service.getAccount("v1_account"); - assertThat(account, notNullValue()); - SentMessages messages = account.send(hipChatMessage, null); - assertSentMessagesAreValid(3, messages); - } - - public void testSendMessageIntegrationAccount() throws Exception { - HipChatService service = getInstanceFromNode(HipChatService.class); - HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values()); - HipChatMessage hipChatMessage = new HipChatMessage( - "HipChatServiceTests#testSendMessage_IntegrationAccount colored " + color.value(), - null, // custom rooms are unsupported by integration profiles - null, // users are unsupported by integration profiles - null, // custom "from" is not supported by integration profiles - HipChatMessage.Format.TEXT, - color, - true); - - HipChatAccount account = service.getAccount("integration_account"); - assertThat(account, notNullValue()); - SentMessages messages = account.send(hipChatMessage, null); - assertSentMessagesAreValid(1, messages); - } - - public void testSendMessageUserAccount() throws Exception { - HipChatService service = getInstanceFromNode(HipChatService.class); - HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values()); - HipChatMessage hipChatMessage = new HipChatMessage( - "HipChatServiceTests#testSendMessage_UserAccount colored " + color.value(), - new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" }, - new String[] { "watcher@elastic.co" }, - null, - HipChatMessage.Format.TEXT, - color, - false); - - HipChatAccount account = service.getAccount("user_account"); - assertThat(account, notNullValue()); - SentMessages messages = account.send(hipChatMessage, null); - assertSentMessagesAreValid(4, messages); - } - - public void testWatchWithHipChatAction() throws Exception { - assertBusy(() -> assertThat(getInstanceFromNode(WatcherService.class).state(), is(WatcherState.STARTED))); - - HipChatAccount.Profile profile = randomFrom(HipChatAccount.Profile.values()); - HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values()); - String account; - HipChatAction.Builder actionBuilder; - switch (profile) { - case USER: - account = "user_account"; - actionBuilder = hipchatAction(account, "_message") - .addRooms("test-watcher", "test-watcher-2", "test watcher with spaces") - .addUsers("watcher@elastic.co") - .setFormat(HipChatMessage.Format.TEXT) - .setColor(color) - .setNotify(false); - break; - - case INTEGRATION: - account = "integration_account"; - actionBuilder = hipchatAction(account, "_message") - .setFormat(HipChatMessage.Format.TEXT) - .setColor(color) - .setNotify(false); - break; - - default: - assertThat(profile, is(HipChatAccount.Profile.V1)); - account = "v1_account"; - actionBuilder = hipchatAction(account, "_message") - .addRooms("test-watcher", "test-watcher-2", "test watcher with spaces") - .setFrom("watcher-test") - .setFormat(HipChatMessage.Format.TEXT) - .setColor(color) - .setNotify(false); - } - - String id = randomAlphaOfLength(10); - WatcherClient watcherClient = new WatcherClient(client()); - PutWatchResponse putWatchResponse = watcherClient.preparePutWatch(id).setSource(watchBuilder() - .trigger(schedule(interval("10m"))) - .input(simpleInput("ref", "HipChatServiceTests#testWatchWithHipChatAction")) - .condition(InternalAlwaysCondition.INSTANCE) - .addAction("hipchat", actionBuilder)) - .execute().get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - watcherClient.prepareExecuteWatch(id).setRecordExecution(true).execute().actionGet(); - - client().admin().indices().prepareRefresh(HistoryStoreField.INDEX_PREFIX_WITH_TEMPLATE + "*").execute().actionGet(); - SearchResponse response = client().prepareSearch(HistoryStoreField.INDEX_PREFIX_WITH_TEMPLATE + "*") - .setSource(searchSource().query(boolQuery() - .must(termQuery("result.actions.id", "hipchat")) - .must(termQuery("result.actions.type", "hipchat")) - .must(termQuery("result.actions.status", "success")) - .must(termQuery("result.actions.hipchat.account", account)) - .must(termQuery("result.actions.hipchat.sent_messages.status", "success")))) - .get(); - - assertThat(response, notNullValue()); - assertThat(response.getHits().getTotalHits(), is(1L)); - } - - public void testDefaultValuesForColorAndFormatWorks() { - HipChatService service = getInstanceFromNode(HipChatService.class); - HipChatMessage hipChatMessage = new HipChatMessage( - "HipChatServiceTests#testSendMessage_UserAccount with default Color and text", - new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" }, - new String[] { "watcher@elastic.co" }, - null, // custom "from" is not supported by integration profiles - null, - null, - false); - - HipChatAccount account = service.getAccount("user_account"); - assertThat(account, notNullValue()); - SentMessages messages = account.send(hipChatMessage, null); - assertSentMessagesAreValid(4, messages); - } - - private void assertSentMessagesAreValid(int expectedMessageSize, SentMessages messages) { - assertThat(messages.count(), is(expectedMessageSize)); - for (SentMessages.SentMessage message : messages) { - logger.info("Request: [{}]", message.getRequest()); - logger.info("Response: [{}]", message.getResponse()); - if (message.getException() != null) { - logger.info("Exception stacktrace: [{}]", ExceptionsHelper.stackTrace(message.getException())); - } - assertThat(message.isSuccess(), is(true)); - assertThat(message.getRequest(), notNullValue()); - assertThat(message.getResponse(), notNullValue()); - assertThat(message.getResponse().status(), lessThan(300)); - } - } -} diff --git a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/PagerDutyServiceTests.java b/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/PagerDutyServiceTests.java deleted file mode 100644 index 6682892a5d8..00000000000 --- a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/PagerDutyServiceTests.java +++ /dev/null @@ -1,96 +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.xpack.watcher.test.integration; - -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.test.junit.annotations.Network; -import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse; -import org.elasticsearch.xpack.core.watcher.watch.Payload; -import org.elasticsearch.xpack.watcher.actions.pagerduty.PagerDutyAction; -import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition; -import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEvent; -import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEventContext; -import org.elasticsearch.xpack.watcher.notification.pagerduty.PagerDutyAccount; -import org.elasticsearch.xpack.watcher.notification.pagerduty.PagerDutyService; -import org.elasticsearch.xpack.watcher.notification.pagerduty.SentEvent; -import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; - -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.pagerDutyAction; -import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; -import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput; -import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; -import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.notNullValue; - -@Network -public class PagerDutyServiceTests extends AbstractWatcherIntegrationTestCase { - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal)) - .put("xpack.notification.pagerduty.account.test_account.service_api_key", "fc082467005d4072a914e0bb041882d0") - .build(); - } - - public void testSendTriggerEvent() throws Exception { - PagerDutyService service = getInstanceFromMaster(PagerDutyService.class); - - IncidentEvent event = new IncidentEvent("#testIncidentEvent()", null, null, "PagerDutyServiceTests", "_client_url", "_account", - true, new IncidentEventContext[] { - IncidentEventContext.link("https://www.elastic.co/products/x-pack/alerting", "Go to the Elastic.co Alerting website"), - IncidentEventContext.image("https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg", - "https://www.elastic.co/products/x-pack/alerting", "X-Pack-Alerting website link with log") - }, null); - - Payload payload = new Payload.Simple("_key", "_val"); - - PagerDutyAccount account = service.getAccount("test_account"); - assertThat(account, notNullValue()); - SentEvent sentEvent = account.send(event, payload); - assertThat(sentEvent, notNullValue()); - assertThat(sentEvent.successful(), is(true)); - assertThat(sentEvent.getRequest(), notNullValue()); - assertThat(sentEvent.getResponse(), notNullValue()); - assertThat(sentEvent.getResponse().status(), lessThan(300)); - } - - public void testWatchWithPagerDutyAction() throws Exception { - String account = "test_account"; - PagerDutyAction.Builder actionBuilder = pagerDutyAction(IncidentEvent - .templateBuilder("pager duty integration test").setAccount(account)); - - PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("1").setSource(watchBuilder() - .trigger(schedule(interval("10m"))) - .input(simpleInput("ref", "testWatchWithPagerDutyAction()")) - .condition(InternalAlwaysCondition.INSTANCE) - .addAction("pd", actionBuilder)) - .execute().get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - timeWarp().trigger("1"); - flush(); - refresh(); - - assertWatchWithMinimumPerformedActionsCount("1", 1L, false); - SearchResponse response = searchHistory(searchSource().query(boolQuery() - .must(termQuery("result.actions.id", "pd")) - .must(termQuery("result.actions.type", "pagerduty")) - .must(termQuery("result.actions.status", "success")) - .must(termQuery("result.actions.pagerduty.sent_event.event.account", account)))); - - assertThat(response, notNullValue()); - assertHitCount(response, 1L); - } -} diff --git a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SlackServiceTests.java b/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SlackServiceTests.java deleted file mode 100644 index 5457f75ec94..00000000000 --- a/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SlackServiceTests.java +++ /dev/null @@ -1,136 +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.xpack.watcher.test.integration; - -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.test.junit.annotations.Network; -import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource; -import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse; -import org.elasticsearch.xpack.watcher.actions.slack.SlackAction; -import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition; -import org.elasticsearch.xpack.watcher.notification.slack.SentMessages; -import org.elasticsearch.xpack.watcher.notification.slack.SlackAccount; -import org.elasticsearch.xpack.watcher.notification.slack.SlackService; -import org.elasticsearch.xpack.watcher.notification.slack.message.Action; -import org.elasticsearch.xpack.watcher.notification.slack.message.Attachment; -import org.elasticsearch.xpack.watcher.notification.slack.message.SlackMessage; -import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; -import org.joda.time.DateTime; - -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS; -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.slackAction; -import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; -import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput; -import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; -import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; - -@Network -public class SlackServiceTests extends AbstractWatcherIntegrationTestCase { - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal)) - .put("xpack.notification.slack.account.test_account.url", - "https://hooks.slack.com/services/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") - .build(); - } - - public void testSendMessage() throws Exception { - SlackService service = getInstanceFromMaster(SlackService.class); - - // String style, String name, String type, String text, String url - Action action = new Action(randomFrom("primary", "danger"), "action name", "button", "Click here to visit Elastic Homepage", - "https://elastic.co"); - List actions = randomBoolean() ? null : Collections.singletonList(action); - Attachment[] attachments = new Attachment[] { - new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext `code` *bold*", "author_name", null, null, - "title あいうえお", null, "_text `code` *bold*", null, null, null, new String[] { "text", "pretext" }, actions) - }; - SlackMessage message = new SlackMessage( - "SlackServiceTests", - new String[] { "#watcher-test", "#watcher-test-2"}, // TODO once we have a dedicated test user in slack, add it here - null, - "slack integration test `testSendMessage()` " + DateTime.now(), attachments); - - SlackAccount account = service.getAccount("test_account"); - assertThat(account, notNullValue()); - SentMessages messages = account.send(message, null); - assertThat(messages.count(), is(2)); - for (SentMessages.SentMessage sentMessage : messages) { - try { - assertThat(sentMessage.getException(), is(nullValue())); - assertThat(sentMessage.getRequest(), notNullValue()); - assertThat(sentMessage.getResponse(), notNullValue()); - assertThat(sentMessage.getResponse().status(), lessThan(300)); - } catch (AssertionError e) { - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.prettyPrint(); - sentMessage.toXContent(builder, EMPTY_PARAMS); - final String messageDescription = builder.string(); - logger.warn("failed to send message. full message description: \n" + messageDescription, e); - throw e; - } - } - } - - public void testWatchWithSlackAction() throws Exception { - String account = "test_account"; - SlackAction.Builder actionBuilder = slackAction(account, SlackMessage.Template.builder() - .setText("slack integration test `testWatchWithSlackAction()` " + DateTime.now()) - .addTo("#watcher-test", "#watcher-test-2")); - - PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("1").setSource(watchBuilder() - .trigger(schedule(interval("10m"))) - .input(simpleInput("ref", "testWatchWithSlackAction()")) - .condition(InternalAlwaysCondition.INSTANCE) - .addAction("slack", actionBuilder)) - .execute().get(); - - assertThat(putWatchResponse.isCreated(), is(true)); - - timeWarp().trigger("1"); - flush(); - refresh(); - - assertWatchWithMinimumPerformedActionsCount("1", 1L, false); - - SearchResponse response = searchHistory(searchSource().query(boolQuery() - .must(termQuery("result.actions.id", "slack")) - .must(termQuery("result.actions.type", "slack")) - .must(termQuery("result.actions.slack.account", account)))); - - assertThat(response.getHits().getTotalHits(), is(1L)); - - SearchHit hit = response.getHits().getAt(0); - assertSuccess(hit, "result.actions.0.slack.sent_messages.0.status"); - assertSuccess(hit, "result.actions.0.slack.sent_messages.1.status"); - assertSuccess(hit, "result.actions.0.status"); - } - - private void assertSuccess(SearchHit hit, String path) { - XContentSource source = new XContentSource(hit.getSourceRef(), XContentType.JSON); - String json = hit.getSourceAsString(); - String message = String.format(Locale.ROOT, "Expected path [%s] to be [success], json is %s", path, json); - assertThat(message, source.getValue(path), is("success")); - } -} diff --git a/qa/smoke-test-watcher/build.gradle b/qa/smoke-test-watcher/build.gradle index 991a16007fe..05b59734048 100644 --- a/qa/smoke-test-watcher/build.gradle +++ b/qa/smoke-test-watcher/build.gradle @@ -8,13 +8,7 @@ apply plugin: 'elasticsearch.rest-test' dependencies { testCompile project(path: xpackModule('core'), configuration: 'runtime') -} - -ext { - jiraUrl = 'https://elasticsearch.atlassian.net/' - jiraUser = 'xpack-user@elastic.co' - jiraPassword = 'N9M4ea9rfy' - jiraProject = 'XWT' + testCompile project(path: xpackModule('watcher'), configuration: 'runtime') } integTestCluster { @@ -24,67 +18,4 @@ integTestCluster { setting 'xpack.ml.enabled', 'false' setting 'xpack.license.self_generated.type', 'trial' setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' - - // - // JIRA integration test settings - // - // The integration tests use a JIRA account on elasticsearch.atlassian.net. This account - // has been created by Edward Sy [edward@elastic.co]. It uses the "XPACK WATCHER TEST" - // Jira project available at https://elasticsearch.atlassian.net/projects/XWT/issues/?filter=allopenissues - // and the "xpack-user@elastic.co" username which is also an internal Google Group. - setting 'xpack.notification.jira.account.test.url', jiraUrl - setting 'xpack.notification.jira.account.test.user', jiraUser - setting 'xpack.notification.jira.account.test.password', jiraPassword - setting 'xpack.notification.jira.account.test.issue_defaults.project.key', jiraProject - setting 'xpack.notification.jira.account.test.issue_defaults.labels', ['integration-tests', project.version] -} - -/** Clean up JIRA after tests: delete all created issues **/ -task cleanJira(type: DefaultTask) { - doLast { - def issues = jiraIssues(jiraProject) - assert issues instanceof List - issues.forEach { - // See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue - logger.debug("Deleting JIRA issue [${it}]") - jiraHttpRequest("issue/${it}", "DELETE", 204) - } - } -} -integTestRunner.finalizedBy cleanJira - -/** List all issues associated to a given Jira project **/ -def jiraIssues(String projectKey) { - // See https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search - def response = jiraHttpRequest("search?maxResults=100&fields=id,self,key&jql=project%3D${projectKey}", "GET", 200) - assert response.issues instanceof List - return response.issues.findAll {it.key.startsWith(projectKey)}.collect {it.key} -} - -/** Execute a HTTP request against the Jira server instance **/ -def jiraHttpRequest(String endpoint, String method, int successCode) { - HttpsURLConnection connection = null; - try { - byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8); - connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection(); - connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials)); - connection.setRequestMethod(method); - connection.connect(); - - if (connection.getResponseCode() == successCode) { - String response = connection.getInputStream().getText(StandardCharsets.UTF_8.name()); - if (response != null && response.length() > 0) { - return new JsonSlurper().parseText(response) - } - } else { - throw new GradleException("Unexpected response code for [${endpoint}]: got ${connection.getResponseCode()} but expected ${successCode}") - } - } catch (Exception e) { - logger.error("Failed to delete JIRA issues after test execution", e) - } finally { - if (connection != null) { - connection.disconnect(); - } - } - return null } diff --git a/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/PreventFailingBuildIT.java b/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/PreventFailingBuildIT.java deleted file mode 100644 index e41b5a7dad4..00000000000 --- a/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/PreventFailingBuildIT.java +++ /dev/null @@ -1,19 +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.smoketest; - -import org.elasticsearch.test.ESIntegTestCase; - -public class PreventFailingBuildIT extends ESIntegTestCase { - - public void testSoThatTestsDoNotFail() { - // Noop - - // This is required because SmokeTestWatcherClientYamlTestSuiteIT - // requires network access, so if network tests are not enable no - // tests will be run in the entire project and all tests will fail. - } -} diff --git a/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java b/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java index 30e5654e475..3ff49260e95 100644 --- a/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java +++ b/qa/smoke-test-watcher/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java @@ -7,7 +7,6 @@ package org.elasticsearch.smoketest; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; @@ -25,8 +24,6 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.is; -/** Runs rest tests against external cluster */ -@Network // Needed to access to an external Jira server public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { diff --git a/qa/third-party/active-directory/build.gradle b/qa/third-party/active-directory/build.gradle new file mode 100644 index 00000000000..3cbba2c3b2c --- /dev/null +++ b/qa/third-party/active-directory/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'elasticsearch.standalone-test' + +dependencies { + testCompile project(xpackModule('security')) + testCompile project(path: xpackModule('security'), configuration: 'testArtifacts') +} + +// add test resources from security, so certificate tool tests can use example certs +sourceSets.test.resources.srcDirs(project(xpackModule('security')).sourceSets.test.resources.srcDirs) + +// we have to repeate these patterns because the security test resources are effectively in the src of this project +forbiddenPatterns { + exclude '**/*.key' + exclude '**/*.p12' + exclude '**/*.der' +} + +test { + /* + * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each + * other if we allow them to set the number of available processors as it's set-once in Netty. + */ + systemProperty 'es.set.netty.runtime.available.processors', 'false' +} + +// these are just tests, no need to audit +thirdPartyAudit.enabled = false diff --git a/plugin/security/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsIT.java similarity index 97% rename from plugin/security/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsTests.java rename to qa/third-party/active-directory/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsIT.java index cc5908ae106..f5067d23c11 100644 --- a/plugin/security/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsTests.java +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/integration/ldap/ActiveDirectoryRunAsIT.java @@ -29,7 +29,7 @@ import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswo * This tests that "run-as" works on LDAP/AD realms */ @Network -public class ActiveDirectoryRunAsTests extends AbstractAdLdapRealmTestCase { +public class ActiveDirectoryRunAsIT extends AbstractAdLdapRealmTestCase { @BeforeClass public static void selectRealmConfig() { diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/AbstractActiveDirectoryIntegTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/AbstractActiveDirectoryIntegTests.java similarity index 100% rename from plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/AbstractActiveDirectoryIntegTests.java rename to qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/AbstractActiveDirectoryIntegTests.java diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java similarity index 99% rename from plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java rename to qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java index 5b65568a824..c19599af00f 100644 --- a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryGroupsResolverTests.java @@ -27,6 +27,7 @@ public class ActiveDirectoryGroupsResolverTests extends GroupsResolverTestCase { private static final String BRUCE_BANNER_DN = "cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; + @SuppressWarnings("unchecked") public void testResolveSubTree() throws Exception { Settings settings = Settings.builder() .put("group_search.scope", LdapSearchScope.SUB_TREE) diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java similarity index 95% rename from plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java rename to qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java index d52edb67cb4..9e20891f2aa 100644 --- a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectorySessionFactoryTests.java @@ -85,6 +85,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI } } + @SuppressWarnings("unchecked") public void testNetbiosAuth() throws Exception { final String adUrl = randomFrom("ldap://54.213.145.20:3268", "ldaps://54.213.145.20:3269", AD_LDAP_URL); RealmConfig config = new RealmConfig("ad-test", buildAdSettings(adUrl, AD_DOMAIN, false), globalSettings, @@ -117,8 +118,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI .put("ssl.verification_mode", VerificationMode.CERTIFICATE) .put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms") .build(); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { PlainActionFuture> groups = new PlainActionFuture<>(); @@ -147,8 +148,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI public void testAuthenticate() throws Exception { Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", LdapSearchScope.ONE_LEVEL, false); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { String userName = "hulk"; @@ -201,8 +202,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI "CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com") .put(ActiveDirectorySessionFactorySettings.AD_GROUP_SEARCH_SCOPE_SETTING, LdapSearchScope.BASE) .build(); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { String userName = "hulk"; @@ -219,8 +220,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI public void testAuthenticateWithUserPrincipalName() throws Exception { Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", LdapSearchScope.ONE_LEVEL, false); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { //Login with the UserPrincipalName @@ -237,11 +238,12 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI } } + @SuppressWarnings("unchecked") public void testAuthenticateWithSAMAccountName() throws Exception { Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", LdapSearchScope.ONE_LEVEL, false); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { //login with sAMAccountName @@ -267,8 +269,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI .put(ActiveDirectorySessionFactorySettings.AD_USER_SEARCH_FILTER_SETTING, "(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))") .build(); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { //Login with the UserPrincipalName @@ -408,8 +410,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI .put(LdapTestCase.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) .put("ssl.verification_mode", VerificationMode.FULL) .build(); - RealmConfig config = - new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(globalSettings)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); String user = "Bruce Banner"; diff --git a/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryUserSearchSessionFactoryTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryUserSearchSessionFactoryTests.java new file mode 100644 index 00000000000..20001292bad --- /dev/null +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryUserSearchSessionFactoryTests.java @@ -0,0 +1,138 @@ +/* + * 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.xpack.security.authc.ldap; + +import com.unboundid.ldap.sdk.LDAPException; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.MockSecureSettings; +import org.elasticsearch.common.settings.SecureString; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.env.Environment; +import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.threadpool.TestThreadPool; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope; +import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession; +import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase; +import org.junit.After; +import org.junit.Before; + +import java.nio.file.Path; +import java.util.List; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasItems; + +public class ActiveDirectoryUserSearchSessionFactoryTests extends LdapTestCase { + + private SSLService sslService; + private Settings globalSettings; + private ThreadPool threadPool; + + @Before + public void init() throws Exception { + Path keystore = getDataPath("support/ADtrust.jks"); + Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build()); + /* + * Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext. + * If we re-use a SSLContext, previously connected sessions can get re-established which breaks hostname + * verification tests since a re-established connection does not perform hostname verification. + */ + + globalSettings = Settings.builder() + .put("path.home", createTempDir()) + .put("xpack.ssl.truststore.path", keystore) + .setSecureSettings(newSecureSettings("xpack.ssl.truststore.secure_password", "changeit")) + .build(); + sslService = new SSLService(globalSettings, env); + threadPool = new TestThreadPool("LdapUserSearchSessionFactoryTests"); + } + + @After + public void shutdown() throws InterruptedException { + terminate(threadPool); + } + + @Network + @SuppressWarnings("unchecked") + public void testUserSearchWithActiveDirectory() throws Exception { + String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com"; + String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; + Settings settings = Settings.builder() + .put(LdapTestCase.buildLdapSettings( + new String[] { ActiveDirectorySessionFactoryTests.AD_LDAP_URL }, + Strings.EMPTY_ARRAY, groupSearchBase, LdapSearchScope.SUB_TREE, null, + true)) + .put("user_search.base_dn", userSearchBase) + .put("bind_dn", "ironman@ad.test.elasticsearch.com") + .put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD) + .put("user_search.filter", "(cn={0})") + .put("user_search.pool.enabled", randomBoolean()) + .build(); + Settings.Builder builder = Settings.builder() + .put(globalSettings); + settings.keySet().forEach(k -> { + builder.copy("xpack.security.authc.realms.ldap." + k, k, settings); + + }); + Settings fullSettings = builder.build(); + sslService = new SSLService(fullSettings, TestEnvironment.newEnvironment(fullSettings)); + RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings, + TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + LdapUserSearchSessionFactory sessionFactory = getLdapUserSearchSessionFactory(config, sslService, threadPool); + + String user = "Bruce Banner"; + try { + //auth + try (LdapSession ldap = session(sessionFactory, user, new SecureString(ActiveDirectorySessionFactoryTests.PASSWORD))) { + assertConnectionCanReconnect(ldap.getConnection()); + List groups = groups(ldap); + + assertThat(groups, containsInAnyOrder( + containsString("Avengers"), + containsString("SHIELD"), + containsString("Geniuses"), + containsString("Philanthropists"))); + } + + //lookup + try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) { + assertConnectionCanReconnect(ldap.getConnection()); + List groups = groups(ldap); + + assertThat(groups, containsInAnyOrder( + containsString("Avengers"), + containsString("SHIELD"), + containsString("Geniuses"), + containsString("Philanthropists"))); + } + } finally { + sessionFactory.close(); + } + } + + static LdapUserSearchSessionFactory getLdapUserSearchSessionFactory(RealmConfig config, SSLService sslService, ThreadPool threadPool) + throws LDAPException { + LdapUserSearchSessionFactory sessionFactory = new LdapUserSearchSessionFactory(config, sslService, threadPool); + if (sessionFactory.getConnectionPool() != null) { + // don't use this in production + // used here to catch bugs that might get masked by an automatic retry + sessionFactory.getConnectionPool().setRetryFailedOperationsDueToInvalidConnections(false); + } + return sessionFactory; + } + + private MockSecureSettings newSecureSettings(String key, String value) { + MockSecureSettings secureSettings = new MockSecureSettings(); + secureSettings.setString(key, value); + return secureSettings; + } +} diff --git a/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/PreventFailingTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/PreventFailingTests.java new file mode 100644 index 00000000000..a0a407a503a --- /dev/null +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/PreventFailingTests.java @@ -0,0 +1,17 @@ +/* + * 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.xpack.security.authc.ldap; + +import org.elasticsearch.test.ESTestCase; + +public class PreventFailingTests extends ESTestCase { + + public void testPreventFailingWithNetworkingDisabled() { + // Noop + // This is required because if network tests are not enabled no tests will be run in the entire project and all tests will fail. + } + +} diff --git a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java similarity index 97% rename from plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java rename to qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java index a7ad54876db..e5a9ab43cc5 100644 --- a/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java +++ b/qa/third-party/active-directory/src/test/java/org/elasticsearch/xpack/security/authc/ldap/UserAttributeGroupsResolverTests.java @@ -27,6 +27,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase { public static final String BRUCE_BANNER_DN = "cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; + @SuppressWarnings("unchecked") public void testResolve() throws Exception { //falling back on the 'memberOf' attribute UserAttributeGroupsResolver resolver = new UserAttributeGroupsResolver(Settings.EMPTY); @@ -39,6 +40,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase { containsString("Philanthropists"))); } + @SuppressWarnings("unchecked") public void testResolveFromPreloadedAttributes() throws Exception { SearchRequest preSearch = new SearchRequest(BRUCE_BANNER_DN, SearchScope.BASE, LdapUtils.OBJECT_CLASS_PRESENCE_FILTER, "memberOf"); final Collection attributes = ldapConnection.searchForEntry(preSearch).getAttributes(); @@ -53,6 +55,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase { containsString("Philanthropists"))); } + @SuppressWarnings("unchecked") public void testResolveCustomGroupAttribute() throws Exception { Settings settings = Settings.builder() .put("user_group_attribute", "seeAlso") diff --git a/qa/third-party/build.gradle b/qa/third-party/build.gradle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/third-party/hipchat/build.gradle b/qa/third-party/hipchat/build.gradle new file mode 100644 index 00000000000..e700efe8e85 --- /dev/null +++ b/qa/third-party/hipchat/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.rest-test' + +dependencies { + testCompile project(path: xpackModule('core'), configuration: 'runtime') + testCompile project(path: xpackModule('watcher'), configuration: 'runtime') +} + +String integrationAccountPropertyName = 'xpack.notification.hipchat.auth_token_integration' +System.setProperty(integrationAccountPropertyName, 'huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU') +String userAccountPropertyName = 'xpack.notification.hipchat.auth_token_user' +System.setProperty(userAccountPropertyName, '4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K') +String v1AccountPropertyName = 'xpack.notification.hipchat.auth_token_v1' +System.setProperty(v1AccountPropertyName, 'a734baf62df618b96dda55b323fc30') + +integTestCluster { + plugin xpackProject('plugin').path + setting 'xpack.security.enabled', 'false' + setting 'xpack.monitoring.enabled', 'false' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' + + // hipchat + setting 'xpack.notification.hipchat.account.integration_account.profile', 'integration' + setting 'xpack.notification.hipchat.account.integration_account.room', 'test-watcher' + setting 'xpack.notification.hipchat.account.integration_account.auth_token', System.getProperty(integrationAccountPropertyName) + setting 'xpack.notification.hipchat.account.user_account.profile', 'user' + setting 'xpack.notification.hipchat.account.user_account.auth_token', System.getProperty(userAccountPropertyName) + setting 'xpack.notification.hipchat.account.v1_account.profile', 'v1' + setting 'xpack.notification.hipchat.account.v1_account.auth_token', System.getProperty(v1AccountPropertyName) +} + +if (!System.getProperty(integrationAccountPropertyName) || !System.getProperty(userAccountPropertyName) || + !System.getProperty(v1AccountPropertyName) || !System.getProperty('tests.network')) { + + integTest.enabled = false +} diff --git a/qa/third-party/hipchat/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java b/qa/third-party/hipchat/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java new file mode 100644 index 00000000000..30e5654e475 --- /dev/null +++ b/qa/third-party/hipchat/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java @@ -0,0 +1,78 @@ +/* + * 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.smoketest; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; +import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; +import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; +import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; +import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.hamcrest.Matchers.is; + +/** Runs rest tests against external cluster */ +@Network // Needed to access to an external Jira server +public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { + + public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { + super(testCandidate); + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return ESClientYamlSuiteTestCase.createParameters(); + } + + @Before + public void startWatcher() throws Exception { + final List watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES); + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap()); + + for (String template : watcherTemplates) { + ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template", + singletonMap("name", template), emptyList(), emptyMap()); + assertThat(templateExistsResponse.getStatusCode(), is(200)); + } + + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("started")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } + + @After + public void stopWatcher() throws Exception { + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap()); + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("stopped")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } +} diff --git a/qa/third-party/hipchat/src/test/resources/rest-api-spec/test/hipchat/10_hipchat.yml b/qa/third-party/hipchat/src/test/resources/rest-api-spec/test/hipchat/10_hipchat.yml new file mode 100644 index 00000000000..9277ddae6c6 --- /dev/null +++ b/qa/third-party/hipchat/src/test/resources/rest-api-spec/test/hipchat/10_hipchat.yml @@ -0,0 +1,276 @@ +--- +"Test Hipchat v1 account Action": + - do: + cluster.health: + wait_for_status: yellow + + - do: + xpack.watcher.put_watch: + id: "hipchat_v1_watch" + body: > + { + "trigger": { + "schedule": { + "interval": "1d" + } + }, + "input": { + "simple": { + "foo": "something from input" + } + }, + "actions": { + "my_hipchat_action": { + "hipchat": { + "account": "v1_account", + "message": { + "from" : "watcher-tests", + "room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"], + "body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the v1 account", + "format": "text", + "color": "red", + "notify": true + } + } + } + } + } + + - do: + xpack.watcher.execute_watch: + id: "hipchat_v1_watch" + body: > + { + "record_execution": true + } + + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "my_hipchat_action" } + - match: { watch_record.result.actions.0.type: "hipchat" } + - match: { watch_record.result.actions.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.account: "v1_account" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" } + + # Waits for the watcher history index to be available + - do: + cluster.health: + index: ".watcher-history-*" + wait_for_no_relocating_shards: true + timeout: 60s + + - do: + indices.refresh: {} + + - do: + search: + index: ".watcher-history-*" + body: > + { + "query" : { + "term" : { + "watch_id" : "hipchat_v1_watch" + } + } + } + + - match: { hits.total: 1 } + - match: { hits.hits.0._source.state: "executed" } + - match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" } + - match: { hits.hits.0._source.result.actions.0.type: "hipchat" } + - match: { hits.hits.0._source.result.actions.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.account: "v1_account" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" } + +--- +"Test Hipchat integration account Action": + - do: + cluster.health: + wait_for_status: yellow + + # custom rooms, custom users and custom from are not allowed for this account type to be configured + - do: + xpack.watcher.put_watch: + id: "hipchat_integration_account_watch" + body: > + { + "trigger": { + "schedule": { + "interval": "1d" + } + }, + "input": { + "simple": { + "foo": "something from input" + } + }, + "actions": { + "my_hipchat_action": { + "hipchat": { + "account": "integration_account", + "message": { + "body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the integration account", + "format": "text", + "color": "red", + "notify": true + } + } + } + } + } + + - do: + xpack.watcher.execute_watch: + id: "hipchat_integration_account_watch" + body: > + { + "record_execution": true + } + + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "my_hipchat_action" } + - match: { watch_record.result.actions.0.type: "hipchat" } + - match: { watch_record.result.actions.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.account: "integration_account" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + + # Waits for the watcher history index to be available + - do: + cluster.health: + index: ".watcher-history-*" + wait_for_no_relocating_shards: true + timeout: 60s + + - do: + indices.refresh: {} + + - do: + search: + index: ".watcher-history-*" + body: > + { + "query" : { + "term" : { + "watch_id" : "hipchat_integration_account_watch" + } + } + } + + - match: { hits.total: 1 } + - match: { hits.hits.0._source.state: "executed" } + - match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" } + - match: { hits.hits.0._source.result.actions.0.type: "hipchat" } + - match: { hits.hits.0._source.result.actions.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.account: "integration_account" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" } + +--- +"Test Hipchat user account Action": + - do: + cluster.health: + wait_for_status: yellow + + - do: + xpack.watcher.put_watch: + id: "hipchat_user_account_watch" + body: > + { + "trigger": { + "schedule": { + "interval": "1d" + } + }, + "input": { + "simple": { + "foo": "something from input" + } + }, + "actions": { + "my_hipchat_action": { + "hipchat": { + "account": "user_account", + "message": { + "user" : [ "watcher@elastic.co" ], + "room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"], + "body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the user_account test. bold", + "format": "html" + } + } + } + } + } + + - do: + xpack.watcher.execute_watch: + id: "hipchat_user_account_watch" + body: > + { + "record_execution": true + } + + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "my_hipchat_action" } + - match: { watch_record.result.actions.0.type: "hipchat" } + - match: { watch_record.result.actions.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.account: "user_account" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" } + - match: { watch_record.result.actions.0.hipchat.sent_messages.3.status: "success" } + + # Waits for the watcher history index to be available + - do: + cluster.health: + index: ".watcher-history-*" + wait_for_no_relocating_shards: true + timeout: 60s + + - do: + indices.refresh: {} + + - do: + search: + index: ".watcher-history-*" + body: > + { + "query" : { + "term" : { + "watch_id" : "hipchat_user_account_watch" + } + } + } + + - match: { hits.total: 1 } + - match: { hits.hits.0._source.state: "executed" } + - match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" } + - match: { hits.hits.0._source.result.actions.0.type: "hipchat" } + - match: { hits.hits.0._source.result.actions.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.account: "user_account" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" } + - match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" } + + diff --git a/qa/third-party/jira/build.gradle b/qa/third-party/jira/build.gradle new file mode 100644 index 00000000000..0cc6709c58d --- /dev/null +++ b/qa/third-party/jira/build.gradle @@ -0,0 +1,107 @@ +import groovy.json.JsonSlurper + +import javax.net.ssl.HttpsURLConnection +import java.nio.charset.StandardCharsets + +apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.rest-test' + +dependencies { + testCompile project(path: xpackModule('core'), configuration: 'runtime') + testCompile project(path: xpackModule('watcher'), configuration: 'runtime') +} + +ext { + jiraUrlPropertyName = 'xpack.notification.jira.url' + jiraUserPropertyName = 'xpack.notification.jira.user' + jiraPasswordPropertyName = 'xpack.notification.jira.password' + jiraProjectPropertyName = 'xpack.notification.jira.project' +} + +System.setProperty(jiraUrlPropertyName, 'https://elasticsearch.atlassian.net/') +System.setProperty(jiraUserPropertyName, 'xpack-user@elastic.co') +System.setProperty(jiraPasswordPropertyName, 'N9M4ea9rfy') +System.setProperty(jiraProjectPropertyName, 'XWT') + +integTestCluster { + plugin xpackProject('plugin').path + setting 'xpack.security.enabled', 'false' + setting 'xpack.monitoring.enabled', 'false' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' + + // + // JIRA integration test settings + // + // The integration tests use a JIRA account on elasticsearch.atlassian.net. This account + // has been created by Edward Sy [edward@elastic.co]. It uses the "XPACK WATCHER TEST" + // Jira project available at https://elasticsearch.atlassian.net/projects/XWT/issues/?filter=allopenissues + // and the "xpack-user@elastic.co" username which is also an internal Google Group. + setting 'xpack.notification.jira.account.test.url', System.getProperty(jiraUrlPropertyName) + setting 'xpack.notification.jira.account.test.user', System.getProperty(jiraUserPropertyName) + setting 'xpack.notification.jira.account.test.password', System.getProperty(jiraPasswordPropertyName) + setting 'xpack.notification.jira.account.test.issue_defaults.project.key', System.getProperty(jiraProjectPropertyName) + setting 'xpack.notification.jira.account.test.issue_defaults.labels', ['integration-tests', project.version] +} + +/** Clean up JIRA after tests: delete all created issues **/ +task cleanJira(type: DefaultTask) { + doLast { + def issues = jiraIssues(System.getProperty(jiraProjectPropertyName)) + assert issues instanceof List + issues.forEach { + // See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue + logger.debug("Deleting JIRA issue [${it}]") + jiraHttpRequest("issue/${it}", "DELETE", 204) + } + } +} + +// require network access for this one, exit early instead of starting up the cluster if we dont have network +if (!System.getProperty(jiraUrlPropertyName) || !System.getProperty(jiraUserPropertyName) || + !System.getProperty(jiraPasswordPropertyName) || !System.getProperty(jiraProjectPropertyName) || + !System.getProperty('tests.network')) { + integTest.enabled = false +} else { + integTestRunner.finalizedBy cleanJira +} + +/** List all issues associated to a given Jira project **/ +def jiraIssues(projectKey) { + // See https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search + def response = jiraHttpRequest("search?maxResults=100&fields=id,self,key&jql=project%3D${projectKey}", "GET", 200) + assert response.issues instanceof List + return response.issues.findAll {it.key.startsWith(projectKey)}.collect {it.key} +} + +/** Execute a HTTP request against the Jira server instance **/ +def jiraHttpRequest(String endpoint, String method, int successCode) { + HttpsURLConnection connection = null; + try { + def jiraUser = System.getProperty(jiraUserPropertyName) + def jiraPassword = System.getProperty(jiraPasswordPropertyName) + def jiraUrl = System.getProperty(jiraUrlPropertyName) + byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8); + connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection(); + connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials)); + connection.setRequestMethod(method); + connection.connect(); + + if (connection.getResponseCode() == successCode) { + String response = connection.getInputStream().getText(StandardCharsets.UTF_8.name()); + if (response != null && response.length() > 0) { + return new JsonSlurper().parseText(response) + } + } else { + throw new GradleException("Unexpected response code for [${endpoint}]: got ${connection.getResponseCode()} but expected ${successCode}") + } + } catch (Exception e) { + logger.error("Failed to delete JIRA issues after test execution", e) + } finally { + if (connection != null) { + connection.disconnect(); + } + } + return null +} diff --git a/qa/third-party/jira/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java b/qa/third-party/jira/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java new file mode 100644 index 00000000000..30e5654e475 --- /dev/null +++ b/qa/third-party/jira/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java @@ -0,0 +1,78 @@ +/* + * 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.smoketest; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; +import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; +import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; +import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; +import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.hamcrest.Matchers.is; + +/** Runs rest tests against external cluster */ +@Network // Needed to access to an external Jira server +public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { + + public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { + super(testCandidate); + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return ESClientYamlSuiteTestCase.createParameters(); + } + + @Before + public void startWatcher() throws Exception { + final List watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES); + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap()); + + for (String template : watcherTemplates) { + ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template", + singletonMap("name", template), emptyList(), emptyMap()); + assertThat(templateExistsResponse.getStatusCode(), is(200)); + } + + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("started")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } + + @After + public void stopWatcher() throws Exception { + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap()); + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("stopped")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } +} diff --git a/qa/smoke-test-watcher/src/test/resources/rest-api-spec/test/actions/20_jira.yml b/qa/third-party/jira/src/test/resources/rest-api-spec/test/jira/10_jira.yml similarity index 100% rename from qa/smoke-test-watcher/src/test/resources/rest-api-spec/test/actions/20_jira.yml rename to qa/third-party/jira/src/test/resources/rest-api-spec/test/jira/10_jira.yml diff --git a/qa/third-party/pagerduty/build.gradle b/qa/third-party/pagerduty/build.gradle new file mode 100644 index 00000000000..60606b32a01 --- /dev/null +++ b/qa/third-party/pagerduty/build.gradle @@ -0,0 +1,39 @@ +apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.rest-test' + +dependencies { + testCompile project(path: xpackModule('core'), configuration: 'runtime') + testCompile project(path: xpackModule('watcher'), configuration: 'runtime') +} + +String pagerDutyPropertyName = 'xpack.notification.pagerduty.service_api_key' +System.setProperty(pagerDutyPropertyName, 'fc082467005d4072a914e0bb041882d0') + +ext { + jiraUrl = 'https://elasticsearch.atlassian.net/' + jiraUser = 'xpack-user@elastic.co' + jiraPassword = 'N9M4ea9rfy' + jiraProject = 'XWT' + slackUrl = 'https://hooks.slack.com/services/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' + pagerDutyUrl = 'fc082467005d4072a914e0bb041882d0' + hipchatUserAuthToken = '4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K' + hipchatIntegrationAuthToken = 'huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU' + hipchatV1AuthToken = 'a734baf62df618b96dda55b323fc30' +} + +integTestCluster { + plugin xpackProject('plugin').path + setting 'xpack.security.enabled', 'false' + setting 'xpack.monitoring.enabled', 'false' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' + + // pagerduty + setting 'xpack.notification.pagerduty.account.test_account.service_api_key', System.getProperty(pagerDutyPropertyName) +} + +// require network access for this one, exit early instead of starting up the cluster if we dont have network +if (!System.getProperty(pagerDutyPropertyName) || !System.getProperty('tests.network')) { + integTest.enabled = false +} diff --git a/qa/third-party/pagerduty/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java b/qa/third-party/pagerduty/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java new file mode 100644 index 00000000000..30e5654e475 --- /dev/null +++ b/qa/third-party/pagerduty/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java @@ -0,0 +1,78 @@ +/* + * 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.smoketest; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; +import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; +import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; +import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; +import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.hamcrest.Matchers.is; + +/** Runs rest tests against external cluster */ +@Network // Needed to access to an external Jira server +public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { + + public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { + super(testCandidate); + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return ESClientYamlSuiteTestCase.createParameters(); + } + + @Before + public void startWatcher() throws Exception { + final List watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES); + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap()); + + for (String template : watcherTemplates) { + ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template", + singletonMap("name", template), emptyList(), emptyMap()); + assertThat(templateExistsResponse.getStatusCode(), is(200)); + } + + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("started")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } + + @After + public void stopWatcher() throws Exception { + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap()); + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("stopped")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } +} diff --git a/qa/third-party/pagerduty/src/test/resources/rest-api-spec/test/pagerduty/10_pagerduty.yml b/qa/third-party/pagerduty/src/test/resources/rest-api-spec/test/pagerduty/10_pagerduty.yml new file mode 100644 index 00000000000..47706e5f1e7 --- /dev/null +++ b/qa/third-party/pagerduty/src/test/resources/rest-api-spec/test/pagerduty/10_pagerduty.yml @@ -0,0 +1,103 @@ +--- +"Test PagerDuty Action": + - do: + cluster.health: + wait_for_status: yellow + + - do: + xpack.watcher.put_watch: + id: "pagerduty_watch" + body: > + { + "trigger": { + "schedule": { + "interval": "1d" + } + }, + "input": { + "simple": { + } + }, + "actions": { + "my_pagerduty_action": { + "pagerduty": { + "description": "#testIncidentEvent()", + "client": "PagerDutyServiceTests", + "client_url": "_client_url", + "account" : "_account", + "contexts" : [ + { + "type": "link", + "href": "https://www.elastic.co/products/x-pack/alerting", + "text": "Go to the Elastic.co Alerting website" + }, + { + "type": "image", + "src": "https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg", + "href": "https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg", + "alt": "X-Pack-Alerting website link with log" + } + ] + } + } + } + } + + - do: + xpack.watcher.execute_watch: + id: "pagerduty_watch" + body: > + { + "record_execution": true + } + + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "my_pagerduty_action" } + - match: { watch_record.result.actions.0.type: "pagerduty" } + - match: { watch_record.result.actions.0.status: "success" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.account: "_account" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.incident_key: "pagerduty_watch" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.description: "#testIncidentEvent()" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.client: "PagerDutyServiceTests" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.client_url: "_client_url" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.attach_payload: false } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.contexts.0.type: "link" } + - match: { watch_record.result.actions.0.pagerduty.sent_event.event.contexts.1.type: "image" } + + # Waits for the watcher history index to be available + - do: + cluster.health: + index: ".watcher-history-*" + wait_for_no_relocating_shards: true + timeout: 60s + + - do: + indices.refresh: {} + + - do: + search: + index: ".watcher-history-*" + body: > + { + "query" : { + "term" : { + "watch_id" : "pagerduty_watch" + } + } + } + + - match: { hits.total: 1 } + - match: { hits.hits.0._source.state: "executed" } + - match: { hits.hits.0._source.result.actions.0.id: "my_pagerduty_action" } + - match: { hits.hits.0._source.result.actions.0.type: "pagerduty" } + - match: { hits.hits.0._source.result.actions.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.account: "_account" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.incident_key: "pagerduty_watch" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.description: "#testIncidentEvent()" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.client: "PagerDutyServiceTests" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.client_url: "_client_url" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.attach_payload: false } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.contexts.0.type: "link" } + - match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.contexts.1.type: "image" } + diff --git a/qa/third-party/slack/build.gradle b/qa/third-party/slack/build.gradle new file mode 100644 index 00000000000..6522c5a1f06 --- /dev/null +++ b/qa/third-party/slack/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'elasticsearch.standalone-rest-test' +apply plugin: 'elasticsearch.rest-test' + +dependencies { + testCompile project(path: xpackModule('core'), configuration: 'runtime') + testCompile project(path: xpackModule('watcher'), configuration: 'runtime') +} + +String slackPropertyName = 'xpack.notification.slack.url' +System.setProperty(slackPropertyName, 'https://hooks.slack.com/services/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') + +integTestCluster { + plugin xpackProject('plugin').path + setting 'xpack.security.enabled', 'false' + setting 'xpack.monitoring.enabled', 'false' + setting 'xpack.ml.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' + + setting 'xpack.notification.slack.account.test_account.url', System.getProperty(slackPropertyName) +} + +// require network access for this one, exit early instead of starting up the cluster if we dont have network +if (!System.getProperty(slackPropertyName) || !System.getProperty('tests.network')) { + integTest.enabled = false +} diff --git a/qa/third-party/slack/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java b/qa/third-party/slack/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java new file mode 100644 index 00000000000..30e5654e475 --- /dev/null +++ b/qa/third-party/slack/src/test/java/org/elasticsearch/smoketest/SmokeTestWatcherClientYamlTestSuiteIT.java @@ -0,0 +1,78 @@ +/* + * 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.smoketest; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; +import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; +import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; +import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; +import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.hamcrest.Matchers.is; + +/** Runs rest tests against external cluster */ +@Network // Needed to access to an external Jira server +public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { + + public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { + super(testCandidate); + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return ESClientYamlSuiteTestCase.createParameters(); + } + + @Before + public void startWatcher() throws Exception { + final List watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES); + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap()); + + for (String template : watcherTemplates) { + ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template", + singletonMap("name", template), emptyList(), emptyMap()); + assertThat(templateExistsResponse.getStatusCode(), is(200)); + } + + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("started")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } + + @After + public void stopWatcher() throws Exception { + assertBusy(() -> { + try { + getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap()); + ClientYamlTestResponse response = + getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap()); + String state = (String) response.evaluate("stats.0.watcher_state"); + assertThat(state, is("stopped")); + } catch (IOException e) { + throw new AssertionError(e); + } + }); + } +} diff --git a/qa/third-party/slack/src/test/resources/rest-api-spec/test/slack/10_slack.yml b/qa/third-party/slack/src/test/resources/rest-api-spec/test/slack/10_slack.yml new file mode 100644 index 00000000000..3b04ba71675 --- /dev/null +++ b/qa/third-party/slack/src/test/resources/rest-api-spec/test/slack/10_slack.yml @@ -0,0 +1,109 @@ +--- +"Test Slack Action": + - do: + cluster.health: + wait_for_status: yellow + + - do: + xpack.watcher.put_watch: + id: "slack_watch" + body: > + { + "trigger": { + "schedule": { + "interval": "1d" + } + }, + "input": { + "simple": { + "foo" : "something from input" + } + }, + "actions": { + "my_slack_action": { + "slack": { + "account": "test_account", + "message": { + "from": "SlackServiceTests", + "to": [ + "#watcher-test", "#watcher-test-2" + ], + "text": "slack integration test {{ctx.trigger.triggered_time}}", + "attachments": [ + { + "title": "title あいうえお", + "text": "From input: {{ctx.payload.foo}} - other testing: :facepalm: also `code` and *bold*", + "color": "warning", + "author_name" : "your friendly slack integration test" + }, + { + "title" : "attachment with action", + "text" : "button test", + "actions" : [ + { + "name" : "action name", + "style" : "danger", + "type" : "button", + "text" : "Button to go to elastic.co", + "url" : "https://elastic.co" + } + ] + } + ] + } + } + } + } + } + + - do: + xpack.watcher.execute_watch: + id: "slack_watch" + body: > + { + "record_execution": true + } + + - match: { watch_record.trigger_event.type: "manual" } + - match: { watch_record.state: "executed" } + - match: { watch_record.result.actions.0.id: "my_slack_action" } + - match: { watch_record.result.actions.0.type: "slack" } + - match: { watch_record.result.actions.0.status: "success" } + - match: { watch_record.result.actions.0.slack.account: "test_account" } + - match: { watch_record.result.actions.0.slack.sent_messages.0.to: "#watcher-test" } + - match: { watch_record.result.actions.0.slack.sent_messages.1.to: "#watcher-test-2" } + - match: { watch_record.result.actions.0.slack.sent_messages.0.status: "success" } + - match: { watch_record.result.actions.0.slack.sent_messages.1.status: "success" } + + # Waits for the watcher history index to be available + - do: + cluster.health: + index: ".watcher-history-*" + wait_for_no_relocating_shards: true + timeout: 60s + + - do: + indices.refresh: {} + + - do: + search: + index: ".watcher-history-*" + body: > + { + "query" : { + "term" : { + "watch_id" : "slack_watch" + } + } + } + + - match: { hits.total: 1 } + - match: { hits.hits.0._source.state: "executed" } + - match: { hits.hits.0._source.result.actions.0.id: "my_slack_action" } + - match: { hits.hits.0._source.result.actions.0.type: "slack" } + - match: { hits.hits.0._source.result.actions.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.slack.account: "test_account" } + - match: { hits.hits.0._source.result.actions.0.slack.sent_messages.0.to: "#watcher-test" } + - match: { hits.hits.0._source.result.actions.0.slack.sent_messages.1.to: "#watcher-test-2" } + - match: { hits.hits.0._source.result.actions.0.slack.sent_messages.0.status: "success" } + - match: { hits.hits.0._source.result.actions.0.slack.sent_messages.1.status: "success" }