Search in sources :

Example 11 with ConfigStoreException

use of com.mesosphere.sdk.state.ConfigStoreException in project dcos-commons by mesosphere.

the class ConfigQueries method getConfiguration.

/**
 * Produces the content of the provided configuration ID, or returns an error if that ID doesn't
 * exist or the data couldn't be read.
 */
public static <T extends Configuration> Response getConfiguration(ConfigStore<T> configStore, String configurationId) {
    LOGGER.info("Attempting to fetch config with id '{}'", configurationId);
    UUID uuid;
    try {
        uuid = UUID.fromString(configurationId);
    } catch (Exception ex) {
        LOGGER.warn(String.format("Failed to parse requested configuration id '%s' as a UUID", configurationId), ex);
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
    try {
        return fetchConfig(configStore, uuid);
    } catch (ConfigStoreException ex) {
        if (ex.getReason() == Reason.NOT_FOUND) {
            LOGGER.warn(String.format("Requested configuration '%s' doesn't exist", configurationId), ex);
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        LOGGER.error(String.format("Failed to fetch requested configuration with id '%s'", configurationId), ex);
        return Response.serverError().build();
    }
}
Also used : ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException) UUID(java.util.UUID) ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException)

Example 12 with ConfigStoreException

use of com.mesosphere.sdk.state.ConfigStoreException in project dcos-commons by mesosphere.

the class TaskUtilsTest method buildPodLayout.

private static ConfigStore<ServiceSpec> buildPodLayout(int essentialTasks, int nonessentialTasks) {
    DefaultPodSpec.Builder podBuilder = DefaultPodSpec.newBuilder("executor-uri").type("server").count(3);
    for (int i = 0; i < essentialTasks; ++i) {
        podBuilder.addTask(buildTaskTemplate(String.format("essential%d", i)).goalState(GoalState.RUNNING).build());
    }
    for (int i = 0; i < nonessentialTasks; ++i) {
        podBuilder.addTask(buildTaskTemplate(String.format("nonessential%d", i)).goalState(GoalState.RUNNING).essential(false).build());
    }
    // should be ignored for recovery purposes:
    podBuilder.addTask(buildTaskTemplate("once").goalState(GoalState.ONCE).build());
    ServiceSpec serviceSpec = DefaultServiceSpec.newBuilder().name("svc").addPod(podBuilder.build()).build();
    ConfigStore<ServiceSpec> configStore = new ConfigStore<>(DefaultServiceSpec.getConfigurationFactory(serviceSpec), new MemPersister());
    try {
        configStore.setTargetConfig(configStore.store(serviceSpec));
    } catch (ConfigStoreException e) {
        throw new IllegalStateException(e);
    }
    return configStore;
}
Also used : ConfigStore(com.mesosphere.sdk.state.ConfigStore) MemPersister(com.mesosphere.sdk.storage.MemPersister) ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException)

Example 13 with ConfigStoreException

use of com.mesosphere.sdk.state.ConfigStoreException in project dcos-commons by mesosphere.

the class TaskUtilsTest method buildTask.

private static Protos.TaskInfo buildTask(ConfigStore<ServiceSpec> configStore, int index, String task) {
    Protos.TaskInfo.Builder taskBuilder = Protos.TaskInfo.newBuilder().setTaskId(TestConstants.TASK_ID).setSlaveId(TestConstants.AGENT_ID).setName(String.format("server-%d-%s", index, task));
    UUID id;
    try {
        id = configStore.getTargetConfig();
    } catch (ConfigStoreException e) {
        throw new IllegalStateException(e);
    }
    taskBuilder.setLabels(new TaskLabelWriter(taskBuilder).setIndex(index).setType("server").setTargetConfiguration(id).toProto());
    return taskBuilder.build();
}
Also used : ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException) TaskLabelWriter(com.mesosphere.sdk.offer.taskdata.TaskLabelWriter) UUID(java.util.UUID)

Example 14 with ConfigStoreException

use of com.mesosphere.sdk.state.ConfigStoreException in project dcos-commons by mesosphere.

the class DefaultConfigurationUpdater method cleanupDuplicateAndUnusedConfigs.

/**
 * Searches for any task configurations which are already identical to the target configuration
 * and updates the embedded config version label in those tasks to point to the current target
 * configuration.
 */
private void cleanupDuplicateAndUnusedConfigs(ServiceSpec targetConfig, UUID targetConfigId) throws ConfigStoreException {
    List<Protos.TaskInfo> taskInfosToUpdate = new ArrayList<>();
    Set<UUID> neededConfigs = new HashSet<>();
    neededConfigs.add(targetConfigId);
    // Search task labels for configs which need to be cleaned up.
    for (Protos.TaskInfo taskInfo : stateStore.fetchTasks()) {
        final UUID taskConfigId;
        try {
            taskConfigId = new TaskLabelReader(taskInfo).getTargetConfiguration();
        } catch (TaskException e) {
            LOGGER.warn(String.format("Unable to extract configuration ID from task %s: %s", taskInfo.getName(), TextFormat.shortDebugString(taskInfo)), e);
            continue;
        }
        if (taskConfigId.equals(targetConfigId)) {
            LOGGER.info("Task {} configuration ID matches target: {}", taskInfo.getName(), taskConfigId);
        } else {
            try {
                final ServiceSpec taskConfig = configStore.fetch(taskConfigId);
                if (!needsConfigUpdate(taskInfo, targetConfig, taskConfig)) {
                    // Task is effectively already on the target config. Update task's config ID to match target,
                    // and allow the duplicate config to be dropped from configStore.
                    TaskInfo.Builder taskBuilder = taskInfo.toBuilder();
                    taskBuilder.setLabels(new TaskLabelWriter(taskInfo).setTargetConfiguration(targetConfigId).toProto());
                    taskInfosToUpdate.add(taskBuilder.build());
                } else {
                    // Config isn't the same as the target. Refrain from updating task, mark config as 'needed'.
                    neededConfigs.add(taskConfigId);
                }
            } catch (Exception e) {
                LOGGER.error(String.format("Failed to fetch configuration %s for task %s", taskConfigId, taskInfo.getName()), e);
                // Cannot read this task's config. Do not delete the config.
                neededConfigs.add(taskConfigId);
            }
        }
    }
    if (!taskInfosToUpdate.isEmpty()) {
        LOGGER.info("Updating {} tasks in StateStore with target configuration ID {}", taskInfosToUpdate.size(), targetConfigId);
        stateStore.storeTasks(taskInfosToUpdate);
    }
    Collection<UUID> configIds = configStore.list();
    LOGGER.info("Testing deserialization of {} listed configurations before cleanup:", configIds.size());
    for (UUID configId : configIds) {
        try {
            configStore.fetch(configId);
            LOGGER.info("- {}: OK", configId);
        } catch (Exception e) {
            LOGGER.info("- {}: FAILED, leaving as-is: {}", configId, e.getMessage());
            neededConfigs.add(configId);
        }
    }
    clearConfigsNotListed(neededConfigs);
}
Also used : TaskLabelReader(com.mesosphere.sdk.offer.taskdata.TaskLabelReader) DefaultServiceSpec(com.mesosphere.sdk.specification.DefaultServiceSpec) ServiceSpec(com.mesosphere.sdk.specification.ServiceSpec) TaskInfo(org.apache.mesos.Protos.TaskInfo) TaskException(com.mesosphere.sdk.offer.TaskException) ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException) TaskInfo(org.apache.mesos.Protos.TaskInfo) TaskException(com.mesosphere.sdk.offer.TaskException) Protos(org.apache.mesos.Protos) TaskLabelWriter(com.mesosphere.sdk.offer.taskdata.TaskLabelWriter)

Example 15 with ConfigStoreException

use of com.mesosphere.sdk.state.ConfigStoreException in project dcos-commons by mesosphere.

the class DefaultConfigurationUpdater method updateConfiguration.

@Override
public UpdateResult updateConfiguration(ServiceSpec candidateConfig) throws ConfigStoreException {
    // Get the currently stored target configuration
    UUID targetConfigId;
    try {
        targetConfigId = configStore.getTargetConfig();
    } catch (ConfigStoreException e) {
        LOGGER.debug("No target configuration ID was set. First launch?");
        targetConfigId = null;
    }
    Optional<ServiceSpec> targetConfig;
    if (targetConfigId != null) {
        LOGGER.info("Loading current target configuration: {}", targetConfigId);
        targetConfig = Optional.of(configStore.fetch(targetConfigId));
    } else {
        targetConfig = Optional.empty();
    }
    // Log the config state (with diff of changes vs prior state) before proceeding with checks.
    final List<ConfigValidationError> errors = new ArrayList<>();
    String candidateConfigJson = null;
    try {
        candidateConfigJson = candidateConfig.toJsonString();
        LOGGER.info("New prospective config:\n{}", candidateConfigJson);
    } catch (Exception e) {
        LOGGER.error(String.format("Unable to get JSON representation of new prospective config object: %s", candidateConfig), e);
        errors.add(ConfigValidationError.valueError("NewConfigAsJson", "jsonString", String.format("Unable to serialize new config to JSON for logging: %s", e.getMessage())));
    }
    if (!targetConfig.isPresent()) {
        LOGGER.info("Skipping config diff: There is no old config target to diff against");
    } else if (candidateConfigJson == null) {
        LOGGER.error("Skipping config diff: New target couldn't be represented as JSON");
    } else {
        LOGGER.info("Prior target config:\n{}", targetConfig.get().toJsonString());
        printConfigDiff(targetConfig.get(), targetConfigId, candidateConfigJson);
    }
    targetConfig = fixServiceSpecUser(targetConfig);
    // whether it's considered equal by the ConfigComparator.
    for (ConfigValidator<ServiceSpec> validator : validators) {
        errors.addAll(validator.validate(targetConfig, candidateConfig));
    }
    // there are validation errors against the new config, we continue using the prior target.
    if (!errors.isEmpty()) {
        StringJoiner sj = new StringJoiner("\n");
        int i = 1;
        for (ConfigValidationError error : errors) {
            sj.add(String.format("%d: %s", i++, error.toString()));
        }
        LOGGER.warn("New configuration failed validation against current target " + "configuration {}, with {} errors across {} validators:\n{}", targetConfigId, errors.size(), validators.size(), sj.toString());
        if (!targetConfig.isPresent()) {
            throw new ConfigStoreException(Reason.LOGIC_ERROR, String.format("Configuration failed validation without any prior target configuration" + "available for fallback. Initial launch with invalid configuration? " + "%d Errors: %s", errors.size(), sj.toString()));
        }
    } else if (!targetConfig.isPresent() || !configComparator.equals(targetConfig.get(), candidateConfig)) {
        UUID oldTargetId = targetConfigId;
        targetConfigId = configStore.store(candidateConfig);
        LOGGER.info("Updating target configuration: " + "Prior target configuration '{}' is different from new configuration '{}'. ", oldTargetId, targetConfigId);
        targetConfig = Optional.of(candidateConfig);
        configStore.setTargetConfig(targetConfigId);
    } else {
        LOGGER.info("No changes detected between current target configuration '{}' and new configuration. " + "Leaving current configuration as the target.", targetConfigId);
    }
    // Update config IDs on tasks whose config contents match the current target, then clean up
    // leftover configs which are not the target and which are not referenced by any tasks.
    cleanupDuplicateAndUnusedConfigs(targetConfig.get(), targetConfigId);
    return new ConfigurationUpdater.UpdateResult(targetConfigId, errors);
}
Also used : ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException) DefaultServiceSpec(com.mesosphere.sdk.specification.DefaultServiceSpec) ServiceSpec(com.mesosphere.sdk.specification.ServiceSpec) TaskException(com.mesosphere.sdk.offer.TaskException) ConfigStoreException(com.mesosphere.sdk.state.ConfigStoreException) ConfigValidationError(com.mesosphere.sdk.config.validate.ConfigValidationError)

Aggregations

ConfigStoreException (com.mesosphere.sdk.state.ConfigStoreException)22 Test (org.junit.Test)11 Response (javax.ws.rs.core.Response)9 UUID (java.util.UUID)5 ServiceSpec (com.mesosphere.sdk.specification.ServiceSpec)3 RawServiceSpec (com.mesosphere.sdk.specification.yaml.RawServiceSpec)3 TaskException (com.mesosphere.sdk.offer.TaskException)2 TaskLabelReader (com.mesosphere.sdk.offer.taskdata.TaskLabelReader)2 TaskLabelWriter (com.mesosphere.sdk.offer.taskdata.TaskLabelWriter)2 DefaultServiceSpec (com.mesosphere.sdk.specification.DefaultServiceSpec)2 RawPlan (com.mesosphere.sdk.specification.yaml.RawPlan)2 ConfigStore (com.mesosphere.sdk.state.ConfigStore)2 JsonParseException (com.fasterxml.jackson.core.JsonParseException)1 ConfigurationUpdater (com.mesosphere.sdk.config.ConfigurationUpdater)1 DefaultConfigurationUpdater (com.mesosphere.sdk.config.DefaultConfigurationUpdater)1 ConfigValidationError (com.mesosphere.sdk.config.validate.ConfigValidationError)1 ConfigValidator (com.mesosphere.sdk.config.validate.ConfigValidator)1 AndRule (com.mesosphere.sdk.offer.evaluate.placement.AndRule)1 IsLocalRegionRule (com.mesosphere.sdk.offer.evaluate.placement.IsLocalRegionRule)1 PlacementRule (com.mesosphere.sdk.offer.evaluate.placement.PlacementRule)1