All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.finovertech.vertx.config.aws.ssm.AwsSsmConfigStore Maven / Gradle / Ivy

package com.finovertech.vertx.config.aws.ssm;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClient;
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClientBuilder;
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathRequest;
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathResult;

import io.vertx.config.spi.ConfigStore;
import io.vertx.config.spi.utils.JsonObjectHelper;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;

/**
 * An implementation of {@link ConfigStore} for AWS SSM Parameter Store.
 * (https://aws.amazon.com/ec2/systems-manager/parameter-store/)
 */
public class AwsSsmConfigStore implements ConfigStore {

    private final String path;
    private final boolean decrypt;
    private final boolean recursive;
    private final Vertx vertx;
    private final AWSSimpleSystemsManagementClient ssmClient;

    /**
     * creates an instance of {@link AwsSsmConfigStore}.
     *
     * @param vertx
     *            the vert.x instance
     * @param config
     *            the configuration, used for creating the SSM client and requests.
     */
    public AwsSsmConfigStore(final Vertx vertx, final JsonObject config) {
        this.vertx = vertx;
        this.path = Objects.requireNonNull(config.getString("path"), "The path must be set.");
        this.decrypt = config.getBoolean("decrypt", true);
        this.recursive = config.getBoolean("recursive", true);
        ssmClient = (AWSSimpleSystemsManagementClient) AWSSimpleSystemsManagementClientBuilder.defaultClient();
    }

    @Override
    public void get(final Handler> completionHandler) {
        getParameters() // Retrieve the data from AWS
            .compose(this::toBuffer) // Change to a Buffer
            .setHandler(completionHandler); // Done
    }

    private Future getParameters() {
        final Future result = Future.future();
        vertx.executeBlocking(
            future -> {
                try {
                    final Map map = getParamsFromAwsAsMap();
                    future.complete(new JsonObject(map));
                } catch (final Throwable thr) {
                    future.fail(thr);
                }
            },
            result.completer());
        return result;
    }

    private Map getParamsFromAwsAsMap() {
        final Map returnMap = new HashMap();

        GetParametersByPathResult response = makeAwsRequest(null);
        addParamsToMap(returnMap, response);
        String nextToken = response.getNextToken();

        // call the AWS API until there is no longer a nextToken.
        while (nextToken != null) {
            response = makeAwsRequest(nextToken);
            addParamsToMap(returnMap, response);
            nextToken = response.getNextToken();
        }
        return returnMap;
    }

    private void addParamsToMap(final Map returnMap, final GetParametersByPathResult response) {
        response.getParameters()
            .forEach(p -> returnMap.put(p.getName(), p.getValue()));
    }

    private GetParametersByPathResult makeAwsRequest(final String nextToken) {
        GetParametersByPathRequest request = new GetParametersByPathRequest()
            .withPath(path)
            .withWithDecryption(decrypt)
            .withRecursive(recursive);
        if (nextToken != null) {
            request = request.withNextToken(nextToken);
        }
        return ssmClient.getParametersByPath(request);
    }

    private Future toBuffer(final JsonObject json) {
        final Future future = Future.future();

        if (json == null) {
            future.complete(Buffer.buffer());
        } else {
            future.complete(JsonObjectHelper.toBuffer(json));
        }

        return future;
    }

    @Override
    public void close(final Handler completionHandler) {
        ssmClient.shutdown();
        completionHandler.handle(null);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy