public Object handleRequest()

in resources/custom-resources/rds-bootstrap/src/main/java/com/amazon/aws/partners/saasfactory/saasboost/RdsBootstrap.java [77:209]


    public Object handleRequest(Map<String, Object> event, Context context) {
        try {
            LOGGER.info(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(event));
        } catch (JsonProcessingException e) {
            LOGGER.error("Could not log input");
        }

        final String requestType = (String) event.get("RequestType");
        final Map<String, Object> resourceProperties = (Map<String, Object>) event.get("ResourceProperties");
        final String host = (String) resourceProperties.get("Host");
        final String port = (String) resourceProperties.get("Port");
        final String database = (String) resourceProperties.get("Database");
        final String username = (String) resourceProperties.get("User");
        final String passwordParam = (String) resourceProperties.get("Password");
        final String bootstrapFileBucket = (String) resourceProperties.get("BootstrapFileBucket");
        final String bootstrapFileKey = (String) resourceProperties.get("BootstrapFileKey");
        final String driverClassName = driverClassNameFromPort(port);
        final String type = typeFromPort(port);
        final boolean createAndBootstrap = (bootstrapFileBucket != null && !bootstrapFileBucket.isBlank()
                && bootstrapFileKey != null && !bootstrapFileKey.isBlank());

        ExecutorService service = Executors.newSingleThreadExecutor();
        ObjectNode responseData = JsonNodeFactory.instance.objectNode();
        try {
            Runnable r = () -> {
                if ("Create".equalsIgnoreCase(requestType)) {
                    LOGGER.info("CREATE");

                    LOGGER.info("Getting database password secret from Parameter Store");
                    String password = null;
                    try {
                        password = ssm.getParameter(request -> request.withDecryption(true).name(passwordParam)).parameter().value();
                    } catch (SdkServiceException ssmError) {
                        LOGGER.error("ssm:GetParameter error", ssmError.getMessage());
                        throw ssmError;
                    }
                    if (password == null) {
                        throw new RuntimeException("Password is null");
                    }

                    // We need a connection that doesn't specify the database name since we may be creating it right now
                    String dbCheck = null;

                    // Unlike MySQL/MariaDB, you have to specify a database name to get a connection to postgres...
                    // And you should connect to dbo.master in SQL Server to check for a database
                    if (type.equals("postgresql")) {
                        dbCheck = "template1";
                    } else if (type.equals("sqlserver")) {
                        dbCheck = "master";
                    }

                    // Create the database if it doesn't exist - this is helpful
                    // for SQL Server because RDS/CloudFormation won't create a
                    // database when you bring up an instance.
                    LOGGER.info("Checking if database {} exists", database);
                    try (Connection dbCheckConn = DriverManager.getConnection(jdbcUrl(type, driverClassName, host, port, dbCheck), username, password)) {
                        String engine = dbCheckConn.getMetaData().getDatabaseProductName().toLowerCase();
                        if (!databaseExists(dbCheckConn, engine, database)) {
                            createdb(dbCheckConn, engine, database);
                        } else {
                            LOGGER.info("Database {} exists", database);
                        }
                    } catch (SQLException e) {
                        LOGGER.error("Can't connect to database host", e.getMessage());
                        throw new RuntimeException(e);
                    }

                    if (createAndBootstrap) {
                        LOGGER.info("Getting SQL file from S3 s3://{}/{}", bootstrapFileBucket, bootstrapFileKey);
                        InputStream bootstrapSQL = null;
                        try {
                            ResponseBytes<GetObjectResponse> responseBytes = s3.getObjectAsBytes(request -> request
                                    .bucket(bootstrapFileBucket)
                                    .key(bootstrapFileKey)
                            );
                            bootstrapSQL = responseBytes.asInputStream();
                        } catch (SdkServiceException s3Error) {
                            LOGGER.error("s3:GetObject error", s3Error.getMessage());
                            throw s3Error;
                        }
                        // We have a database. Execute the SQL commands in the bootstrap file stored in S3.
                        LOGGER.info("Executing bootstrap SQL");
                        try (Connection conn = DriverManager.getConnection(jdbcUrl(type, driverClassName, host, port, database), username, password);
                             Statement sql = conn.createStatement()) {
                            conn.setAutoCommit(false);
                            Scanner sqlScanner = new Scanner(bootstrapSQL, "UTF-8");
                            sqlScanner.useDelimiter(";");
                            int batch = 0;
                            while (sqlScanner.hasNext()) {
                                String ddl = sqlScanner.next().trim();
                                if (!ddl.isEmpty()) {
                                    //LOGGER.info(String.format("%02d %s", ++batch, ddl));
                                    sql.addBatch(ddl);
                                }
                            }
                            sql.executeBatch();
                            conn.commit();

                            LOGGER.info("Finished initializing database");
                            sendResponse(event, context, "SUCCESS", responseData);
                        } catch (SQLException e) {
                            LOGGER.error("Error executing bootstrap SQL", e.getMessage());
                            throw new RuntimeException(e);
                        }
                    } else {
                        // We were just creating a database and there isn't a SQL file to execute
                        sendResponse(event, context, "SUCCESS", responseData);
                    }
                } else if ("Update".equalsIgnoreCase(requestType)) {
                    LOGGER.info("UPDATE");
                    sendResponse(event, context, "SUCCESS", responseData);
                } else if ("Delete".equalsIgnoreCase(requestType)) {
                    LOGGER.info("DELETE");
                    sendResponse(event, context, "SUCCESS", responseData);
                } else {
                    LOGGER.error("FAILED unknown requestType " + requestType);
                    responseData.put("Reason", "Unknown RequestType " + requestType);
                    sendResponse(event, context, "FAILED", responseData);
                }
            };
            Future<?> f = service.submit(r);
            f.get(context.getRemainingTimeInMillis() - 1000, TimeUnit.MILLISECONDS);
        } catch (final TimeoutException | InterruptedException | ExecutionException e) {
            // Timed out
            LOGGER.error("FAILED unexpected error or request timed out " + e.getMessage());
            LOGGER.error(getFullStackTrace(e));
            responseData.put("Reason", e.getMessage());
            sendResponse(event, context, "FAILED", responseData);
        } finally {
            service.shutdown();
        }
        return null;
    }