org.apache.aurora.scheduler.configuration.executor.ExecutorSettingsLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.aurora.scheduler.configuration.executor.ExecutorSettingsLoader.java

Source

/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.aurora.scheduler.configuration.executor;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.hubspot.jackson.datatype.protobuf.ProtobufModule;

import org.apache.aurora.GuavaUtils;
import org.apache.mesos.v1.Protos.ExecutorID;
import org.apache.mesos.v1.Protos.ExecutorInfo;
import org.apache.mesos.v1.Protos.Volume;

import static com.fasterxml.jackson.databind.PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES;

/**
 * A utility class to read JSON-formatted executor configurations.
 */
public final class ExecutorSettingsLoader {
    public static final ExecutorID PLACEHOLDER_EXECUTOR_ID = ExecutorID.newBuilder().setValue("PLACEHOLDER")
            .build();

    private ExecutorSettingsLoader() {
        // Utility class
    }

    /**
     * Thrown when an executor configuration could not be read.
     */
    public static class ExecutorConfigException extends Exception {
        public ExecutorConfigException(Throwable cause) {
            super(cause);
        }
    }

    /**
     * Reads an executor configuration from a JSON-encoded source.
     *
     * @param input The configuration data source.
     * @return A map of executor configurations.
     * @throws ExecutorConfigException If the input cannot be read or is not properly formatted.
     */
    public static Map<String, ExecutorConfig> read(Readable input) throws ExecutorConfigException {
        String configContents;
        try {
            configContents = CharStreams.toString(input);
        } catch (IOException e) {
            throw new ExecutorConfigException(e);
        }

        ObjectMapper mapper = new ObjectMapper().registerModule(new ProtobufModule())
                .setPropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
        List<Schema> parsed;
        try {
            parsed = mapper.readValue(configContents, new TypeReference<List<Schema>>() {
            });
        } catch (IOException e) {
            throw new ExecutorConfigException(e);
        }

        Map<String, ExecutorConfig> customExecutors;
        try {
            // We apply a placeholder value for the executor ID so that we can construct and validate
            // the protobuf schema.  This allows us to catch many validation errors here rather than
            // later on when launching tasks.
            customExecutors = parsed.stream()
                    .collect(GuavaUtils.toImmutableMap(m -> m.executor.getName(),
                            m -> new ExecutorConfig(m.executor.setExecutorId(PLACEHOLDER_EXECUTOR_ID).build(),
                                    Optional.fromNullable(m.volumeMounts).or(ImmutableList.of()), m.taskPrefix)));

        } catch (RuntimeException e) {
            throw new ExecutorConfigException(e);
        }

        return customExecutors;
    }

    /**
     * The JSON schema.  This is separated from the public {@link ExecutorConfig} so we can read
     * objects that do not have all fields required by the protobuf set in the JSON config.
     */
    private static class Schema {
        private ExecutorInfo.Builder executor;
        private List<Volume> volumeMounts;
        private String taskPrefix;

        ExecutorInfo.Builder getExecutor() {
            return executor;
        }

        void setExecutor(ExecutorInfo.Builder executor) {
            this.executor = executor;
        }

        List<Volume> getVolumeMounts() {
            return volumeMounts;
        }

        void setVolumeMounts(List<Volume> volumeMounts) {
            this.volumeMounts = volumeMounts;
        }

        String getTaskPrefix() {
            return taskPrefix;
        }

        void setTaskPrefix(String taskPrefix) {
            this.taskPrefix = taskPrefix;
        }
    }
}