This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 4dc4514abcb14b837e6e66160928a71e47729f20 Author: Alex Heneveld <[email protected]> AuthorDate: Tue Dec 6 09:27:42 2022 +0000 add a "workflow startable" which uses workflow to start/stop entities --- .../core/entity/trait/StartableMethods.java | 2 +- .../core/workflow/steps/CustomWorkflowStep.java | 6 ++ ...artableImpl.java => AbstractStartableImpl.java} | 50 +++------ .../brooklyn/entity/stock/BasicStartable.java | 16 --- .../brooklyn/entity/stock/BasicStartableImpl.java | 74 ++++--------- .../brooklyn/entity/stock/WorkflowStartable.java | 67 ++++++++++++ .../entity/stock/WorkflowStartableImpl.java | 64 ++++++++++++ .../entity/stock/WorkflowStartableTest.java | 114 +++++++++++++++++++++ karaf/init/src/main/resources/catalog.bom | 9 ++ .../software/base/WorkflowSoftwareProcess.java | 20 ++-- 10 files changed, 304 insertions(+), 118 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java b/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java index d887c334ca..00c5e8022d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java @@ -67,7 +67,7 @@ public class StartableMethods { log.debug("Restarted children of entity "+e); } - private static <T extends Entity> Iterable<T> filterStartableManagedEntities(Iterable<T> contenders) { + public static <T extends Entity> Iterable<T> filterStartableManagedEntities(Iterable<T> contenders) { return Iterables.filter(contenders, Predicates.and(Predicates.instanceOf(Startable.class), EntityPredicates.isManaged())); } diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java index 76697cc02c..0c87777f38 100644 --- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java +++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java @@ -65,6 +65,12 @@ public class CustomWorkflowStep extends WorkflowStepDefinition implements Workfl private static final String WORKFLOW_SETTING_SHORTHAND = "[ \"replayable\" ${replayable...} ] [ \"retention\" ${retention...} ] "; + public CustomWorkflowStep() {} + public CustomWorkflowStep(String name, List<Object> steps) { + this.name = name; + this.steps = steps; + } + String shorthand; @Override public void populateFromShorthand(String value) { diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/AbstractStartableImpl.java similarity index 66% copy from core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java copy to core/src/main/java/org/apache/brooklyn/entity/stock/AbstractStartableImpl.java index c6431b0244..0e799690cc 100644 --- a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java +++ b/core/src/main/java/org/apache/brooklyn/entity/stock/AbstractStartableImpl.java @@ -18,24 +18,14 @@ */ package org.apache.brooklyn.entity.stock; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; - import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.core.entity.AbstractEntity; import org.apache.brooklyn.core.entity.Attributes; import org.apache.brooklyn.core.entity.Entities; -import org.apache.brooklyn.core.entity.EntityPredicates; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; import org.apache.brooklyn.core.entity.trait.Startable; @@ -43,10 +33,16 @@ import org.apache.brooklyn.core.entity.trait.StartableMethods; import org.apache.brooklyn.core.location.Locations; import org.apache.brooklyn.util.collections.QuorumCheck; import org.apache.brooklyn.util.exceptions.Exceptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; -public class BasicStartableImpl extends AbstractEntity implements BasicStartable { +public abstract class AbstractStartableImpl extends AbstractEntity implements BasicStartable { - private static final Logger log = LoggerFactory.getLogger(BasicStartableImpl.class); + private static final Logger log = LoggerFactory.getLogger(AbstractStartableImpl.class); @Override public void start(Collection<? extends Location> locations) { @@ -61,37 +57,21 @@ public class BasicStartableImpl extends AbstractEntity implements BasicStartable locations = Locations.getLocationsCheckingAncestors(locations, this); log.info("Starting entity "+this+" at "+locations); - // essentially does StartableMethods.start(this, locations), - // but optionally filters locations for each child - - Locations.LocationsFilter filter = getConfig(LOCATIONS_FILTER); - Iterable<Entity> startables = filterStartableManagedEntities(getChildren()); - if (!Iterables.isEmpty(startables)) { - List<Task<?>> tasks = Lists.newArrayListWithCapacity(Iterables.size(startables)); - for (final Entity entity : startables) { - Collection<? extends Location> l2 = locations; - if (filter != null) { - l2 = filter.filterForContext(new ArrayList<Location>(locations), entity); - log.debug("Child " + entity + " of " + this + " being started in filtered location list: " + l2); - } - tasks.add(Entities.invokeEffectorWithArgs(this, entity, Startable.START, l2)); - } - for (Task<?> t : tasks) { - t.getUnchecked(); - } - } + doStart(locations); sensors().set(Attributes.SERVICE_UP, true); } finally { ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); } } + protected abstract void doStart(Collection<? extends Location> locations); + @Override public void stop() { ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); sensors().set(SERVICE_UP, false); try { - StartableMethods.stop(this); + doStop(); ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); } catch (Exception e) { ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); @@ -99,6 +79,8 @@ public class BasicStartableImpl extends AbstractEntity implements BasicStartable } } + protected abstract void doStop(); + @Override public void restart() { StartableMethods.restart(this); @@ -113,8 +95,4 @@ public class BasicStartableImpl extends AbstractEntity implements BasicStartable .suppressDuplicates(true)); } - // TODO make public in StartableMethods - private static Iterable<Entity> filterStartableManagedEntities(Iterable<Entity> contenders) { - return Iterables.filter(contenders, Predicates.and(Predicates.instanceOf(Startable.class), EntityPredicates.isManaged())); - } } diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartable.java b/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartable.java index c2263db004..873bc45038 100644 --- a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartable.java +++ b/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartable.java @@ -46,20 +46,4 @@ public interface BasicStartable extends Entity, Startable { "brooklyn.locationsFilter", "Provides a hook for customizing locations to be used for a given context"); - /** @deprecated since 0.7.0; use {@link Locations#LocationFilter} */ - @Deprecated - public interface LocationsFilter extends Locations.LocationsFilter { - /** @deprecated since 0.7.0; use {@link Locations#USE_FIRST_LOCATION} */ - @Deprecated - public static final LocationsFilter USE_FIRST_LOCATION = new LocationsFilter() { - private static final long serialVersionUID = 3100091615409115890L; - - @Override - public List<Location> filterForContext(List<Location> locations, Object context) { - if (locations.size()<=1) return locations; - return ImmutableList.of(locations.get(0)); - } - }; - } - } diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java index c6431b0244..820787d520 100644 --- a/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java +++ b/core/src/main/java/org/apache/brooklyn/entity/stock/BasicStartableImpl.java @@ -44,59 +44,36 @@ import org.apache.brooklyn.core.location.Locations; import org.apache.brooklyn.util.collections.QuorumCheck; import org.apache.brooklyn.util.exceptions.Exceptions; -public class BasicStartableImpl extends AbstractEntity implements BasicStartable { +public class BasicStartableImpl extends AbstractStartableImpl implements BasicStartable { private static final Logger log = LoggerFactory.getLogger(BasicStartableImpl.class); @Override - public void start(Collection<? extends Location> locations) { - try { - ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + protected void doStart(Collection<? extends Location> locations) { + // essentially does StartableMethods.start(this, locations), + // but optionally filters locations for each child - // Opportunity to block startup until other dependent components are available - Object val = config().get(START_LATCH); - if (val != null) log.debug("{} finished waiting for start-latch; continuing...", this); - - addLocations(locations); - locations = Locations.getLocationsCheckingAncestors(locations, this); - log.info("Starting entity "+this+" at "+locations); - - // essentially does StartableMethods.start(this, locations), - // but optionally filters locations for each child - - Locations.LocationsFilter filter = getConfig(LOCATIONS_FILTER); - Iterable<Entity> startables = filterStartableManagedEntities(getChildren()); - if (!Iterables.isEmpty(startables)) { - List<Task<?>> tasks = Lists.newArrayListWithCapacity(Iterables.size(startables)); - for (final Entity entity : startables) { - Collection<? extends Location> l2 = locations; - if (filter != null) { - l2 = filter.filterForContext(new ArrayList<Location>(locations), entity); - log.debug("Child " + entity + " of " + this + " being started in filtered location list: " + l2); - } - tasks.add(Entities.invokeEffectorWithArgs(this, entity, Startable.START, l2)); - } - for (Task<?> t : tasks) { - t.getUnchecked(); + Locations.LocationsFilter filter = getConfig(LOCATIONS_FILTER); + Iterable<Entity> startables = StartableMethods.filterStartableManagedEntities(getChildren()); + if (!Iterables.isEmpty(startables)) { + List<Task<?>> tasks = Lists.newArrayListWithCapacity(Iterables.size(startables)); + for (final Entity entity : startables) { + Collection<? extends Location> l2 = locations; + if (filter != null) { + l2 = filter.filterForContext(new ArrayList<Location>(locations), entity); + log.debug("Child " + entity + " of " + this + " being started in filtered location list: " + l2); } + tasks.add(Entities.invokeEffectorWithArgs(this, entity, Startable.START, l2)); + } + for (Task<?> t : tasks) { + t.getUnchecked(); } - sensors().set(Attributes.SERVICE_UP, true); - } finally { - ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); } } @Override - public void stop() { - ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); - sensors().set(SERVICE_UP, false); - try { - StartableMethods.stop(this); - ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); - } catch (Exception e) { - ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); - throw Exceptions.propagate(e); - } + protected void doStop() { + StartableMethods.stop(this); } @Override @@ -104,17 +81,4 @@ public class BasicStartableImpl extends AbstractEntity implements BasicStartable StartableMethods.restart(this); } - @Override - protected void initEnrichers() { - super.initEnrichers(); - enrichers().add(ServiceStateLogic.newEnricherFromChildrenUp() - .checkChildrenOnly() - .requireUpChildren(QuorumCheck.QuorumChecks.all()) - .suppressDuplicates(true)); - } - - // TODO make public in StartableMethods - private static Iterable<Entity> filterStartableManagedEntities(Iterable<Entity> contenders) { - return Iterables.filter(contenders, Predicates.and(Predicates.instanceOf(Startable.class), EntityPredicates.isManaged())); - } } diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartable.java b/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartable.java new file mode 100644 index 0000000000..467b092dcb --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartable.java @@ -0,0 +1,67 @@ +/* + * 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.entity.stock; + +import com.google.common.base.Predicates; +import org.apache.brooklyn.api.catalog.CatalogConfig; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.config.ConfigInheritance; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.BasicConfigInheritance; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.config.ConfigPredicates; +import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.core.location.Locations; +import org.apache.brooklyn.core.workflow.steps.CustomWorkflowStep; +import org.apache.brooklyn.util.core.flags.SetFromFlag; + +import java.util.Arrays; + +/** + * Provides a Startable entity that runs workflow to start/stop and optionally restart + */ +@ImplementedBy(WorkflowStartableImpl.class) +public interface WorkflowStartable extends BasicStartable { + + @CatalogConfig(label = "Start Workflow", priority=5) + ConfigKey<CustomWorkflowStep> START_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "start") + .description("workflow to start the entity") + .runtimeInheritance(BasicConfigInheritance.NEVER_INHERITED) + .constraint(Predicates.notNull()) + .build(); + + @CatalogConfig(label = "Stop Workflow", priority=1) + ConfigKey<CustomWorkflowStep> STOP_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "stop") + .description("workflow to stop the entity") + .runtimeInheritance(BasicConfigInheritance.NEVER_INHERITED) + .constraint(Predicates.notNull()) + .build(); + + static final CustomWorkflowStep DEFAULT_RESTART_WORKFLOW = new CustomWorkflowStep("Restart (default workflow)", Arrays.asList("invoke-effector stop", "invoke-effector start")); + + @CatalogConfig(label = "Restart Workflow", priority=1) + ConfigKey<CustomWorkflowStep> RESTART_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "restart") + .description("workflow to restart the entity; default is to stop then start") + .runtimeInheritance(BasicConfigInheritance.NEVER_INHERITED) + .defaultValue(DEFAULT_RESTART_WORKFLOW) + .build(); + +} diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartableImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartableImpl.java new file mode 100644 index 0000000000..054374a564 --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/entity/stock/WorkflowStartableImpl.java @@ -0,0 +1,64 @@ +/* + * 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.entity.stock; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; +import org.apache.brooklyn.core.entity.trait.StartableMethods; +import org.apache.brooklyn.core.workflow.WorkflowExecutionContext; +import org.apache.brooklyn.core.workflow.steps.CustomWorkflowStep; +import org.apache.brooklyn.util.collections.QuorumCheck; +import org.apache.brooklyn.util.core.task.DynamicTasks; +import org.apache.brooklyn.util.guava.Maybe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; + +public class WorkflowStartableImpl extends AbstractStartableImpl implements WorkflowStartable { + + private static final Logger log = LoggerFactory.getLogger(WorkflowStartableImpl.class); + + protected Maybe<Object> runWorkflow(ConfigKey<CustomWorkflowStep> key) { + CustomWorkflowStep workflow = getConfig(key); + if (workflow==null) return Maybe.absent("No workflow defined for: "+key.getName()); + + WorkflowExecutionContext workflowContext = workflow.newWorkflowExecution(this, key.getName().toLowerCase(), + null /* could getInput from workflow, and merge shell environment here */); + + return Maybe.of(DynamicTasks.queueIfPossible( workflowContext.getTask(true).get() ).orSubmitAsync(this).getTask().getUnchecked()); + } + + @Override + protected void doStart(Collection<? extends Location> locations) { + runWorkflow(START_WORKFLOW).get(); + } + + @Override + protected void doStop() { + runWorkflow(STOP_WORKFLOW).get(); + } + + @Override + public void restart() { + runWorkflow(RESTART_WORKFLOW).get(); + } + +} diff --git a/core/src/test/java/org/apache/brooklyn/entity/stock/WorkflowStartableTest.java b/core/src/test/java/org/apache/brooklyn/entity/stock/WorkflowStartableTest.java new file mode 100644 index 0000000000..dbd4918fa8 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/entity/stock/WorkflowStartableTest.java @@ -0,0 +1,114 @@ +/* + * 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.entity.stock; + +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntityLocal; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.core.entity.*; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.location.Locations.LocationsFilter; +import org.apache.brooklyn.core.location.SimulatedLocation; +import org.apache.brooklyn.core.sensor.Sensors; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.core.workflow.WorkflowBasicTest; +import org.apache.brooklyn.core.workflow.WorkflowEffector; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.time.Duration; +import org.apache.brooklyn.util.time.Time; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +public class WorkflowStartableTest extends BrooklynAppUnitTestSupport { + + @Override + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + WorkflowBasicTest.addWorkflowStepTypes(mgmt); + } + + @Test + public void testSettingSensors() throws Exception { + WorkflowStartable entity = app.addChild(EntitySpec.create(WorkflowStartable.class) + .configure(WorkflowStartable.START_WORKFLOW.getName(), MutableMap.of("steps", MutableList.of("set-sensor started = yes"))) + .configure(WorkflowStartable.STOP_WORKFLOW.getName(), MutableMap.of("steps", MutableList.of("set-sensor started = no", "set-sensor stopped = yes"))) + ); + app.start(null); + EntityAsserts.assertAttributeEquals(entity, Sensors.newStringSensor("started"), "yes"); + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_UP, true); + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + + entity.invoke(entity.getEntityType().getEffectorByName("stop").get(), null).getUnchecked(); + EntityAsserts.assertAttributeEquals(entity, Sensors.newStringSensor("started"), "no"); + EntityAsserts.assertAttributeEquals(entity, Sensors.newStringSensor("stopped"), "yes"); + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_UP, false); + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); + + entity.sensors().set(Sensors.newStringSensor("stopped"), "manually no"); // make sure this is cleared + entity.invoke(entity.getEntityType().getEffectorByName("restart").get(), null).getUnchecked(); + EntityAsserts.assertAttributeEquals(entity, Sensors.newStringSensor("started"), "yes"); + EntityAsserts.assertAttributeEquals(entity, Sensors.newStringSensor("stopped"), "yes"); // because stop ran before start + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_UP, true); + EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + + WorkflowEffector eff = new WorkflowEffector(ConfigBag.newInstance() + .configure(WorkflowEffector.EFFECTOR_NAME, "make-problem") + .configure(WorkflowEffector.STEPS, MutableList.of("set-sensor service.problems = { some_problem: Testing }")) ); +// .configure(WorkflowEffector.STEPS, MutableList.of("set-sensor service.problems['some_problem'] = Testing a problem")) ); + eff.apply((EntityLocal)entity); + entity.invoke(entity.getEntityType().getEffectorByName("make-problem").get(), null).getUnchecked(); + + Time.sleep(Duration.ONE_SECOND); + Dumper.dumpInfo(entity); + EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); + + eff = new WorkflowEffector(ConfigBag.newInstance() + .configure(WorkflowEffector.EFFECTOR_NAME, "fix-problem") + .configure(WorkflowEffector.STEPS, MutableList.of("set-sensor service.problems = {}")) ); +// .configure(WorkflowEffector.STEPS, MutableList.of("clear-sensor service.problems['some_problem']")) ); + eff.apply((EntityLocal)entity); + entity.invoke(entity.getEntityType().getEffectorByName("fix-problem").get(), null).getUnchecked(); + + Time.sleep(Duration.ONE_SECOND); + Dumper.dumpInfo(entity); + EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + } + +} diff --git a/karaf/init/src/main/resources/catalog.bom b/karaf/init/src/main/resources/catalog.bom index 3f0ccfe386..6e7975c5ed 100644 --- a/karaf/init/src/main/resources/catalog.bom +++ b/karaf/init/src/main/resources/catalog.bom @@ -260,3 +260,12 @@ brooklyn.catalog: itemType: policy item: type: org.apache.brooklyn.core.workflow.WorkflowPolicy + + - id: workflow-entity + itemType: entity + item: + type: org.apache.brooklyn.entity.stock.WorkflowStartable + - id: workflow-software-process + itemType: entity + item: + type: org.apache.brooklyn.entity.software.base.WorkflowSoftwareProcess diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/WorkflowSoftwareProcess.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/WorkflowSoftwareProcess.java index 0949601e72..09ab9aef31 100644 --- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/WorkflowSoftwareProcess.java +++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/WorkflowSoftwareProcess.java @@ -33,33 +33,33 @@ import org.apache.brooklyn.core.workflow.steps.CustomWorkflowStep; @ImplementedBy(WorkflowSoftwareProcessImpl.class) public interface WorkflowSoftwareProcess extends SoftwareProcess { - @CatalogConfig(label = "Install Command", priority=5) + @CatalogConfig(label = "Install Workflow", priority=5) ConfigKey<CustomWorkflowStep> INSTALL_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "install.workflow") - .description("command to run during the install phase") + .description("workflow to run during the software install phase") .runtimeInheritance(ConfigInheritance.NONE) .build(); - @CatalogConfig(label = "Customize command", priority=4) + @CatalogConfig(label = "Customize Workflow", priority=4) ConfigKey<CustomWorkflowStep> CUSTOMIZE_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "customize.workflow") - .description("command to run during the customization phase") + .description("workflow to run during the software customization phase") .runtimeInheritance(ConfigInheritance.NONE) .build(); - @CatalogConfig(label = "Launch Command", priority=3) + @CatalogConfig(label = "Launch Workflow", priority=3) ConfigKey<CustomWorkflowStep> LAUNCH_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "launch.workflow") - .description("command to run to launch the process") + .description("workflow to run to launch the software process") .runtimeInheritance(ConfigInheritance.NONE) .build(); - @CatalogConfig(label = "Check-running Command", priority=2) + @CatalogConfig(label = "Check-running Workflow", priority=2) ConfigKey<CustomWorkflowStep> CHECK_RUNNING_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "checkRunning.workflow") - .description("command to determine whether the process is running") + .description("workflow to determine whether the software process is running") .runtimeInheritance(ConfigInheritance.NONE) .build(); - @CatalogConfig(label = "Stop Command", priority=1) + @CatalogConfig(label = "Stop Workflow", priority=1) ConfigKey<CustomWorkflowStep> STOP_WORKFLOW = ConfigKeys.builder(CustomWorkflowStep.class, "stop.workflow") - .description("command to run to stop the process") + .description("workflow to run to stop the software process") .runtimeInheritance(ConfigInheritance.NONE) .build();
