Thursday, April 27, 2023

Deploy Microservice in Oracle Cloud Infrastructure

 

Deploy Microservice in Oracle Cloud Infrastructure

1.   Create a Compute Instance

First, you need to create a Compute Instance in Oracle Cloud Infrastructure. This is a virtual machine that will host your Spring Boot application.

To create a Compute Instance, follow these steps:

1.   Go to the Compute Instances page in the Oracle Cloud Infrastructure Console.

2.   Click Create Instance.

3.   In the Create Instance dialog, select the Operating System and Image for your Compute Instance.

4.   Click Create.

It will take a few minutes for your Compute Instance to be created.

2.   Install Java and Maven

Once your Compute Instance is created, you need to install Java and Maven. Java is the programming language that Spring Boot is written in, and Maven is a build tool that is used to build and deploy Spring Boot applications.

To install Java and Maven, follow these steps:

1.   SSH into your Compute Instance.

2.   Run the following command to install Java:

Code snippet

sudo apt-get install openjdk-11-jdk

 

3.   Run the following command to install Maven:

Code snippet

sudo apt-get install maven

 

3.   Create a Spring Boot Application

Now that you have Java and Maven installed, you can create a Spring Boot application.

To create a Spring Boot application, follow these steps:

1.   Create a new directory for your Spring Boot application.

2.   In the directory, run the following command to create a new Spring Boot project:

mvn archetype:generate -DgroupId=com.example -DartifactId=my-spring-boot-application -DarchetypeArtifactId=maven-archetype-quickstart

This will create a new Spring Boot project with the name my-spring-boot-application.

4.   Build and Deploy the Application

Once you have created a Spring Boot application, you can build and deploy it.

To build and deploy the application, follow these steps:

1.   In the directory of your Spring Boot application, run the following command to build the application:

mvn clean install

 



2.   Run the following command to deploy the application to Oracle Cloud Infrastructure:

cf push my-spring-boot-application

 

 

This will deploy your Spring Boot application to Oracle Cloud Infrastructure.

5.   Access the Application

Once your Spring Boot application is deployed, you can access it by going to the following URL:

https://my-spring-boot-application.[region].oci.oraclecloud.com

 

 

For example, if your application is deployed in the us-central1 region, the URL would be:

https://my-spring-boot-application.us-central1.oci.oraclecloud.com

 

 

You can now access your Spring Boot application in the Oracle Cloud Infrastructure Console.

 

Friday, April 21, 2023

Title: How to Deploy Kubernetes with Helm Charts

 

Title: How to Deploy Kubernetes with Helm Charts

Introduction:

Kubernetes is a powerful container orchestration platform that can be used to deploy

and manage containerized applications. Helm is a package manager for Kubernetes

that makes it easy to deploy and manage Helm charts, which are packages that contain

all the Kubernetes resources needed to deploy an application.

In this blog post, we will show you how to deploy Kubernetes with Helm charts.

We will start by creating a Helm chart for a simple application, and then we will deploy

the application to Kubernetes.

Prerequisites:

· Kubernetes cluster

· Helm

Creating a Helm Chart:

To create a Helm chart, we will use the following command:

helm create my-app

This will create a new directory called my-app that contains the Helm chart for

our application.

The my-app directory contains the following files:

· Chart.yaml: This file contains metadata about the Helm chart, 

· such as the name, version, and description.

· values.yaml: This file contains default values for the Helm chart's parameters.

· templates: This directory contains the Kubernetes resources that will be

· deployed when the Helm chart is installed.

 

Deploying the Helm Chart:

To deploy the Helm chart, we will use the following command:

helm install my-app

This will deploy the Helm chart to Kubernetes.

Once the Helm chart has been deployed, you can verify that the application

is running by using the following command:

kubectl get pods

This command will list all the pods that are running in your Kubernetes cluster.

Conclusion:

In this blog post, we showed you how to deploy Kubernetes with Helm charts.

We started by creating a Helm chart for a simple application, and then

we deployed the application to Kubernetes.

Monday, April 3, 2023

Data refresh in Quick Sight

 Amazon QuickSight does not have a direct mechanism to be notified when underlying data sources (such as an S3 file, RDS database, or Redshift table) are refreshed. However, the recommended approach is to use an AWS Lambda function or an AWS Step Functions workflow in combination with the QuickSight API to trigger dataset refreshes programmatically.

Suggested Approach:

  1. Use QuickSight API to Trigger a Dataset Refresh: After your data is updated (e.g., when an ETL job completes or an S3 file is updated), invoke the QuickSight API to refresh the dataset. This can be done via the AWS SDK or using an AWS Lambda function.

  2. Event-Driven Automation with CloudWatch or Lambda: You can automate the refresh process using AWS CloudWatch Events, Amazon S3 Events, or database triggers to detect data changes and initiate a refresh using the QuickSight API.

  3. QuickSight Refresh Programmatically: To programmatically notify QuickSight, you can use the UpdateDataSet API or CreateIngestion API to refresh the datasets.

Implementation Options:

1. CreateIngestion API to Refresh Dataset:

This approach will trigger a new ingestion (data load) in QuickSight. You can automate this API call using AWS Lambda, Step Functions, or another AWS service.


More details can be found here 

Python Example:

python
import boto3 import datetime # Replace with your actual AWS Region and Dataset ID AWS_REGION = 'us-east-1' DATASET_ID = 'your-dataset-id' AWS_ACCOUNT_ID = 'your-account-id' QUICKSIGHT_ROLE_NAME = 'quicksight' # Initialize QuickSight client quicksight_client = boto3.client('quicksight', region_name=AWS_REGION) def refresh_quicksight_dataset(): response = quicksight_client.create_ingestion( DataSetId=DATASET_ID, IngestionId='Ingestion_' + datetime.datetime.now().strftime("%Y%m%d%H%M%S"), AwsAccountId=AWS_ACCOUNT_ID ) print(f"Ingestion Response: {response}") return response # Call the function to trigger ingestion refresh_quicksight_dataset()

This function triggers a dataset refresh for the specified dataset ID. You can automate the execution of this script using Lambda functions or scheduled events.

2. Automation using AWS Lambda:

If the data refresh is triggered by another event (e.g., S3 file update, Glue job completion, or RDS data change), you can use a Lambda function with an S3 event or a CloudWatch Event Rule to call the create_ingestion API.

Example Lambda Function Configuration:

  • Trigger: Set up S3 Event Notification (PUT) or a CloudWatch Event Rule (for Glue job completion).
  • Action: Call the create_ingestion API to refresh the QuickSight dataset.

3. Event-Driven Approach using Step Functions:

For complex workflows (e.g., multiple datasets need to be refreshed sequentially), you can use AWS Step Functions to define a state machine that:

  1. Triggers data ingestion using the QuickSight API.
  2. Checks for the status of the ingestion.
  3. Updates dashboards once ingestion is complete.

Monitoring and Notifications:

  • Use CloudWatch Alarms to monitor the status of the ingestions and send notifications if ingestion fails.
  • Automate retry mechanisms using Lambda or Step Functions.

Key Considerations:

  • Dataset IDs: Ensure that you have the dataset ID and account ID.
  • Permissions: The AWS Identity needs appropriate permissions (quicksight:CreateIngestion, quicksight:UpdateDataSetPermissions, etc.) to manage dataset ingestion.
  • Ingestion Limits: Each dataset can have only one active ingestion at a time, so coordinate to avoid conflicts.

By combining these approaches, you can effectively notify and trigger QuickSight to reflect changes in your underlying data, ensuring that your visualizations remain up-to-date.

Let me know if you'd like to see this setup in more detail or need guidance for a specific use case!

Wednesday, March 1, 2023

Call a Stored Procedure from a Oracle Package in SpringBoot Application

 

To create a Spring Boot application that calls an Oracle stored procedure `STORED_PRC_NAME` in a package `PACKAGE_NAME`, follow these steps:

 

1. Set Up Your Spring Boot Project: Use Spring Initializr or your IDE to create a new Spring Boot project with the necessary dependencies.

 

 Step 1: Create the Project

 

1. Initialize a Spring Boot project: Include the following dependencies:

   - Spring Web

   - Spring Data JPA

   - Oracle JDBC

   - Spring Boot Starter JDBC

 

2. Project Structure: Ensure your project has the following structure:

 

   src/main/java/com/example/oracleprocedure

   ├── OracleProcedureApplication.java

   ├── config

   │   └── DataSourceConfig.java

   ├── repository

   │   └── OracleRepository.java

   └── service

       └── OracleService.java

 

 

 Step 2: Configure Oracle DataSource

 

Create a configuration class `DataSourceConfig.java` to set up the Oracle DataSource.

 

JAVA CODE:

package com.example.oracleprocedure.config;

 

import oracle.jdbc.pool.OracleDataSource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

 

import javax.sql.DataSource;

import java.sql.SQLException;

 

@Configuration

public class DataSourceConfig {

 

    @Bean

    public DataSource dataSource() throws SQLException {

        OracleDataSource dataSource = new OracleDataSource();

        dataSource.setURL("jdbc:oracle:thin:@//your_db_url:1521/your_service_name");

        dataSource.setUser("your_username");

        dataSource.setPassword("your_password");

        return dataSource;

    }

 

    @Bean

    public JdbcTemplate jdbcTemplate(DataSource dataSource) {

        return new JdbcTemplate(dataSource);

    }

 

    @Bean

    public DataSourceTransactionManager transactionManager(DataSource dataSource) {

        return new DataSourceTransactionManager(dataSource);

    }

}

```

 

 Step 3: Create a Repository to Call the Stored Procedure

 

Create a repository class `OracleRepository.java` to handle the stored procedure call.

 

JAVA CODE:

package com.example.oracleprocedure.repository;

 

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.stereotype.Repository;

 

import javax.annotation.PostConstruct;

import javax.sql.DataSource;

import java.sql.Types;

import org.springframework.jdbc.core.SqlOutParameter;

import org.springframework.jdbc.core.SqlParameter;

import org.springframework.jdbc.core.simple.SimpleJdbcCall;

 

@Repository

public class OracleRepository {

 

    private final JdbcTemplate jdbcTemplate;

    private SimpleJdbcCall simpleJdbcCall;

 

    public OracleRepository(JdbcTemplate jdbcTemplate) {

        this.jdbcTemplate = jdbcTemplate;

    }

 

    @PostConstruct

    public void init() {

        simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)

            .withCatalogName("PACKAGE_NAME") // Package name

            .withProcedureName("STORED_PRC_NAME")    // Procedure name

            .declareParameters(

                new SqlParameter("input_param1", Types.VARCHAR),

                new SqlParameter("input_param2", Types.INTEGER),

                new SqlOutParameter("output_param", Types.VARCHAR)

            );

    }

 

    public String callStoredProcedure(String param1, int param2) {

        Map<String, Object> inParams = new HashMap<>();

        inParams.put("input_param1", param1);

        inParams.put("input_param2", param2);

 

        Map<String, Object> outParams = simpleJdbcCall.execute(inParams);

        return (String) outParams.get("output_param");

    }

}

```

 

 Step 4: Create a Service to Use the Repository

 

Create a service class `OracleService.java` to use the repository.

 

JAVA CODE:

package com.example.oracleprocedure.service;

 

import com.example.oracleprocedure.repository.OracleRepository;

import org.springframework.stereotype.Service;

 

@Service

public class OracleService {

 

    private final OracleRepository oracleRepository;

 

    public OracleService(OracleRepository oracleRepository) {

        this.oracleRepository = oracleRepository;

    }

 

    public String callStoredProcedure(String param1, int param2) {

        return oracleRepository.callStoredProcedure(param1, param2);

    }

}

 

 

 Step 5: Main Application Class

 

Create the main application class `OracleProcedureApplication.java`.

 

JAVA CODE:

package com.example.oracleprocedure;

 

import com.example.oracleprocedure.service.OracleService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.CommandLineRunner;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class OracleProcedureApplication implements CommandLineRunner {

 

    @Autowired

    private OracleService oracleService;

 

    public static void main(String[] args) {

        SpringApplication.run(OracleProcedureApplication.class, args);

    }

 

    @Override

    public void run(String... args) throws Exception {

        String result = oracleService.callStoredProcedure("testParam1", 123);

        System.out.println("Stored Procedure Output: " + result);

    }

}

 

 

 Step 6: Add Dependencies in `pom.xml`

 

Here is the complete `pom.xml` for the project:

 

XML Code

<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

 

    <groupId>com.example</groupId>

    <artifactId>oracleprocedure</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <packaging>jar</packaging>

 

    <name>oracle-procedure</name>

    <description>Spring Boot project to call an Oracle stored procedure</description>

 

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>3.0.0</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

 

    <properties>

        <java.version>17</java.version>

    </properties>

 

    <dependencies>

        <!-- Spring Boot Starter Web -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

 

        <!-- Spring Boot Starter Data JPA -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-data-jpa</artifactId>

        </dependency>

 

        <!-- Spring Boot Starter JDBC -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-jdbc</artifactId>

        </dependency>

 

        <!-- Oracle JDBC -->

        <dependency>

            <groupId>com.oracle.database.jdbc</groupId>

            <artifactId>ojdbc8</artifactId>

            <version>19.8.0.0</version>

        </dependency>

 

        <!-- Spring Boot Starter Test -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>

 

    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

 

</project>

```

 

 Step 7: Run Your Application

 

Run your Spring Boot application. It should call the Oracle stored procedure `STORED_PRC_NAME` and print the result.

 

Make sure your Oracle database is properly set up and accessible from your application. Also, adjust the stored procedure call parameters according to your actual stored procedure's input and output parameters.

Thursday, November 24, 2022

Oracle JDeveloper 4K Display (3840×2160) Resolution Problem on Windows 10

 There were a lot of issues observed when running JDeveloper 12c in high resolution on Windows 10


The issues include:

  • JDeveloper Buttons, Icons, Menu are illegible
  • Fonts are too small

Issues observed in environment:

  • Windows 10 (x64)
  • Java 1.7.080
  • JDeveloper 12c (12.1.3/12.2.2.4)
  • Screen Resolution: 3840×2160 (4K)
Solution

  •  Create a shortcut for JDeveloper on desktop then right click on it; Select “Properties” and go to “Compability” tab, find “Change high DPI settings” button at bottom and click on it. 
  • Check the option “Override high DPI scaling behavior. Scaling performed by: System”. Finally click OK, click Apply!  
 



Saturday, July 16, 2022

SpringBoot API to return compressed CSV file

Here's an example of a Spring Boot Controller that accepts a request payload of type EmployeeRequest, generates a CSV file based on the input data, compresses the file into a ZIP, and returns the zipped file as a response:

 



Spring Boot Controller

java

import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @RestController @RequestMapping("/api/employee") public class EmployeeController { @PostMapping("/generate") public ResponseEntity<StreamingResponseBody> generateZippedCsv(@RequestBody EmployeeRequest request) { StreamingResponseBody responseBody = outputStream -> { // Create CSV in memory ByteArrayOutputStream csvOutputStream = new ByteArrayOutputStream(); try (CSVPrinter csvPrinter = new CSVPrinter(new PrintWriter(csvOutputStream), CSVFormat.DEFAULT)) { // Add CSV Headers csvPrinter.printRecord("First Name", "Last Name", "Middle Name", "Date of Birth"); // Populate CSV rows with request data for (Employee employee : request.getEmployees()) { csvPrinter.printRecord( employee.getFirstName(), employee.getLastName(), employee.getMiddleName(), employee.getDateOfBirth() ); } } // Create ZIP containing the CSV try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) { zipOutputStream.putNextEntry(new ZipEntry("employees.csv")); zipOutputStream.write(csvOutputStream.toByteArray()); zipOutputStream.closeEntry(); } }; // Set headers for ZIP file download HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"employees.zip\""); return ResponseEntity.ok() .headers(headers) .body(responseBody); } }

Supporting Classes

EmployeeRequest

This class represents the input request payload that contains a list of employees.

java

import java.util.List; public class EmployeeRequest { private List<Employee> employees; // Getters and Setters public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } }

Employee

This class represents the individual employee data.

java

public class Employee { private String firstName; private String lastName; private String middleName; private String dateOfBirth; // Use String for simplicity; can use LocalDate or Date instead // Getters and Setters public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getDateOfBirth() { return dateOfBirth; } public void setDateOfBirth(String dateOfBirth) { this.dateOfBirth = dateOfBirth; } } 
 

How It Works

  1. Input: The API receives a JSON payload containing a list of employees with their details (firstName, lastName, middleName, and dateOfBirth).
  2. CSV Generation: It generates a CSV file with these details in memory.
  3. ZIP Compression: The CSV file is compressed into a ZIP archive.
  4. Response: The ZIP file is returned to the client with appropriate headers for file download.

  



Example Request

POST Request

http

POST /api/employee/generate Content-Type: application/json

Request Body

json

{ "employees": [ { "firstName": "John", "lastName": "Doe", "middleName": "A.", "dateOfBirth": "1985-03-15" }, { "firstName": "Jane", "lastName": "Smith", "middleName": "B.", "dateOfBirth": "1990-07-21" } ] }

Response

The API returns a employees.zip file containing the CSV file. The CSV will look like this:

csv

First Name,Last Name,Middle Name,Date of Birth John,Doe,A.,1985-03-15 Jane,Smith,B.,1990-07-21

 

1. Spring Boot Configuration Limits

Spring Boot uses Servlet multipart handling for file uploads and responses. The maximum file size is governed by the spring.servlet.multipart properties:

  • spring.servlet.multipart.max-file-size:

    • Limits the maximum size of a single uploaded file or generated response.
    • Default: 1MB.
  • spring.servlet.multipart.max-request-size:

    • Limits the total size of all files in a multipart request or response.
    • Default: 10MB.

Example Configuration in application.properties:

properties

spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB

2. Server-Specific Limits

Your server configuration (e.g., Tomcat, Jetty) also enforces limits:

Tomcat:

  • server.tomcat.max-swallow-size: Specifies the maximum size of a request body or response.
    • Default: 2MB.
    • Set -1 for no limit.

Example:

properties

server.tomcat.max-swallow-size=-1

Other Servers:

  • Jetty, Undertow, or other embedded servers might have similar settings for request/response size limits. Check their documentation for details.

3. JVM Memory Limits

Your application must have enough memory to handle large files, especially for:

  • In-Memory Operations: When files are stored or manipulated in memory (e.g., CSV generation or zipping).
  • Heap Space: Ensure your JVM has adequate heap memory to avoid OutOfMemoryError.

JVM Options:

bash

-Xms512M -Xmx2G

This example sets the JVM to use 512MB initial memory and 2GB maximum memory.


4. Operating System Limits

The underlying operating system may impose limits on:

  • Temporary File Storage: For file uploads or in-memory buffers, check /tmp (or equivalent) storage space.
  • Maximum Open File Handles: Ensure you are not exceeding the file descriptor limits, particularly in high-concurrency scenarios.

5. Practical Limits for Download Responses

For downloading files (like a CSV zipped file):

  • StreamingResponseBody: Use it to stream large files directly to the response output stream, avoiding in-memory buffering.
  • This approach minimizes memory usage, allowing responses to exceed typical memory constraints.

6. Network Bandwidth

Large file downloads are also affected by:

  • Network bandwidth between the server and the client.
  • Timeouts due to prolonged transfers.

Ensure:

  • Timeouts are configured appropriately (server.connection-timeout in Spring Boot).
  • Clients can handle large file downloads.

Summary

  • Default Spring Boot limits are 1MB per file and 10MB per request.
  • You can increase these limits using properties like spring.servlet.multipart.max-file-size.
  • Use StreamingResponseBody for large file downloads to avoid memory bottlenecks.
  • Monitor JVM memory, server configurations, and OS limits to ensure performance and reliability.

If you are working with extremely large files (e.g., several GB), consider a more robust solution like:

  • Direct S3 File Downloads: Upload the file to AWS S3 and share a pre-signed URL.
  • Chunked File Downloads: Break the file into smaller chunks for transmission.

Monday, December 6, 2021

Creating an Aurora Database Instance with AWS CDK (Python) and Secret Manager

 Title: Creating an Aurora Database Instance with AWS CDK (Python) and Secret Manager


Introduction:

In this blog post, we will walk through the process of creating an Amazon Aurora database instance using AWS Cloud Development Kit (CDK) with Python. Additionally, we'll enhance the security of our application by utilizing AWS Secrets Manager to manage and retrieve our database credentials.


Prerequisites:

Before we begin, make sure you have the following prerequisites:


1. AWS CDK installed: [CDK Installation Guide](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html)

2. Python installed: [Python Installation Guide](https://www.python.org/downloads/)


Step 1: Set Up Your CDK Project

Create a new directory for your CDK project and navigate to it in your terminal.


mkdir aurora-cdk

cd aurora-cdk



Initialize your CDK project.


cdk init app --language python



Step 2: Install Required CDK Libraries

Install the necessary CDK libraries for Amazon Aurora and Secrets Manager.



pip install aws-cdk.aws-rds aws-cdk.aws-secretsmanager



Step 3: Import Dependencies in Your CDK App

Open the `app.py` file in your favorite code editor and import the required CDK modules.


from aws_cdk import (

    core,

    aws_rds as rds,

    aws_secretsmanager as secretsmanager

)



 Step 4: Define the CDK Stack

Define your CDK stack by creating a class that inherits from `core.Stack`. Inside the class, define the Aurora database instance and the Secrets Manager secret.


class AuroraCdkStack(core.Stack):


    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:

        super().__init__(scope, id, **kwargs)


        # Create a Secrets Manager secret for database credentials

        secret = secretsmanager.Secret(

            self,

            "AuroraSecret",

            secret_name="AuroraCredentials",

            generate_secret_string=secretsmanager.SecretStringGenerator(

                secret_string_template='{"username": "admin"}',

                generate_string_key="password",

                exclude_characters='"@/',

            )

        )


        # Create an Aurora database instance

        aurora_db = rds.DatabaseInstance(

            self,

            "AuroraDB",

            engine=rds.DatabaseInstanceEngine.aurora_postgres,

            master_username=secret.secret_value_from_json("username").to_string(),

            master_password=secret.secret_value_from_json("password").to_string(),

            instance_class=core.Fn.select(0, ["db.t3.small"]),

            vpc_subnets={"subnet_type": core.SubnetType.PRIVATE},

            removal_policy=core.RemovalPolicy.DESTROY  # WARNING: Do not use in production

        )


Step 5: Deploy Your CDK Stack

Deploy your CDK stack to create the Aurora database instance.



cdk deploy


### Conclusion:

Congratulations! You have successfully created an Amazon Aurora database instance using AWS CDK with Python. By integrating AWS Secrets Manager, you've enhanced the security of your application by securely managing and retrieving your database credentials.


Remember to manage your secrets and credentials responsibly, and never expose sensitive information in your code or configuration files.

How IdP Groups Are Tied to Databricks Groups (Unity Catalog)

  🔗 How IdP Groups Are Tied to Databricks Groups (Unity Catalog) 🔑 Key Principle (Read This First) Databricks does NOT “map” IdP groups...