@Override
 public MesosSlave getMesosSlave(String hostname) {
   Collection<Entity> slaves = sensors().get(MESOS_SLAVES).getMembers();
   Optional<Entity> found =
       Iterables.tryFind(
           slaves,
           Predicates.or(
               EntityPredicates.attributeEqualTo(MesosSlave.HOSTNAME, hostname),
               EntityPredicates.attributeEqualTo(MesosSlave.ADDRESS, hostname)));
   if (found.isPresent()) {
     return (MesosSlave) found.get();
   } else {
     throw new IllegalStateException("Cannot find slave for host: " + hostname);
   }
 }
 @Override
 public List<ApplicationSummary> list(String typeRegex) {
   if (Strings.isBlank(typeRegex)) {
     typeRegex = ".*";
   }
   return FluentIterable.from(mgmt().getApplications())
       .filter(
           EntitlementPredicates.isEntitled(
               mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY))
       .filter(EntityPredicates.hasInterfaceMatching(typeRegex))
       .transform(ApplicationTransformer.FROM_APPLICATION)
       .toList();
 }
  /** De-register our {@link MesosLocation} and its children. */
  @Override
  public void stop() {
    disconnectSensors();

    sensors().set(SERVICE_UP, Boolean.FALSE);

    deleteLocation();

    Duration timeout = config().get(SHUTDOWN_TIMEOUT);

    // Find all applications and stop, blocking for up to five minutes until ended
    try {
      Iterable<Entity> entities =
          Iterables.filter(
              getManagementContext().getEntityManager().getEntities(),
              Predicates.and(
                  MesosUtils.sameCluster(this),
                  Predicates.not(EntityPredicates.applicationIdEqualTo(getApplicationId()))));
      Set<Application> applications =
          ImmutableSet.copyOf(
              Iterables.transform(
                  entities,
                  new Function<Entity, Application>() {
                    @Override
                    public Application apply(Entity input) {
                      return input.getApplication();
                    }
                  }));
      LOG.debug("Stopping applications: {}", Iterables.toString(applications));
      Entities.invokeEffectorList(this, applications, Startable.STOP).get(timeout);
    } catch (Exception e) {
      LOG.warn("Error stopping applications", e);
    }

    // Stop all framework tasks in parallel
    try {
      Group frameworks = sensors().get(MESOS_FRAMEWORKS);
      LOG.debug("Stopping framework tasks in: {}", Iterables.toString(frameworks.getMembers()));
      Entities.invokeEffectorList(this, frameworks.getMembers(), Startable.STOP).get(timeout);
    } catch (Exception e) {
      LOG.warn("Error stopping frameworks", e);
    }

    // Stop anything else left over
    // TODO Stop slave entities
    try {
      super.stop();
    } catch (Exception e) {
      LOG.warn("Error stopping children", e);
    }
  }
  @Test
  public void testEntityCreatingItsEnricherDoesNotReCreateItUnlessUniqueTagDifferent()
      throws Exception {
    TestEntity e1 =
        origApp.createAndManageChild(
            EntitySpec.create(TestEntity.class, MyTestEntityWithEnricher.class));
    Collection<Enricher> e1e = e1.getEnrichers();
    log.info("enrichers1: " + e1e);
    Entities.dumpInfo(e1);
    assertEquals(e1e.size(), 5);

    newApp = (TestApplication) rebind();
    Entity e2 =
        Iterables.getOnlyElement(
            Entities.descendants(newApp, EntityPredicates.idEqualTo(e1.getId())));
    Collection<Enricher> e2e = e2.getEnrichers();
    log.info("enrichers2: " + e2e);
    Entities.dumpInfo(e2);

    assertEquals(e2e.size(), e1e.size() + 1);
  }
  @Override
  public void init() {
    LOG.info("Starting Mesos cluster id {}", getId());
    registerLocationResolver();
    super.init();

    Group slaves = addChild(EntitySpec.create(BasicGroup.class).displayName("Mesos Slaves"));

    Group frameworks =
        addChild(EntitySpec.create(BasicGroup.class).displayName("Mesos Frameworks"));

    DynamicGroup tasks =
        addChild(
            EntitySpec.create(DynamicGroup.class)
                .configure(
                    DynamicGroup.ENTITY_FILTER,
                    Predicates.and(
                        Predicates.instanceOf(MesosTask.class),
                        EntityPredicates.attributeEqualTo(MesosAttributes.MESOS_CLUSTER, this)))
                .displayName("Mesos Tasks"));

    DynamicMultiGroup applications =
        addChild(
            EntitySpec.create(DynamicMultiGroup.class)
                .configure(
                    DynamicMultiGroup.ENTITY_FILTER,
                    Predicates.and(
                        MesosUtils.sameCluster(this),
                        Predicates.not(EntityPredicates.applicationIdEqualTo(getApplicationId()))))
                .configure(DynamicMultiGroup.RESCAN_INTERVAL, 15L)
                .configure(
                    DynamicMultiGroup.BUCKET_FUNCTION,
                    new Function<Entity, String>() {
                      @Override
                      public String apply(@Nullable Entity input) {
                        return input.getApplication().getDisplayName()
                            + ":"
                            + input.getApplicationId();
                      }
                    })
                .configure(DynamicMultiGroup.BUCKET_SPEC, EntitySpec.create(BasicGroup.class))
                .displayName("Mesos Applications"));

    if (config().get(SDN_ENABLE) && config().get(SDN_PROVIDER_SPEC) != null) {
      EntitySpec entitySpec = EntitySpec.create(config().get(SDN_PROVIDER_SPEC));
      entitySpec.configure(MesosAttributes.MESOS_CLUSTER, this);
      Entity sdn = addChild(entitySpec);
      sensors().set(SDN_PROVIDER, sdn);
    }

    sensors().set(MESOS_SLAVES, slaves);
    sensors().set(MESOS_FRAMEWORKS, frameworks);
    sensors().set(MESOS_TASKS, tasks);
    sensors().set(MESOS_APPLICATIONS, applications);

    // Override the health-check: just interested in the slaves, frameworks and sdn (rather than
    // the groups that show the tasks or apps).
    Entity sdn = sensors().get(SDN_PROVIDER);
    enrichers()
        .add(
            EnricherSpec.create(ComputeServiceIndicatorsFromChildrenAndMembers.class)
                .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG)
                .configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_CHILDREN, true)
                .configure(
                    ComputeServiceIndicatorsFromChildrenAndMembers.ENTITY_FILTER,
                    Predicates.or(
                        ImmutableList.of(
                            Predicates.<Entity>equalTo(slaves),
                            Predicates.<Entity>equalTo(frameworks),
                            (sdn == null
                                ? Predicates.<Entity>alwaysFalse()
                                : Predicates.equalTo(sdn))))));
  }
  @Test
  public void testParameterDefaultsUsedInConfig() throws Exception {
    addCatalogItems(
        "brooklyn.catalog:",
        "  version: " + TEST_VERSION,
        "  items:",
        "    - id: " + ConfigEntityForTest.class.getSimpleName() + "WithParams",
        "      itemType: entity",
        "      item:",
        "        type: " + ConfigEntityForTest.class.getName(),
        "        brooklyn.parameters:",
        "          - name: num",
        "            type: integer",
        "            default: 1234",
        "        brooklyn.children:",
        "          - type: " + BasicStartable.class.getName(),
        "            name: s",
        "            brooklyn.config:",
        "              test: $brooklyn:parent().config(\"num\")",
        "    - id: " + SYMBOLIC_NAME,
        "      itemType: entity",
        "      item:",
        "        type: " + BasicApplication.class.getName(),
        "        brooklyn.children:",
        "          - type: " + ConfigEntityForTest.class.getSimpleName() + "WithParams",
        "            name: a",
        "          - type: " + ConfigEntityForTest.class.getSimpleName() + "WithParams",
        "            name: b",
        "            brooklyn.config:",
        "              num: 5678",
        "          - type: " + ConfigEntityForTest.class.getSimpleName() + "WithParams",
        "            name: c",
        "            brooklyn.config:",
        "              test: $brooklyn:config(\"num\")");

    CatalogItem<?, ?> item =
        catalog.getCatalogItem(
            ConfigEntityForTest.class.getSimpleName() + "WithParams", TEST_VERSION);
    AbstractBrooklynObjectSpec<?, ?> spec = createSpec(item);
    List<SpecParameter<?>> params = spec.getParameters();
    assertEquals(params.size(), 3);
    assertTrue(Iterables.tryFind(params, nameEqualTo("num")).isPresent());

    Application app =
        (Application) createAndStartApplication("services:", "  - type: " + ver(SYMBOLIC_NAME));

    Iterable<Entity> children = app.getChildren();
    Optional<Entity> a = Iterables.tryFind(children, EntityPredicates.displayNameEqualTo("a"));
    assertTrue(a.isPresent());
    assertEquals(a.get().config().get(NUM).intValue(), 1234);
    Optional<Entity> as =
        Iterables.tryFind(a.get().getChildren(), EntityPredicates.displayNameEqualTo("s"));
    assertTrue(as.isPresent());
    assertEquals(as.get().config().get(ConfigKeys.newIntegerConfigKey("test")).intValue(), 1234);
    Optional<Entity> b = Iterables.tryFind(children, EntityPredicates.displayNameEqualTo("b"));
    assertTrue(b.isPresent());
    assertEquals(b.get().config().get(NUM).intValue(), 5678);
    Optional<Entity> bs =
        Iterables.tryFind(b.get().getChildren(), EntityPredicates.displayNameEqualTo("s"));
    assertTrue(bs.isPresent());
    assertEquals(bs.get().config().get(ConfigKeys.newIntegerConfigKey("test")).intValue(), 5678);
    Optional<Entity> c = Iterables.tryFind(children, EntityPredicates.displayNameEqualTo("c"));
    assertTrue(c.isPresent());
    assertEquals(c.get().config().get(ConfigKeys.newIntegerConfigKey("test")).intValue(), 1234);
    Optional<Entity> cs =
        Iterables.tryFind(c.get().getChildren(), EntityPredicates.displayNameEqualTo("s"));
    assertTrue(cs.isPresent());
    assertEquals(cs.get().config().get(ConfigKeys.newIntegerConfigKey("test")).intValue(), 1234);
  }