Search in sources :

Example 1 with InputValidationException

use of com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException in project aws-greengrass-nucleus by aws-greengrass.

the class GreengrassService method setupDependencies.

private synchronized void setupDependencies(Collection<String> dependencyList) throws ServiceLoadException, InputValidationException {
    Map<GreengrassService, DependencyType> oldDependencies = new HashMap<>(getDependencies());
    Map<GreengrassService, DependencyType> keptDependencies = getDependencyTypeMap(dependencyList);
    Set<GreengrassService> removedDependencies = dependencies.entrySet().stream().filter(e -> !keptDependencies.containsKey(e.getKey()) && !e.getValue().isDefaultDependency).map(Map.Entry::getKey).collect(Collectors.toSet());
    if (!removedDependencies.isEmpty()) {
        logger.atDebug("removing-unused-dependencies").kv("removedDependencies", removedDependencies).log();
        removedDependencies.forEach(dependency -> {
            DependencyInfo dependencyInfo = dependencies.remove(dependency);
            dependency.removeStateSubscriber(dependencyInfo.stateTopicSubscriber);
        });
        context.get(Kernel.class).clearODcache();
    }
    AtomicBoolean hasNewService = new AtomicBoolean(false);
    keptDependencies.forEach((dependentService, dependencyType) -> {
        try {
            if (!oldDependencies.containsKey(dependentService)) {
                hasNewService.set(true);
            }
            addOrUpdateDependency(dependentService, dependencyType, false);
        } catch (InputValidationException e) {
            logger.atWarn("add-dependency").log("Unable to add dependency {}", dependentService, e);
        }
    });
    if (hasNewService.get()) {
        requestRestart();
    } else if (!dependencyReady() && !getState().equals(State.FINISHED)) {
        // if dependency type changed, restart this service.
        requestRestart();
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) DependencyType(com.amazon.aws.iot.greengrass.component.common.DependencyType) InputValidationException(com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 2 with InputValidationException

use of com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException in project aws-greengrass-nucleus by aws-greengrass.

the class GreengrassService method parseSingleDependency.

/**
 * Parse a string into a dependency specification.
 *
 * @param dependency string in the format of one service dependency
 * @return a pair of dependency name and type
 * @throws InputValidationException if the dependency string has invalid format
 */
public static Pair<String, DependencyType> parseSingleDependency(String dependency) throws InputValidationException {
    String[] dependencyInfo = dependency.split(":");
    if (dependencyInfo.length == 0 || dependencyInfo.length > 2) {
        throw new InputValidationException("Bad dependency syntax");
    }
    String typeString = dependencyInfo.length > 1 ? dependencyInfo[1] : null;
    DependencyType type = null;
    if (typeString != null && !typeString.isEmpty()) {
        // do "friendly" match
        for (DependencyType s : DependencyType.values()) {
            if (typeString.regionMatches(true, 0, s.name(), 0, typeString.length())) {
                type = s;
                break;
            }
        }
        if (type == null) {
            throw new InputValidationException(typeString + " does not match any Service dependency type");
        }
    }
    return new Pair<>(dependencyInfo[0], type == null ? DependencyType.HARD : type);
}
Also used : DependencyType(com.amazon.aws.iot.greengrass.component.common.DependencyType) InputValidationException(com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException) Pair(com.aws.greengrass.util.Pair)

Example 3 with InputValidationException

use of com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException in project aws-greengrass-nucleus by aws-greengrass.

the class GreengrassService method addOrUpdateDependency.

/**
 * Add a dependency.
 *
 * @param dependentGreengrassService the service to add as a dependency.
 * @param dependencyType            type of the dependency.
 * @param isDefault                 True if the dependency is added without explicit declaration in 'dependencies'
 *                                  Topic.
 * @throws InputValidationException if the provided arguments are invalid.
 */
public synchronized void addOrUpdateDependency(GreengrassService dependentGreengrassService, DependencyType dependencyType, boolean isDefault) throws InputValidationException {
    if (dependentGreengrassService == null || dependencyType == null) {
        throw new InputValidationException("One or more parameters was null");
    }
    dependencies.compute(dependentGreengrassService, (dependentService, dependencyInfo) -> {
        // new subscriber with updated input.
        if (dependencyInfo != null) {
            dependentGreengrassService.removeStateSubscriber(dependencyInfo.stateTopicSubscriber);
        }
        Subscriber subscriber = createDependencySubscriber(dependentGreengrassService, dependencyType);
        dependentGreengrassService.addStateSubscriber(subscriber);
        context.get(Kernel.class).clearODcache();
        return new DependencyInfo(dependencyType, isDefault, subscriber);
    });
}
Also used : Subscriber(com.aws.greengrass.config.Subscriber) InputValidationException(com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException)

Example 4 with InputValidationException

use of com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException in project aws-greengrass-nucleus by aws-greengrass.

the class Kernel method locateGreengrassService.

@SuppressWarnings({ "UseSpecificCatch", "PMD.AvoidCatchingThrowable", "PMD.AvoidDeeplyNestedIfStmts", "PMD.ConfusingTernary" })
private GreengrassService locateGreengrassService(Context.Value v, String name, CrashableFunction<String, GreengrassService, ServiceLoadException> locateFunction) throws ServiceLoadException {
    Topics serviceRootTopics = findServiceTopic(name);
    Class<?> clazz = null;
    if (serviceRootTopics != null) {
        // Try locating all the dependencies first so that they'll all exist prior to their dependant.
        // This is to fix an ordering problem with plugins such as lambda manager. The plugin needs to be
        // located *before* the dependant is located so that the plugin has its jar loaded into the classloader.
        Topic dependenciesTopic = serviceRootTopics.findLeafChild(SERVICE_DEPENDENCIES_NAMESPACE_TOPIC);
        if (dependenciesTopic != null && dependenciesTopic.getOnce() instanceof Collection) {
            try {
                for (Pair<String, DependencyType> p : GreengrassService.parseDependencies((Collection<String>) dependenciesTopic.getOnce())) {
                    locateFunction.apply(p.getLeft());
                }
            } catch (ServiceLoadException | InputValidationException e) {
                throw new ServiceLoadException("Unable to load service " + name, e);
            }
        }
        Topic classTopic = serviceRootTopics.findLeafChild(SERVICE_CLASS_TOPIC_KEY);
        String className = null;
        // If a "class" is specified in the recipe, then use that
        if (classTopic != null) {
            className = Coerce.toString(classTopic);
        } else {
            Topic componentTypeTopic = serviceRootTopics.findLeafChild(SERVICE_TYPE_TOPIC_KEY);
            // If a "componentType" is specified, then map that to a class
            if (componentTypeTopic != null) {
                className = ((Map<String, String>) context.getvIfExists(SERVICE_TYPE_TO_CLASS_MAP_KEY).get()).get(Coerce.toString(componentTypeTopic).toLowerCase());
                // plugin
                if (className == null && Coerce.toString(componentTypeTopic).equalsIgnoreCase(PLUGIN_SERVICE_TYPE_NAME)) {
                    clazz = locateExternalPlugin(name, serviceRootTopics);
                }
            }
        }
        if (className != null) {
            try {
                clazz = context.get(EZPlugins.class).forName(className);
            } catch (Throwable ex) {
                throw new ServiceLoadException("Can't load service class from " + className, ex);
            }
        }
    }
    // try to find service implementation class from plugins.
    if (clazz == null) {
        Map<String, Class<?>> si = context.getIfExists(Map.class, CONTEXT_SERVICE_IMPLEMENTERS);
        if (si != null) {
            logger.atInfo().kv(GreengrassService.SERVICE_NAME_KEY, name).log("Attempt to load service from plugins");
            clazz = si.get(name);
        }
    }
    GreengrassService ret;
    // If found class, try to load service class from plugins.
    if (clazz != null) {
        try {
            // Lookup the service topics here because the Topics passed into the GreengrassService
            // constructor must not be null
            Topics topics = config.lookupTopics(SERVICES_NAMESPACE_TOPIC, name);
            try {
                Constructor<?> ctor = clazz.getConstructor(Topics.class);
                ret = (GreengrassService) ctor.newInstance(topics);
            } catch (NoSuchMethodException e) {
                // If the basic constructor doesn't exist, then try injecting from the context
                ret = (GreengrassService) context.newInstance(clazz);
            }
            // Force plugins to be singletons
            if (clazz.getAnnotation(Singleton.class) != null || PluginService.class.isAssignableFrom(clazz)) {
                context.put(ret.getClass(), v);
            }
            if (clazz.getAnnotation(ImplementsService.class) != null) {
                topics.createLeafChild(VERSION_CONFIG_KEY).withNewerValue(0L, clazz.getAnnotation(ImplementsService.class).version());
            }
            logger.atDebug("service-loaded").kv(GreengrassService.SERVICE_NAME_KEY, ret.getName()).log();
            return ret;
        } catch (Throwable ex) {
            throw new ServiceLoadException("Can't create Greengrass Service instance " + clazz.getSimpleName(), ex);
        }
    }
    if (serviceRootTopics == null || serviceRootTopics.isEmpty()) {
        throw new ServiceLoadException("No matching definition in system model for: " + name);
    }
    // if not found, initialize GenericExternalService
    try {
        ret = new GenericExternalService(serviceRootTopics);
        logger.atDebug("generic-service-loaded").kv(GreengrassService.SERVICE_NAME_KEY, ret.getName()).log();
    } catch (Throwable ex) {
        throw new ServiceLoadException("Can't create generic service instance " + name, ex);
    }
    return ret;
}
Also used : Topics(com.aws.greengrass.config.Topics) DependencyType(com.amazon.aws.iot.greengrass.component.common.DependencyType) Collection(java.util.Collection) InputValidationException(com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException) ImplementsService(com.aws.greengrass.dependency.ImplementsService) Topic(com.aws.greengrass.config.Topic) ServiceLoadException(com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException)

Example 5 with InputValidationException

use of com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException in project aws-greengrass-nucleus by aws-greengrass.

the class KernelLifecycle method launch.

/**
 * Startup the Kernel and all services.
 */
public void launch() {
    logger.atInfo("system-start").kv("version", kernel.getContext().get(DeviceConfiguration.class).getNucleusVersion()).kv("rootPath", nucleusPaths.rootPath()).kv("configPath", nucleusPaths.configPath()).log("Launch Nucleus");
    // This guarantees that IPC, for example, is running before any user code
    for (Class<? extends Startable> c : startables) {
        kernel.getContext().get(c).startup();
    }
    final List<DeviceIdentityInterface> provisioningPlugins = findProvisioningPlugins();
    // Must be called before everything else so that these are available to be
    // referenced by main/dependencies of main
    // NOPMD
    final Queue<String> autostart = findBuiltInServicesAndPlugins();
    loadPlugins();
    // run the provisioning if device is not provisioned
    if (!kernel.getContext().get(DeviceConfiguration.class).isDeviceConfiguredToTalkToCloud() && !provisioningPlugins.isEmpty()) {
        // There is also no compelling use case right now for multiple provisioning plugins.
        if (provisioningPlugins.size() > 1) {
            String errorString = String.format(MULTIPLE_PROVISIONING_PLUGINS_FOUND_EXCEPTION, provisioningPlugins.toString());
            throw new RuntimeException(errorString);
        }
        executeProvisioningPlugin(provisioningPlugins.get(0));
    }
    mainService = kernel.locateIgnoreError(KernelCommandLine.MAIN_SERVICE_NAME);
    autostart.forEach(s -> {
        try {
            mainService.addOrUpdateDependency(kernel.locate(s), DependencyType.HARD, true);
        } catch (ServiceLoadException se) {
            logger.atError().log("Unable to load service {}", s, se);
        } catch (InputValidationException e) {
            logger.atError().log("Unable to add auto-starting dependency {} to main", s, e);
        }
    });
    kernel.writeEffectiveConfig();
    logger.atInfo().setEventType("system-start").addKeyValue("main", kernel.getMain()).log();
    startupAllServices();
}
Also used : DeviceIdentityInterface(com.aws.greengrass.provisioning.DeviceIdentityInterface) InputValidationException(com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException) Utils.deepToString(com.aws.greengrass.util.Utils.deepToString) DeviceConfiguration(com.aws.greengrass.deployment.DeviceConfiguration) ServiceLoadException(com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException)

Aggregations

InputValidationException (com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException)6 DependencyType (com.amazon.aws.iot.greengrass.component.common.DependencyType)3 Topic (com.aws.greengrass.config.Topic)2 ServiceLoadException (com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException)2 CaseInsensitiveString (com.aws.greengrass.config.CaseInsensitiveString)1 Node (com.aws.greengrass.config.Node)1 Subscriber (com.aws.greengrass.config.Subscriber)1 Topics (com.aws.greengrass.config.Topics)1 ImplementsService (com.aws.greengrass.dependency.ImplementsService)1 DeviceConfiguration (com.aws.greengrass.deployment.DeviceConfiguration)1 DeviceIdentityInterface (com.aws.greengrass.provisioning.DeviceIdentityInterface)1 Pair (com.aws.greengrass.util.Pair)1 Utils.deepToString (com.aws.greengrass.util.Utils.deepToString)1 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Matcher (java.util.regex.Matcher)1