public static ChefModes detectChefMode(Entity entity) {
   ChefModes mode = entity.getConfig(ChefConfig.CHEF_MODE);
   if (mode == ChefModes.AUTODETECT) {
     // TODO server via API
     ProcessTaskWrapper<Boolean> installCheck =
         DynamicTasks.queue(ChefServerTasks.isKnifeInstalled());
     mode = installCheck.get() ? ChefModes.KNIFE : ChefModes.SOLO;
     log.debug(
         "Using Chef in "
             + mode
             + " mode due to autodetect exit code "
             + installCheck.getExitCode());
   }
   Preconditions.checkNotNull(
       mode, "Non-null " + ChefConfig.CHEF_MODE + " required for " + entity);
   return mode;
 }
  @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
  protected void startWithKnifeAsync() {
    // TODO prestart, ports (as above); also, note, some aspects of this are untested as we need a
    // chef server

    String primary = getPrimaryCookbook();

    // put all config under brooklyn/cookbook/config
    Navigator<MutableMap<Object, Object>> attrs = Jsonya.newInstancePrimitive().at("brooklyn");
    if (Strings.isNonBlank(primary)) attrs.at(primary);
    attrs.at("config");
    attrs.put(entity().getAllConfigBag().getAllConfig());
    // and put launch attrs at root
    try {
      attrs
          .root()
          .put(
              (Map<?, ?>)
                  Tasks.resolveDeepValue(
                      entity().getConfig(CHEF_LAUNCH_ATTRIBUTES),
                      Object.class,
                      entity().getExecutionContext()));
    } catch (Exception e) {
      Exceptions.propagate(e);
    }

    Collection<? extends String> runList = entity().getConfig(CHEF_LAUNCH_RUN_LIST);
    if (runList == null) runList = entity().getConfig(CHEF_RUN_LIST);
    if (runList == null) {
      if (Strings.isNonBlank(primary)) runList = ImmutableList.of(primary + "::" + "start");
      else
        throw new IllegalStateException(
            "Require a primary cookbook or a run_list to effect " + "start" + " on " + entity());
    }

    DynamicTasks.queue(
        ChefServerTasks.knifeConvergeTask()
            .knifeNodeName(getNodeName())
            .knifeRunList(Strings.join(runList, ","))
            .knifeAddAttributes((Map<? extends Object, ? extends Object>) (Map) attrs.root().get())
            .knifeRunTwice(entity().getConfig(CHEF_RUN_CONVERGE_TWICE)));
  }