public LocalManagementContext(
      Builder builder,
      Map<String, Object> brooklynAdditionalProperties,
      DataGridFactory datagridFactory) {
    super(builder.build(), datagridFactory);
    // TODO in a persisted world the planeId may be injected
    this.managementPlaneId = Strings.makeRandomId(8);

    this.managementNodeId = Strings.makeRandomId(8);
    checkNotNull(configMap, "brooklynProperties");
    this.builder = builder;
    this.brooklynAdditionalProperties = brooklynAdditionalProperties;
    if (brooklynAdditionalProperties != null) configMap.addFromMap(brooklynAdditionalProperties);

    this.locationManager = new LocalLocationManager(this);
    this.accessManager = new LocalAccessManager();
    this.usageManager = new LocalUsageManager(this);

    if (configMap.getConfig(OsgiManager.USE_OSGI)) {
      this.osgiManager = new OsgiManager();
      osgiManager.start();
    }

    INSTANCES.add(this);
    log.debug("Created management context " + this);
  }
  public String configFile() {
    // Check template URL exists
    String templateUrl = driver.getEntity().getConfig(NginxController.SERVER_CONF_TEMPLATE_URL);
    ResourceUtils.create(this).checkUrlExists(templateUrl);

    // Check SSL configuration
    ProxySslConfig ssl = driver.getEntity().getConfig(NginxController.SSL_CONFIG);
    if (ssl != null
        && Strings.isEmpty(ssl.getCertificateDestination())
        && Strings.isEmpty(ssl.getCertificateSourceUrl())) {
      throw new IllegalStateException(
          "ProxySslConfig can't have a null certificateDestination and null certificateSourceUrl. One or both need to be set");
    }

    // For mapping by URL
    Iterable<UrlMapping> mappings = ((NginxController) driver.getEntity()).getUrlMappings();
    Multimap<String, UrlMapping> mappingsByDomain = LinkedHashMultimap.create();
    for (UrlMapping mapping : mappings) {
      Collection<String> addrs = mapping.getAttribute(UrlMapping.TARGET_ADDRESSES);
      if (addrs != null && addrs.size() > 0) {
        mappingsByDomain.put(mapping.getDomain(), mapping);
      }
    }
    Map<String, Object> substitutions =
        MutableMap.<String, Object>builder()
            .putIfNotNull("ssl", ssl)
            .put("urlMappings", mappings)
            .put("domainMappings", mappingsByDomain)
            .build();

    // Get template contents and process
    String contents = ResourceUtils.create(driver.getEntity()).getResourceAsString(templateUrl);
    return TemplateProcessor.processTemplateContents(contents, driver, substitutions);
  }
 /**
  * attempts to resolve hostnameTarget from origin
  *
  * @return null if it definitively can't be resolved, best-effort IP address if possible, or blank
  *     if we could not run ssh or make sense of the output
  */
 public static String getResolvedAddress(
     Entity entity, SshMachineLocation origin, String hostnameTarget) {
   ProcessTaskWrapper<Integer> task =
       SshTasks.newSshExecTaskFactory(origin, "ping -c 1 -t 1 " + hostnameTarget)
           .summary("checking resolution of " + hostnameTarget)
           .allowingNonZeroExitCode()
           .newTask();
   DynamicTasks.queueIfPossible(task).orSubmitAndBlock(entity).asTask().blockUntilEnded();
   if (task.asTask().isError()) {
     log.warn(
         "ping could not be run, at "
             + entity
             + " / "
             + origin
             + ": "
             + Tasks.getError(task.asTask()));
     return "";
   }
   if (task.getExitCode() == null || task.getExitCode() != 0) {
     if (task.getExitCode() != null && task.getExitCode() < 10) {
       // small number means ping failed to resolve or ping the hostname
       log.debug(
           "not able to resolve "
               + hostnameTarget
               + " from "
               + origin
               + " for "
               + entity
               + " because exit code was "
               + task.getExitCode());
       return null;
     }
     // large number means ping probably did not run
     log.warn(
         "ping not run as expected, at "
             + entity
             + " / "
             + origin
             + " (code "
             + task.getExitCode()
             + "):\n"
             + task.getStdout().trim()
             + " --- "
             + task.getStderr().trim());
     return "";
   }
   String out = task.getStdout();
   try {
     String line1 = Strings.getFirstLine(out);
     String ip = Strings.getFragmentBetween(line1, "(", ")");
     if (Strings.isNonBlank(ip)) return ip;
   } catch (Exception e) {
     Exceptions.propagateIfFatal(e);
     /* ignore non-parseable output */
   }
   if (out.contains("127.0.0.1")) return "127.0.0.1";
   return "";
 }
  /**
   * true if the URL points to content which must be resolved on the server-side (i.e. classpath)
   * and which is safe to do so (currently just images, though in future perhaps also javascript and
   * html plugins)
   *
   * <p>note we do not let caller access classpath through this mechanism, just those which are
   * supplied by the platform administrator e.g. as an icon url
   */
  public boolean isUrlServerSideAndSafe(String url) {
    if (Strings.isEmpty(url)) return false;
    String ext = Files.getFileExtension(url);
    if (Strings.isEmpty(ext)) return false;
    MediaType mime = WebResourceUtils.getImageMediaTypeFromExtension(ext);
    if (mime == null) return false;

    return !Urls.isUrlWithProtocol(url) || url.startsWith("classpath:");
  }
  private DownloadResolver newDownloader(DownloadRequirement req) {
    // Infer filename
    String filename = null;
    for (Function<? super DownloadRequirement, String> filenameProducer : filenameProducers) {
      filename = filenameProducer.apply(req);
      if (!Strings.isBlank(filename)) break;
    }

    // If a filename-producer has given us the filename, then augment the DownloadRequirement with
    // that
    // (so that local-repo substitutions etc can use that explicit filename)
    DownloadRequirement wrappedReq;
    if (filename == null) {
      wrappedReq = req;
    } else {
      wrappedReq = BasicDownloadRequirement.copy(req, ImmutableMap.of("filename", filename));
    }

    // Get ordered download targets to be tried
    List<String> primaries = Lists.newArrayList();
    List<String> fallbacks = Lists.newArrayList();
    for (Function<? super DownloadRequirement, ? extends DownloadTargets> producer : producers) {
      DownloadTargets vals = producer.apply(wrappedReq);
      primaries.addAll(vals.getPrimaryLocations());
      fallbacks.addAll(vals.getFallbackLocations());
      if (!vals.canContinueResolving()) {
        break;
      }
    }

    Set<String> result = Sets.newLinkedHashSet();
    result.addAll(primaries);
    result.addAll(fallbacks);

    if (result.isEmpty()) {
      throw new IllegalArgumentException("No downloads matched for " + req);
    }

    // If filename-producers didn't give any explicit filename, then infer from download results
    if (filename == null) {
      for (String target : result) {
        filename = FilenameProducers.inferFilename(target);
        if (!Strings.isBlank(filename)) break;
      }
    }
    if (Strings.isBlank(filename)) {
      throw new IllegalArgumentException(
          "No filenames matched for " + req + " (targets " + result + ")");
    }

    // And return the result
    return new BasicDownloadResolver(result, filename);
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  private <T extends Entity> brooklyn.entity.proxying.EntitySpec<?> toCoreEntitySpec(
      Class<T> clazz, String name, Map<String, String> configO) {
    Map<String, String> config =
        (configO == null)
            ? Maps.<String, String>newLinkedHashMap()
            : Maps.newLinkedHashMap(configO);

    brooklyn.entity.proxying.EntitySpec<? extends Entity> result;
    if (clazz.isInterface()) {
      result = brooklyn.entity.proxying.EntitySpec.create(clazz);
    } else {
      // If this is a concrete class, particularly for an Application class, we want the proxy
      // to expose all interfaces it implements.
      Class interfaceclazz =
          (Application.class.isAssignableFrom(clazz)) ? Application.class : Entity.class;
      Set<Class<?>> additionalInterfaceClazzes =
          Reflections.getInterfacesIncludingClassAncestors(clazz);
      result =
          brooklyn.entity.proxying.EntitySpec.create(interfaceclazz)
              .impl(clazz)
              .additionalInterfaces(additionalInterfaceClazzes);
    }

    if (!Strings.isEmpty(name)) result.displayName(name);
    result.configure(convertFlagsToKeys(result.getImplementation(), config));
    return result;
  }
  @SuppressWarnings("unchecked")
  private brooklyn.entity.proxying.EntitySpec<? extends Entity> toCoreEntitySpec(
      brooklyn.rest.domain.EntitySpec spec) {
    String type = spec.getType();
    String name = spec.getName();
    Map<String, String> config =
        (spec.getConfig() == null)
            ? Maps.<String, String>newLinkedHashMap()
            : Maps.newLinkedHashMap(spec.getConfig());

    Class<? extends Entity> tempclazz;
    try {
      tempclazz = getCatalog().loadClassByType(type, Entity.class);
    } catch (NoSuchElementException e) {
      try {
        tempclazz = (Class<? extends Entity>) getCatalog().getRootClassLoader().loadClass(type);
        log.info("Catalog does not contain item for type {}; loaded class directly instead", type);
      } catch (ClassNotFoundException e2) {
        log.warn(
            "No catalog item for type {}, and could not load class directly; rethrowing", type);
        throw e;
      }
    }
    final Class<? extends Entity> clazz = tempclazz;
    brooklyn.entity.proxying.EntitySpec<? extends Entity> result;
    if (clazz.isInterface()) {
      result = brooklyn.entity.proxying.EntitySpec.create(clazz);
    } else {
      result = brooklyn.entity.proxying.EntitySpec.create(Entity.class).impl(clazz);
    }
    if (!Strings.isEmpty(name)) result.displayName(name);
    result.configure(convertFlagsToKeys(result.getType(), config));
    configureRenderingMetadata(spec, result);
    return result;
  }
 @Deprecated
 public static String fixLocation(String locationId) {
   if (locationId.startsWith("/v1/locations/")) {
     log.warn("REST API using legacy URI syntax for location: " + locationId);
     locationId = Strings.removeFromStart(locationId, "/v1/locations/");
   }
   return locationId;
 }
  public static Map<ConfigKey<String>, String> finalAndOriginalSpecs(
      String finalSpec, Object... sourcesForOriginalSpec) {
    // yuck!: TODO should clean up how these things get passed around
    Map<ConfigKey<String>, String> result = MutableMap.of();
    if (finalSpec != null) result.put(LocationInternal.FINAL_SPEC, finalSpec);

    String originalSpec = null;
    for (Object source : sourcesForOriginalSpec) {
      if (source instanceof CharSequence) originalSpec = source.toString();
      else if (source instanceof Map) {
        if (originalSpec == null)
          originalSpec = Strings.toString(((Map<?, ?>) source).get(LocationInternal.ORIGINAL_SPEC));
        if (originalSpec == null)
          originalSpec =
              Strings.toString(((Map<?, ?>) source).get(LocationInternal.ORIGINAL_SPEC.getName()));
      }
      if (originalSpec != null) break;
    }
    if (originalSpec == null) originalSpec = finalSpec;
    if (originalSpec != null) result.put(LocationInternal.ORIGINAL_SPEC, originalSpec);

    return result;
  }
 static String makeCommandExecutingInDirectory(
     String command, String executionDir, EntityLocal entity) {
   String finalCommand = command;
   String execDir = executionDir;
   if (Strings.isBlank(execDir)) {
     // default to run dir
     execDir = entity.getAttribute(SoftwareProcess.RUN_DIR);
     // if no run dir, default to home
     if (Strings.isBlank(execDir)) {
       execDir = "~";
     }
   } else if (!Os.isAbsolutish(execDir)) {
     // relative paths taken wrt run dir
     String runDir = entity.getAttribute(SoftwareProcess.RUN_DIR);
     if (!Strings.isBlank(runDir)) {
       execDir = Os.mergePaths(runDir, execDir);
     }
   }
   if (!"~".equals(execDir)) {
     finalCommand = "mkdir -p '" + execDir + "' && cd '" + execDir + "' && " + finalCommand;
   }
   return finalCommand;
 }
  @Override
  public void customize() {
    newScript(CUSTOMIZING)
        .body
        .append(
            format("mkdir -p %s", getRunDir()),
            format("cp -R %s/dist/{conf,html,logs,sbin} %s", getExpandedInstallDir(), getRunDir()))
        .execute();

    // Install static content archive, if specified
    String archiveUrl = entity.getConfig(NginxController.STATIC_CONTENT_ARCHIVE_URL);
    if (Strings.isNonBlank(archiveUrl)) {
      getEntity().deploy(archiveUrl);
    }

    customizationCompleted = true;
    getEntity().doExtraConfigurationDuringStart();
  }
 @SuppressWarnings("rawtypes")
 private static void addNamedAction(
     MutableMap.Builder<String, URI> lb,
     RendererHints.NamedAction na,
     Entity entity,
     Sensor<?> sensor) {
   if (na instanceof RendererHints.NamedActionWithUrl) {
     try {
       String v =
           ((RendererHints.NamedActionWithUrl) na).getUrl(entity, (AttributeSensor<?>) sensor);
       if (Strings.isNonBlank(v)) {
         String action = na.getActionName().toLowerCase();
         lb.putIfAbsent("action:" + action, URI.create(v));
       }
     } catch (Exception e) {
       Exceptions.propagateIfFatal(e);
       log.warn("Unable to make use of URL sensor " + sensor + " on " + entity + ": " + e);
     }
   }
 }
Example #13
0
 public String getSummary() {
   if (summary != null) return summary;
   return Strings.join(commands, " ; ");
 }
  @Override
  public void install() {
    // will fail later if can't sudo (if sudo is required)
    DynamicTasks.queueIfPossible(SshTasks.dontRequireTtyForSudo(getMachine(), false))
        .orSubmitAndBlock();

    DownloadResolver nginxResolver = mgmt().getEntityDownloadsManager().newDownloader(this);
    List<String> nginxUrls = nginxResolver.getTargets();
    String nginxSaveAs = nginxResolver.getFilename();
    setExpandedInstallDir(
        getInstallDir()
            + "/"
            + nginxResolver.getUnpackedDirectoryName(format("nginx-%s", getVersion())));

    boolean sticky = ((NginxController) entity).isSticky();
    boolean isMac = getMachine().getOsDetails().isMac();

    MutableMap<String, String> installGccPackageFlags =
        MutableMap.of(
            "onlyifmissing", "gcc",
            "yum", "gcc",
            "apt", "gcc",
            "zypper", "gcc",
            "port", null);
    MutableMap<String, String> installMakePackageFlags =
        MutableMap.of(
            "onlyifmissing", "make",
            "yum", "make",
            "apt", "make",
            "zypper", "make",
            "port", null);
    MutableMap<String, String> installPackageFlags =
        MutableMap.of(
            "yum", "openssl-devel pcre-devel",
            "apt", "libssl-dev zlib1g-dev libpcre3-dev",
            "zypper", "libopenssl-devel pcre-devel",
            "port", null);

    String stickyModuleVersion = entity.getConfig(NginxController.STICKY_VERSION);
    DownloadResolver stickyModuleResolver =
        mgmt()
            .getEntityDownloadsManager()
            .newDownloader(
                this, "stickymodule", ImmutableMap.of("addonversion", stickyModuleVersion));
    List<String> stickyModuleUrls = stickyModuleResolver.getTargets();
    String stickyModuleSaveAs = stickyModuleResolver.getFilename();
    String stickyModuleExpandedInstallDir =
        String.format(
            "%s/src/%s",
            getExpandedInstallDir(),
            stickyModuleResolver.getUnpackedDirectoryName(
                "nginx-sticky-module-" + stickyModuleVersion));

    List<String> cmds = Lists.newArrayList();

    cmds.add(BashCommands.INSTALL_TAR);
    cmds.add(
        BashCommands.alternatives(
            BashCommands.ifExecutableElse0(
                "apt-get", BashCommands.installPackage("build-essential")),
            BashCommands.ifExecutableElse0(
                "yum",
                BashCommands.sudo("yum -y --nogpgcheck groupinstall \"Development Tools\""))));
    cmds.add(BashCommands.installPackage(installGccPackageFlags, "nginx-prerequisites-gcc"));
    cmds.add(BashCommands.installPackage(installMakePackageFlags, "nginx-prerequisites-make"));
    cmds.add(BashCommands.installPackage(installPackageFlags, "nginx-prerequisites"));
    cmds.addAll(BashCommands.commandsToDownloadUrlsAs(nginxUrls, nginxSaveAs));

    String pcreExpandedInstallDirname = "";
    if (isMac) {
      String pcreVersion = entity.getConfig(NginxController.PCRE_VERSION);
      DownloadResolver pcreResolver =
          mgmt()
              .getEntityDownloadsManager()
              .newDownloader(this, "pcre", ImmutableMap.of("addonversion", pcreVersion));
      List<String> pcreUrls = pcreResolver.getTargets();
      String pcreSaveAs = pcreResolver.getFilename();
      pcreExpandedInstallDirname = pcreResolver.getUnpackedDirectoryName("pcre-" + pcreVersion);

      // Install PCRE
      cmds.addAll(BashCommands.commandsToDownloadUrlsAs(pcreUrls, pcreSaveAs));
      cmds.add(format("mkdir -p %s/pcre-dist", getInstallDir()));
      cmds.add(format("tar xvzf %s", pcreSaveAs));
      cmds.add(format("cd %s", pcreExpandedInstallDirname));
      cmds.add(format("./configure --prefix=%s/pcre-dist", getInstallDir()));
      cmds.add("make");
      cmds.add("make install");
      cmds.add("cd ..");
    }

    cmds.add(format("tar xvzf %s", nginxSaveAs));
    cmds.add(format("cd %s", getExpandedInstallDir()));

    if (sticky) {
      cmds.add("cd src");
      cmds.addAll(BashCommands.commandsToDownloadUrlsAs(stickyModuleUrls, stickyModuleSaveAs));
      cmds.add(format("tar xvzf %s", stickyModuleSaveAs));
      cmds.add("cd ..");
    }

    // Note that for OS X, not including space after "-L" because broken in 10.6.8 (but fixed in
    // 10.7.x)
    //      see http://trac.nginx.org/nginx/ticket/227
    String withLdOpt = entity.getConfig(NginxController.WITH_LD_OPT);
    if (isMac)
      withLdOpt =
          format("-L%s/pcre-dist/lib", getInstallDir())
              + (Strings.isBlank(withLdOpt) ? "" : " " + withLdOpt);
    String withCcOpt = entity.getConfig(NginxController.WITH_CC_OPT);

    StringBuilder configureCommand =
        new StringBuilder("./configure")
            .append(format(" --prefix=%s/dist", getExpandedInstallDir()))
            .append(" --with-http_ssl_module")
            .append(sticky ? format(" --add-module=%s ", stickyModuleExpandedInstallDir) : "")
            .append(!Strings.isBlank(withLdOpt) ? format(" --with-ld-opt=\"%s\"", withLdOpt) : "")
            .append(!Strings.isBlank(withCcOpt) ? format(" --with-cc-opt=\"%s\"", withCcOpt) : "");
    if (isMac) {
      configureCommand
          .append(" --with-pcre=")
          .append(getInstallDir())
          .append("/")
          .append(pcreExpandedInstallDirname);
    }

    cmds.addAll(ImmutableList.of("mkdir -p dist", configureCommand.toString(), "make install"));

    ScriptHelper script =
        newScript(INSTALLING)
            .body
            .append(cmds)
            .header
            .prepend("set -x")
            .gatherOutput()
            .failOnNonZeroResultCode(false);

    int result = script.execute();

    if (result != 0) {
      String notes =
          "likely an error building nginx. consult the brooklyn log ssh output for further details.\n"
              + "note that this Brooklyn nginx driver compiles nginx from source. "
              + "it attempts to install common prerequisites but this does not always succeed.\n";
      OsDetails os = getMachine().getOsDetails();
      if (os.isMac()) {
        notes +=
            "deploying to Mac OS X, you will require Xcode and Xcode command-line tools, and on "
                + "some versions the pcre library (e.g. using macports, sudo port install pcre).\n";
      }
      if (os.isWindows()) {
        notes +=
            "this nginx driver is not designed for windows, unless cygwin is installed, and you are patient.\n";
      }
      if (getEntity().getApplication().getClass().getCanonicalName().startsWith("brooklyn.demo.")) {
        // this is maybe naughty ... but since we use nginx in the first demo example,
        // and since it's actually pretty complicated, let's give a little extra hand-holding
        notes +=
            "if debugging this is all a bit much and you just want to run a demo, "
                + "you have two fairly friendly options.\n"
                + "1. you can use a well known cloud, like AWS or Rackspace, where this should run "
                + "in a tried-and-tested Ubuntu or CentOS environment, without any problems "
                + "(and if it does let us know and we'll fix it!).\n"
                + "2. or you can just use the demo without nginx, instead access the appserver instances directly.\n";
      }

      if (!script.getResultStderr().isEmpty()) {
        notes += "\n" + "STDERR\n" + script.getResultStderr() + "\n";
        Streams.logStreamTail(
            log,
            "STDERR of problem in " + Tasks.current(),
            Streams.byteArrayOfString(script.getResultStderr()),
            1024);
      }
      if (!script.getResultStdout().isEmpty()) {
        notes += "\n" + "STDOUT\n" + script.getResultStdout() + "\n";
        Streams.logStreamTail(
            log,
            "STDOUT of problem in " + Tasks.current(),
            Streams.byteArrayOfString(script.getResultStdout()),
            1024);
      }

      Tasks.setExtraStatusDetails(notes.trim());

      throw new IllegalStateException(
          "Installation of nginx failed (shell returned non-zero result " + result + ")");
    }
  }
  @SuppressWarnings("unchecked")
  public Application create(ApplicationSpec spec) {
    log.debug("REST creating application instance for {}", spec);

    if (!Entitlements.isEntitled(
        mgmt.getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, spec)) {
      throw WebResourceUtils.unauthorized(
          "User '%s' is not authorized to deploy application %s",
          Entitlements.getEntitlementContext().user(), spec);
    }

    final String type = spec.getType();
    final String name = spec.getName();
    final Map<String, String> configO = spec.getConfig();
    final Set<EntitySpec> entities =
        (spec.getEntities() == null) ? ImmutableSet.<EntitySpec>of() : spec.getEntities();

    final Application instance;

    // Load the class; first try to use the appropriate catalog item; but then allow anything that
    // is on the classpath
    final Class<? extends Entity> clazz;
    if (Strings.isEmpty(type)) {
      clazz = BasicApplication.class;
    } else {
      Class<? extends Entity> tempclazz;
      try {
        tempclazz = getCatalog().loadClassByType(type, Entity.class);
      } catch (NoSuchElementException e) {
        try {
          tempclazz = (Class<? extends Entity>) getCatalog().getRootClassLoader().loadClass(type);
          log.info(
              "Catalog does not contain item for type {}; loaded class directly instead", type);
        } catch (ClassNotFoundException e2) {
          log.warn(
              "No catalog item for type {}, and could not load class directly; rethrowing", type);
          throw e;
        }
      }
      clazz = tempclazz;
    }
    if (Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, null)) {

      try {
        if (ApplicationBuilder.class.isAssignableFrom(clazz)) {
          Constructor<?> constructor = clazz.getConstructor();
          ApplicationBuilder appBuilder = (ApplicationBuilder) constructor.newInstance();
          if (!Strings.isEmpty(name)) appBuilder.appDisplayName(name);
          if (entities.size() > 0)
            log.warn(
                "Cannot supply additional entities when using an ApplicationBuilder; ignoring in spec {}",
                spec);

          log.info("REST placing '{}' under management", spec.getName());
          appBuilder.configure(convertFlagsToKeys(appBuilder.getType(), configO));
          configureRenderingMetadata(spec, appBuilder);
          instance = appBuilder.manage(mgmt);

        } else if (Application.class.isAssignableFrom(clazz)) {
          brooklyn.entity.proxying.EntitySpec<?> coreSpec = toCoreEntitySpec(clazz, name, configO);
          configureRenderingMetadata(spec, coreSpec);
          instance = (Application) mgmt.getEntityManager().createEntity(coreSpec);
          for (EntitySpec entitySpec : entities) {
            log.info("REST creating instance for entity {}", entitySpec.getType());
            instance.addChild(mgmt.getEntityManager().createEntity(toCoreEntitySpec(entitySpec)));
          }

          log.info(
              "REST placing '{}' under management", spec.getName() != null ? spec.getName() : spec);
          Entities.startManagement(instance, mgmt);

        } else if (Entity.class.isAssignableFrom(clazz)) {
          if (entities.size() > 0)
            log.warn(
                "Cannot supply additional entities when using a non-application entity; ignoring in spec {}",
                spec);

          brooklyn.entity.proxying.EntitySpec<?> coreSpec =
              toCoreEntitySpec(BasicApplication.class, name, configO);
          configureRenderingMetadata(spec, coreSpec);

          instance = (Application) mgmt.getEntityManager().createEntity(coreSpec);

          final Class<? extends Entity> eclazz =
              getCatalog().loadClassByType(spec.getType(), Entity.class);
          Entity soleChild =
              mgmt.getEntityManager().createEntity(toCoreEntitySpec(eclazz, name, configO));
          instance.addChild(soleChild);
          instance.addEnricher(Enrichers.builder().propagatingAll().from(soleChild).build());

          log.info("REST placing '{}' under management", spec.getName());
          Entities.startManagement(instance, mgmt);

        } else {
          throw new IllegalArgumentException(
              "Class " + clazz + " must extend one of ApplicationBuilder, Application or Entity");
        }

        return instance;

      } catch (Exception e) {
        log.error("REST failed to create application: " + e, e);
        throw Exceptions.propagate(e);
      }
    }
    throw WebResourceUtils.unauthorized(
        "User '%s' is not authorized to create application from applicationSpec %s",
        Entitlements.getEntitlementContext().user(), spec);
  }
 @Override
 public boolean isAuthenticated(HttpSession session) {
   if (session == null) return false;
   Object value = session.getAttribute(getAuthenticationKey());
   return Strings.isNonBlank(Strings.toString(value));
 }