Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 409DF200C1C for ; Wed, 15 Feb 2017 19:57:27 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 3F649160B4D; Wed, 15 Feb 2017 18:57:27 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 929CC160B77 for ; Wed, 15 Feb 2017 19:57:25 +0100 (CET) Received: (qmail 85743 invoked by uid 500); 15 Feb 2017 18:57:24 -0000 Mailing-List: contact commits-help@brooklyn.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.apache.org Delivered-To: mailing list commits@brooklyn.apache.org Received: (qmail 85572 invoked by uid 99); 15 Feb 2017 18:57:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Feb 2017 18:57:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 6CFC8E04F1; Wed, 15 Feb 2017 18:57:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: heneveld@apache.org To: commits@brooklyn.apache.org Date: Wed, 15 Feb 2017 18:57:30 -0000 Message-Id: <647ea0f9e8634911bc7eee42ae46d0b9@git.apache.org> In-Reply-To: <0c27d34131b642f2aa97df5dd8198a85@git.apache.org> References: <0c27d34131b642f2aa97df5dd8198a85@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [07/10] brooklyn-server git commit: add CompositeEffector tests and improve its implementation archived-at: Wed, 15 Feb 2017 18:57:27 -0000 add CompositeEffector tests and improve its implementation Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b32581dd Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b32581dd Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b32581dd Branch: refs/heads/master Commit: b32581dd81a390d69ff63779465cd83520c7dcab Parents: b0b83da Author: Andrea Turli Authored: Thu Feb 2 17:27:41 2017 +0100 Committer: Andrea Turli Committed: Mon Feb 13 15:16:02 2017 +0100 ---------------------------------------------------------------------- .../brooklyn/CompositeEffectorYamlTest.java | 79 ++++++ .../core/effector/CompositeEffector.java | 68 ++--- .../core/effector/http/HttpCommandEffector.java | 71 +++-- .../CompositeEffectorIntegrationTest.java | 27 +- .../core/effector/CompositeEffectorTest.java | 262 +++++++++++++++++++ .../effector/http/HttpCommandEffectorTest.java | 88 ++++++- .../core/effector/http/int-response.json | 16 ++ .../core/effector/http/list-response.json | 19 ++ .../core/effector/http/map-response.json | 16 ++ .../org/apache/brooklyn/core/effector/test.json | 16 ++ 10 files changed, 595 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java new file mode 100644 index 0000000..f114f23 --- /dev/null +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CompositeEffectorYamlTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.camp.brooklyn; + +import static org.testng.Assert.assertEquals; + +import java.util.List; + +import org.apache.brooklyn.api.effector.Effector; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.core.effector.CompositeEffector; +import org.apache.brooklyn.core.effector.http.HttpCommandEffector; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class CompositeEffectorYamlTest extends AbstractYamlTest { + private static final Logger log = LoggerFactory.getLogger(CompositeEffectorYamlTest.class); + + @Test + public void testCompositeEffector() throws Exception { + Entity app = createAndStartApplication( + "location: localhost", + "services:", + "- type: " + EmptySoftwareProcess.class.getName(), + " brooklyn.config:", + " onbox.base.dir.skipResolution: true", + " softwareProcess.serviceProcessIsRunningPollPeriod: forever", + " brooklyn.initializers:", + " - type: " + HttpCommandEffector.class.getName(), + " brooklyn.config:", + " name: myEffector", + " description: myDescription", + " uri: https://httpbin.org/get?id=myId", + " httpVerb: GET", + " jsonPath: $.args.id", + " publishSensor: results", + " - type: " + CompositeEffector.class.getName(), + " brooklyn.config:", + " name: start", + " override: true", + " effectors:", + " - myEffector" + ); + waitForApplicationTasks(app); + + EmptySoftwareProcess entity = (EmptySoftwareProcess) Iterables.getOnlyElement(app.getChildren()); + Effector effector = entity.getEntityType().getEffectorByName("start").get(); + + // Invoke without parameter + Object results = entity.invoke(effector, ImmutableMap.of()).get(); + assertEquals(((List)results).get(0), "myId"); + } + + @Override + protected Logger getLogger() { + return log; + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java index 32f0f1d..5345b4a 100644 --- a/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java +++ b/core/src/main/java/org/apache/brooklyn/core/effector/CompositeEffector.java @@ -18,11 +18,12 @@ */ package org.apache.brooklyn.core.effector; +import static org.apache.brooklyn.core.entity.trait.Startable.START; +import static org.apache.brooklyn.core.entity.trait.Startable.STOP; + import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - import org.apache.brooklyn.api.effector.Effector; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.config.ConfigKey; @@ -36,11 +37,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.annotations.Beta; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.reflect.TypeToken; @@ -48,11 +46,14 @@ import com.google.common.reflect.TypeToken; public class CompositeEffector extends AddEffector { private static final Logger LOG = LoggerFactory.getLogger(CompositeEffector.class); + private static final String ORIGINAL_PREFIX = "original-"; - public static final ConfigKey> EFFECTORS = ConfigKeys.newConfigKey(new TypeToken>() {}, "effectors", + public static final ConfigKey> EFFECTORS = ConfigKeys.newConfigKey(new TypeToken>() { + }, "effectors", "Effector names to be chained together in the composite effector", ImmutableList.of()); public static final ConfigKey OVERRIDE = ConfigKeys.newBooleanConfigKey("override", "Wheter additional defined effectors should override pre-existing effector with same name or not (default: false)", Boolean.FALSE); + public CompositeEffector(ConfigBag params) { super(newEffectorBuilder(params).build()); } @@ -61,8 +62,8 @@ public class CompositeEffector extends AddEffector { this(ConfigBag.newInstance(params)); } - public static EffectorBuilder newEffectorBuilder(ConfigBag params) { - EffectorBuilder eff = AddEffector.newEffectorBuilder(String.class, params); + public static EffectorBuilder newEffectorBuilder(ConfigBag params) { + EffectorBuilder eff = AddEffector.newEffectorBuilder(List.class, params); eff.impl(new Body(eff.buildAbstract(), params)); return eff; } @@ -71,13 +72,13 @@ public class CompositeEffector extends AddEffector { public void apply(EntityLocal entity) { Maybe> effectorMaybe = entity.getEntityType().getEffectorByName(effector.getName()); if (!effectorMaybe.isAbsentOrNull()) { - Effector original = Effectors.effector(effectorMaybe.get()).name("original-" + effector.getName()).build(); - ((EntityInternal)entity).getMutableEntityType().addEffector(original); + Effector original = Effectors.effector(effectorMaybe.get()).name(ORIGINAL_PREFIX + effector.getName()).build(); + ((EntityInternal) entity).getMutableEntityType().addEffector(original); } super.apply(entity); } - protected static class Body extends EffectorBody { + protected static class Body extends EffectorBody { private final Effector effector; private final ConfigBag params; @@ -88,46 +89,47 @@ public class CompositeEffector extends AddEffector { } @Override - public String call(final ConfigBag params) { + public List call(final ConfigBag params) { ConfigBag allConfig = ConfigBag.newInstanceCopying(this.params).putAll(params); final List effectorNames = EntityInitializers.resolve(allConfig, EFFECTORS); final Boolean override = allConfig.get(OVERRIDE); List results = Lists.newArrayList(); - if (!override) { - Optional> effectorOptional = Iterables.tryFind(entity().getEntityType().getEffectors(), new Predicate>() { - @Override - public boolean apply(@Nullable Effector input) { - return input.getName().equals("original-" + effector.getName()); - } - }); - // if it is a stop effector, it has to be executed as last effector - if (effectorOptional.isPresent()) { - if (effectorOptional.get().getName().endsWith("-stop")) { - effectorNames.add(effectorOptional.get().getName()); - } else { - effectorNames.add(0, effectorOptional.get().getName()); - } - } - } + if (!override && isStartRedefined()) { + results.add(invokeEffectorNamed(ORIGINAL_PREFIX + START.getName(), params)); + } for (String eff : effectorNames) { results.add(invokeEffectorNamed(eff, params)); } - return Iterables.toString(results); + if (!override && isStopRedefined()) { + results.add(invokeEffectorNamed(ORIGINAL_PREFIX + STOP.getName(), params)); + } + return results; + } + + private boolean isStartRedefined() { + return isEffectorRedefined(ORIGINAL_PREFIX + START.getName()); + } + + private boolean isStopRedefined() { + return isEffectorRedefined(ORIGINAL_PREFIX + STOP.getName()); + } + + private boolean isEffectorRedefined(String effectorName) { + return entity().getEntityType().getEffectorByName(effectorName).isPresent(); } private Object invokeEffectorNamed(String effectorName, ConfigBag params) { - LOG.debug("{} invoking effector on {}, effector={}, parameters={}", + LOG.info("{} invoking effector on {}, effector={}, parameters={}", new Object[]{this, entity(), effectorName, params}); Maybe> effector = entity().getEntityType().getEffectorByName(effectorName); if (effector.isAbsent()) { - // TODO + throw new IllegalStateException("Cannot find effector " + effectorName); } return entity().invoke(effector.get(), params.getAllConfig()).getUnchecked(); - } - } + } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java index 2d8266e..1388a926 100644 --- a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java +++ b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java @@ -19,6 +19,7 @@ package org.apache.brooklyn.core.effector.http; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -49,28 +50,33 @@ import org.apache.brooklyn.util.http.executor.HttpRequest; import org.apache.brooklyn.util.http.executor.HttpResponse; import org.apache.brooklyn.util.http.executor.UsernamePassword; import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Enums; import com.google.common.base.Joiner; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.jayway.jsonpath.JsonPath; public final class HttpCommandEffector extends AddEffector { + private static final Logger LOG = LoggerFactory.getLogger(HttpCommandEffector.class); + public static final ConfigKey EFFECTOR_URI = ConfigKeys.newStringConfigKey("uri"); public static final ConfigKey EFFECTOR_HTTP_VERB = ConfigKeys.newStringConfigKey("httpVerb"); public static final ConfigKey EFFECTOR_HTTP_USERNAME = ConfigKeys.newStringConfigKey("httpUsername"); public static final ConfigKey EFFECTOR_HTTP_PASSWORD = ConfigKeys.newStringConfigKey("httpPassword"); public static final ConfigKey> EFFECTOR_HTTP_HEADERS = new MapConfigKey(String.class, "headers"); - public static final ConfigKey> EFFECTOR_HTTP_PAYLOAD = new MapConfigKey(String.class, "httpPayload"); + public static final ConfigKey EFFECTOR_HTTP_PAYLOAD = ConfigKeys.newConfigKey(Object.class, "httpPayload"); public static final ConfigKey JSON_PATH = ConfigKeys.newStringConfigKey("jsonPath", "JSON path to select in HTTP response"); public static final ConfigKey PUBLISH_SENSOR = ConfigKeys.newStringConfigKey("publishSensor", "Sensor name where to store json path extracted value"); + public static final String APPLICATION_JSON = "application/json"; + private enum HttpVerb { - GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE } public HttpCommandEffector(ConfigBag params) { @@ -89,29 +95,28 @@ public final class HttpCommandEffector extends AddEffector { public Body(Effector eff, final ConfigBag params) { this.effector = eff; - Preconditions.checkNotNull(params.getAllConfigRaw().get(EFFECTOR_URI.getName()), "uri must be supplied when defining this effector"); - Preconditions.checkNotNull(params.getAllConfigRaw().get(EFFECTOR_HTTP_VERB.getName()), "HTTP verb must be supplied when defining this effector"); + checkNotNull(params.getAllConfigRaw().get(EFFECTOR_URI.getName()), "uri must be supplied when defining this effector"); + checkNotNull(params.getAllConfigRaw().get(EFFECTOR_HTTP_VERB.getName()), "HTTP verb must be supplied when defining this effector"); this.params = params; } @Override public String call(final ConfigBag params) { ConfigBag allConfig = ConfigBag.newInstanceCopying(this.params).putAll(params); - final String uri = EntityInitializers.resolve(allConfig, EFFECTOR_URI); - final String httpVerb = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_VERB); + final URI uri = convertToURI(EntityInitializers.resolve(allConfig, EFFECTOR_URI)); + final String httpVerb = isValidHttpVerb(EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_VERB)); final String httpUsername = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_USERNAME); final String httpPassword = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PASSWORD); final Map headers = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_HEADERS); - final Map payload = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PAYLOAD); + final Object payload = EntityInitializers.resolve(allConfig, EFFECTOR_HTTP_PAYLOAD); final String jsonPath = EntityInitializers.resolve(allConfig, JSON_PATH); final String publishSensor = EntityInitializers.resolve(allConfig, PUBLISH_SENSOR); + final HttpExecutor httpExecutor = HttpExecutorImpl.newInstance(); + + final HttpRequest request = buildHttpRequest(httpVerb, uri, headers, httpUsername, httpPassword, payload); Task t = Tasks.builder().displayName(effector.getName()).body(new Callable() { @Override public Object call() throws Exception { - HttpExecutor httpExecutor = HttpExecutorImpl.newInstance(); - - String body = getBodyFromPayload(payload, headers); - HttpRequest request = buildHttpRequest(httpVerb, uri, headers, httpUsername, httpPassword, body); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { HttpResponse response = httpExecutor.execute(request); @@ -127,6 +132,7 @@ public final class HttpCommandEffector extends AddEffector { String responseBody = (String) queue(t).getUnchecked(); if (jsonPath == null) return responseBody; + String extractedValue = JsonPath.parse(responseBody).read(jsonPath, String.class); if (publishSensor != null) { entity().sensors().set(Sensors.newStringSensor(publishSensor), extractedValue); @@ -134,6 +140,16 @@ public final class HttpCommandEffector extends AddEffector { return extractedValue; } + private URI convertToURI(String url) { + try { + return new URL(url).toURI(); + } catch (MalformedURLException e) { + throw Exceptions.propagate(e); + } catch (URISyntaxException e) { + throw Exceptions.propagate(e); + } + } + private void validateResponse(HttpResponse response) { int statusCode = response.code(); if (statusCode == 401) { @@ -145,13 +161,8 @@ public final class HttpCommandEffector extends AddEffector { } } - private HttpRequest buildHttpRequest(String httpVerb, String url, Map headers, String httpUsername, String httpPassword, String body) throws MalformedURLException, URISyntaxException { - // validate url string - URI uri = new URL(url).toURI(); - // validate HTTP verb - validateHttpVerb(httpVerb); + private HttpRequest buildHttpRequest(String httpVerb, URI uri, Map headers, String httpUsername, String httpPassword, Object payload) { HttpRequest.Builder httpRequestBuilder = new HttpRequest.Builder() - .body(body.getBytes()) .uri(uri) .method(httpVerb) .config(HttpConfig.builder() @@ -164,6 +175,19 @@ public final class HttpCommandEffector extends AddEffector { httpRequestBuilder.headers(headers); } + if (payload != null) { + String body = ""; + String contentType = headers.get(HttpHeaders.CONTENT_TYPE); + if (contentType == null || contentType.equalsIgnoreCase(APPLICATION_JSON)) { + LOG.warn("Content-Type not specified. Using {}, as default (continuing)", APPLICATION_JSON); + body = toJsonString(payload); + } else if (!(payload instanceof String) && !contentType.equalsIgnoreCase(APPLICATION_JSON)) { + LOG.warn("the http request may fail with payload {} and 'Content-Type= {}, (continuing)", payload, contentType); + body = payload.toString(); + } + httpRequestBuilder.body(body.getBytes()); + } + if (httpUsername != null && httpPassword != null) { httpRequestBuilder.credentials(new UsernamePassword(httpUsername, httpPassword)); } @@ -171,17 +195,14 @@ public final class HttpCommandEffector extends AddEffector { return httpRequestBuilder.build(); } - private void validateHttpVerb(String httpVerb) { + private String isValidHttpVerb(String httpVerb) { Optional state = Enums.getIfPresent(HttpVerb.class, httpVerb.toUpperCase()); checkArgument(state.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(HttpVerb.values()), httpVerb); + return httpVerb; } - private String getBodyFromPayload(Map payload, Map headers) { - String body = ""; - if (payload != null && !payload.isEmpty() && headers.containsKey(HttpHeaders.CONTENT_TYPE)) { - body = Jsonya.newInstance().put(payload).toString(); - } - return body; + private String toJsonString(Object payload) { + return Jsonya.newInstance().add(payload).toString(); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java index e8cc30e..dd168ed 100644 --- a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorIntegrationTest.java @@ -18,6 +18,12 @@ */ package org.apache.brooklyn.core.effector; +import static org.apache.brooklyn.test.Asserts.assertEquals; +import static org.apache.brooklyn.test.Asserts.assertNull; +import static org.apache.brooklyn.test.Asserts.assertTrue; + +import java.util.List; + import org.apache.brooklyn.api.effector.Effector; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.api.entity.EntitySpec; @@ -36,11 +42,11 @@ import com.google.common.collect.ImmutableList; public class CompositeEffectorIntegrationTest { - final static Effector EFFECTOR_START = Effectors.effector(String.class, "start").buildAbstract(); + final static Effector EFFECTOR_START = Effectors.effector(List.class, "start").buildAbstract(); private TestApplication app; private EntityLocal entity; - + @BeforeMethod(alwaysRun=true) public void setUp() throws Exception { app = TestApplication.Factory.newManagedInstanceForTests(); @@ -58,21 +64,28 @@ public class CompositeEffectorIntegrationTest { new HttpCommandEffector(ConfigBag.newInstance() .configure(HttpCommandEffector.EFFECTOR_NAME, "eff1") .configure(HttpCommandEffector.EFFECTOR_URI, "https://api.github.com/users/apache") - .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.login")) .apply(entity); new HttpCommandEffector(ConfigBag.newInstance() .configure(HttpCommandEffector.EFFECTOR_NAME, "eff2") .configure(HttpCommandEffector.EFFECTOR_URI, "https://api.github.com/users/brooklyncentral") - .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.login")) .apply(entity); new CompositeEffector(ConfigBag.newInstance() .configure(CompositeEffector.EFFECTOR_NAME, "start") .configure(CompositeEffector.EFFECTORS, ImmutableList.of("eff1", "eff2"))) .apply(entity); - String val = entity.invoke(EFFECTOR_START, MutableMap.of()).get(); - // TODO - System.out.println(val); + List results = entity.invoke(EFFECTOR_START, MutableMap.of()).get(); + + assertEquals(results.size(), 3); + assertNull(results.get(0)); + assertTrue(results.get(1) instanceof String); + assertEquals(results.get(1), "apache"); + assertTrue(results.get(2) instanceof String); + assertEquals(results.get(2), "brooklyncentral"); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java new file mode 100644 index 0000000..3bf0018 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/core/effector/CompositeEffectorTest.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.core.effector; + +import static org.apache.brooklyn.core.effector.http.HttpCommandEffectorTest.EFFECTOR_HTTP_COMMAND; +import static org.apache.brooklyn.test.Asserts.assertNotNull; +import static org.apache.brooklyn.test.Asserts.assertNull; +import static org.apache.brooklyn.test.Asserts.assertTrue; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import org.apache.brooklyn.api.effector.Effector; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.effector.http.HttpCommandEffector; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.core.http.BetterMockWebServer; +import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException; +import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Charsets; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Resources; +import com.google.mockwebserver.MockResponse; + +public class CompositeEffectorTest extends BrooklynAppUnitTestSupport { + + private static final Logger log = LoggerFactory.getLogger(CompositeEffectorTest.class); + private static final String DEFAULT_ENDPOINT = "/"; + + final static Effector EFFECTOR_COMPOSITE = Effectors.effector(List.class, "CompositeEffector").buildAbstract(); + + protected BetterMockWebServer server; + protected URL baseUrl; + + protected Location loc; + protected CompositeEffector compositeEffector; + + @BeforeMethod + public void start() throws IOException { + server = BetterMockWebServer.newInstanceLocalhost(); + server.play(); + } + + @AfterMethod(alwaysRun = true) + public void stop() throws IOException { + server.shutdown(); + } + + protected String url(String path) { + return server.getUrl(path).toString(); + } + + protected MockResponse jsonResponse(String resource) { + return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource)); + } + + protected MockResponse response404() { + return new MockResponse().setStatus("HTTP/1.1 404 Not Found"); + } + + protected MockResponse response204() { + return new MockResponse().setStatus("HTTP/1.1 204 No Content"); + } + + protected String stringFromResource(String resourceName) { + return stringFromResource("/org/apache/brooklyn/core/effector", resourceName); + } + + private String stringFromResource(String prefix, String resourceName) { + try { + return Resources.toString(getClass().getResource(String.format("%s/%s", prefix, resourceName)), Charsets.UTF_8) + .replace(DEFAULT_ENDPOINT, url("")); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + @Test + public void testCompositeEffectorWithNonExistingName() throws InterruptedException { + server.enqueue(jsonResponse("test.json")); + + HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login") + ); + assertNotNull(httpCommandEffector); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName()) + .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName())) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector)); + List results = testEntity.invoke(EFFECTOR_COMPOSITE, ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + Asserts.assertEquals(results.size(), 1); + + assertTrue(results.get(0) instanceof String); + Asserts.assertEquals(results.get(0), "myLogin"); + } + + @Test + public void testCompositeEffectorWithStartName() throws InterruptedException { + server.enqueue(jsonResponse("test.json")); + + HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login") + ); + assertNotNull(httpCommandEffector); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, "start") + .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName())) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector)); + List results = testEntity.invoke(Effectors.effector(List.class, "start").buildAbstract(), ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + Asserts.assertEquals(results.size(), 2); + assertNull(results.get(0)); + assertTrue(results.get(1) instanceof String); + Asserts.assertEquals(results.get(1), "myLogin"); + } + + @Test + public void testCompositeEffectorWithStartNameAndOverriding() throws InterruptedException { + server.enqueue(jsonResponse("test.json")); + + HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login") + ); + assertNotNull(httpCommandEffector); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, "start") + .configure(CompositeEffector.OVERRIDE, true) + .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName())) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector)); + List results = testEntity.invoke(Effectors.effector(List.class, "start").buildAbstract(), ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + Asserts.assertEquals(results.size(), 1); + assertTrue(results.get(0) instanceof String); + Asserts.assertEquals(results.get(0), "myLogin"); + } + + @Test + public void testCompositeEffectorWithStopName() throws InterruptedException { + server.enqueue(jsonResponse("test.json")); + + HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login") + ); + assertNotNull(httpCommandEffector); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, "stop") + .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName())) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector)); + List results = testEntity.invoke(Effectors.effector(List.class, "stop").buildAbstract(), ImmutableMap.of()).getUnchecked(Duration.minutes(1)); + Asserts.assertEquals(results.size(), 2); + assertTrue(results.get(0) instanceof String); + Asserts.assertEquals(results.get(0), "myLogin"); + assertNull(results.get(1)); + } + + @Test + public void testCompositeEffectorWithStopNameAndOverriding() throws InterruptedException { + server.enqueue(jsonResponse("test.json")); + + HttpCommandEffector httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login") + ); + assertNotNull(httpCommandEffector); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, "stop") + .configure(CompositeEffector.OVERRIDE, true) + .configure(CompositeEffector.EFFECTORS, ImmutableList.of(EFFECTOR_HTTP_COMMAND.getName())) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector, compositeEffector)); + List results = testEntity.invoke(Effectors.effector(List.class, "stop").buildAbstract(), ImmutableMap.of()).getUnchecked(Duration.minutes(1)); + Asserts.assertEquals(results.size(), 1); + assertTrue(results.get(0) instanceof String); + Asserts.assertEquals(results.get(0), "myLogin"); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testMissingEffectors() { + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName()) + .configure(CompositeEffector.EFFECTORS, null) + ); + } + + @Test(expectedExceptions = PropagatedRuntimeException.class) + public void testWhenOneEffectorFails() throws InterruptedException { + server.enqueue(response404()); + + HttpCommandEffector eff1 = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, "eff1") + .configure(HttpCommandEffector.EFFECTOR_URI, url("/get?login=myLogin")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "GET") + .configure(HttpCommandEffector.JSON_PATH, "$.args.login")); + compositeEffector = new CompositeEffector(ConfigBag.newInstance() + .configure(CompositeEffector.EFFECTOR_NAME, EFFECTOR_COMPOSITE.getName()) + .configure(CompositeEffector.EFFECTORS, ImmutableList.of("eff1", "eff2")) + ); + assertNotNull(compositeEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(eff1, compositeEffector)); + List results = testEntity.invoke(EFFECTOR_COMPOSITE, ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + Asserts.assertEquals(results.size(), 2); + } + + private EntitySpec buildEntitySpec(AddEffector... effectors) { + EntitySpec testEntitySpec = EntitySpec.create(TestEntity.class); + for (AddEffector effector : effectors) { + testEntitySpec.addInitializer(effector); + } + return testEntitySpec; + } + +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java index a4b8ee0..0580c39 100644 --- a/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/effector/http/HttpCommandEffectorTest.java @@ -44,8 +44,10 @@ import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.io.Resources; +import com.google.common.net.HttpHeaders; import com.google.mockwebserver.MockResponse; import com.google.mockwebserver.RecordedRequest; @@ -54,7 +56,7 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport { private static final Logger log = LoggerFactory.getLogger(HttpCommandEffectorTest.class); private static final String DEFAULT_ENDPOINT = "/"; - final static Effector EFFECTOR_HTTP_COMMAND = Effectors.effector(String.class, "http-command-effector").buildAbstract(); + public final static Effector EFFECTOR_HTTP_COMMAND = Effectors.effector(String.class, "http-command-effector").buildAbstract(); protected BetterMockWebServer server; protected URL baseUrl; @@ -78,7 +80,7 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport { } protected MockResponse jsonResponse(String resource) { - return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource)); + return new MockResponse().addHeader(HttpHeaders.CONTENT_TYPE, "application/json").setBody(stringFromResource(resource)); } protected MockResponse response404() { @@ -144,6 +146,88 @@ public class HttpCommandEffectorTest extends BrooklynAppUnitTestSupport { } @Test + public void testPayloadWithContentTypeHeaderJson() throws InterruptedException { + server.enqueue(jsonResponse("map-response.json")); + + httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/post")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST") + .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableMap.of("key", "value")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_HEADERS, ImmutableMap.of(HttpHeaders.CONTENT_TYPE, "application/json")) + .configure(HttpCommandEffector.JSON_PATH, "$.data") + ); + assertNotNull(httpCommandEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector)); + Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.of()).getUnchecked(Duration.minutes(1)); + assertEquals(output, "{\"key\", \"value\"}"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "POST", "/post"); + } + + @Test + public void testPayloadWithoutContentTypeHeader() throws InterruptedException { + server.enqueue(jsonResponse("map-response.json")); + + httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/post")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST") + .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableMap.of("key", "value")) + .configure(HttpCommandEffector.JSON_PATH, "$.data") + ); + assertNotNull(httpCommandEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector)); + Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + assertEquals(output, "{\"key\", \"value\"}"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "POST", "/post"); + } + + @Test + public void testListPayloadWithoutContentTypeHeader() throws InterruptedException { + server.enqueue(jsonResponse("list-response.json")); + + httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/post")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST") + .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, ImmutableList.of("key", "value")) + .configure(HttpCommandEffector.JSON_PATH, "$.data") + ); + assertNotNull(httpCommandEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector)); + Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + assertEquals(output, "[\"key\", \"value\"]"); + + assertEquals(server.getRequestCount(), "[\"key\", \"value\"]"); + assertSent(server, "POST", "/post"); + } + + @Test + public void testPayloadWithContentTypeHeaderXml() throws InterruptedException { + server.enqueue(jsonResponse("int-response.json")); + + httpCommandEffector = new HttpCommandEffector(ConfigBag.newInstance() + .configure(HttpCommandEffector.EFFECTOR_NAME, EFFECTOR_HTTP_COMMAND.getName()) + .configure(HttpCommandEffector.EFFECTOR_URI, url("/post")) + .configure(HttpCommandEffector.EFFECTOR_HTTP_VERB, "POST") + .configure(HttpCommandEffector.EFFECTOR_HTTP_PAYLOAD, 1) + .configure(HttpCommandEffector.EFFECTOR_HTTP_HEADERS, ImmutableMap.of(HttpHeaders.CONTENT_TYPE, "application/xml")) + .configure(HttpCommandEffector.JSON_PATH, "$.data") + ); + assertNotNull(httpCommandEffector); + TestEntity testEntity = app.createAndManageChild(buildEntitySpec(httpCommandEffector)); + Object output = testEntity.invoke(EFFECTOR_HTTP_COMMAND, ImmutableMap.of()).getUnchecked(Duration.seconds(1)); + assertEquals(output, "1"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "POST", "/post"); + } + + @Test public void testHappyPath() throws InterruptedException { server.enqueue(jsonResponse("login.json")); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json new file mode 100644 index 0000000..9b133f7 --- /dev/null +++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/int-response.json @@ -0,0 +1,16 @@ +{ + "args": {}, + "data": "1", + "files": {}, + "form": {}, + "headers": { + "Accept": "*/*", + "Content-Length": "1", + "Content-Type": "application/json", + "Host": "httpbin.org", + "User-Agent": "curl/7.49.1" + }, + "json": 1, + "origin": "93.61.99.89", + "url": "http://httpbin.org/post" +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json new file mode 100644 index 0000000..88394ea --- /dev/null +++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/list-response.json @@ -0,0 +1,19 @@ +{ + "args": {}, + "data": "[\"key\", \"value\"]", + "files": {}, + "form": {}, + "headers": { + "Accept": "*/*", + "Content-Length": "16", + "Content-Type": "application/json", + "Host": "httpbin.org", + "User-Agent": "curl/7.49.1" + }, + "json": [ + "key", + "value" + ], + "origin": "93.61.99.89", + "url": "http://httpbin.org/post" +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json b/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json new file mode 100644 index 0000000..959b763 --- /dev/null +++ b/core/src/test/resources/org/apache/brooklyn/core/effector/http/map-response.json @@ -0,0 +1,16 @@ +{ + "args": {}, + "data": "{\"key\", \"value\"}", + "files": {}, + "form": {}, + "headers": { + "Accept": "*/*", + "Content-Length": "16", + "Content-Type": "application/json", + "Host": "httpbin.org", + "User-Agent": "curl/7.49.1" + }, + "json": null, + "origin": "93.61.99.89", + "url": "http://httpbin.org/post" +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b32581dd/core/src/test/resources/org/apache/brooklyn/core/effector/test.json ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/effector/test.json b/core/src/test/resources/org/apache/brooklyn/core/effector/test.json new file mode 100644 index 0000000..b39889a --- /dev/null +++ b/core/src/test/resources/org/apache/brooklyn/core/effector/test.json @@ -0,0 +1,16 @@ +{ + "args": { + "login": "myLogin" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch, br", + "Accept-Language": "en-US,en;q=0.8,it;q=0.6", + "Cookie": "_ga=GA1.2.1060288368.1484053495; _gat=1", + "Host": "httpbin.org", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36" + }, + "origin": "93.61.99.89", + "url": "https://httpbin.org/get?login=myLogin" +}