DynamoDB and TableNameOverride with prefix

前端 未结 3 1620
[愿得一人]
[愿得一人] 2021-02-20 01:54

I am testing DynamoDB tables and want to set up different table names for prod and dev environment using the prefix \"dev_\" for development.

I made this test to print t

相关标签:
3条回答
  • 2021-02-20 02:34

    I've faced the same situation and struggled with myself a couple of days to get that working.

    Just in case you're using DynamoDB + Spring here is what worked for me:

    POJO class:

    @DynamoDBTable(tableName = "APP-ACCESSKEY")
    public class AccessKey {
        @NotBlank
        @Size(min = 1, max = 36)
        private String accessToken;
    
        @NotNull
        @Size(min = 3, max = 15)
        private String userName;
    
        private Date dateInsertion;
    
    
        public AccessKey() {
    
        // ... All POJO stuff
    }
    

    Spring configuration:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
        <!-- Amazon Credentials -->
        <bean id="tableNameOverride" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
            <property name="staticMethod" value="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix"/>
            <property name="arguments" value="DES-" />
        </bean>
    
        <bean id="dynamoDBMapperConfig" class="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig">
            <constructor-arg index="0" ref="tableNameOverride" />
        </bean>
    
        <bean id="BasicAWSCredentials" class="com.amazonaws.auth.BasicAWSCredentials">
             <constructor-arg index="0" value="${amazon.accessKey}" />
             <constructor-arg index="1" value="${amazon.secretKey}" />
        </bean>
    
        <bean id="amazonDynamoDBClient" class="com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient">
            <constructor-arg index="0" ref="BasicAWSCredentials" />
            <property name="endpoint" value="http://dynamodb.us-west-2.amazonaws.com" />
        </bean>
    
        <bean id="dynamoDBMapper" class="com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper">
            <constructor-arg index="0" ref="amazonDynamoDBClient" />
            <constructor-arg index="1" ref="dynamoDBMapperConfig" />
        </bean>
    
    </beans>
    

    Explanation:

    Taking into account that my AccessKey object point to APP-ACCESSKEY table on AWS DynamodDB then it turns out that after running this, your application will start to point to DES-APP-ACCESSKEY.

    Hope it helps someone who's facing a situation akin to it

    Cheers

    0 讨论(0)
  • 2021-02-20 02:46

    Same as Paolo Almeidas solution, just with Spring-Boot annotations. Just wanted to share it and maybe save someone time:

    I have dynamodb tables for each namespace, e.g. myApp-dev-UserTable, myApp-prod-UserTable and I am using the EKS_NAMESPACE env variable, which in my case gets injected into the pods by kubernetes.

    import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
    import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
    import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
    
    @Configuration
    @EnableDynamoDBRepositories(basePackages = "de.dynamodb")
    public class DynamoDBConfig {
    
        @Value("${EKS_NAMESPACE}")
        String eksNamespace;
    
        @Bean
        public AmazonDynamoDB amazonDynamoDB() {
            return AmazonDynamoDBClientBuilder.standard()
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(
                        "dynamodb.eu-central-1.amazonaws.com", "eu-central-1"))
                .withCredentials(awsCredentials())
                .build();
        }
    
        @Bean
        public AWSCredentialsProvider awsCredentials() {
            return WebIdentityTokenCredentialsProvider.builder().build();
        }
    
        // Table Name override:
    
        @Bean
        public DynamoDBMapperConfig.TableNameOverride tableNameOverride() {
            return DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix("myApp-" + eksNamespace + "-");
        }
    
        @Bean
        public DynamoDBMapperConfig dynamoDBMapperConfig() {
            return DynamoDBMapperConfig.builder().withTableNameOverride(tableNameOverride()).build();
        }
    
        @Bean
        // Marked as primary bean to override default bean.
        @Primary
        public DynamoDBMapper dynamoDBMapper() {
            return new DynamoDBMapper(amazonDynamoDB(), dynamoDBMapperConfig());
        }
    }
    

    With a table like this:

    @Data
    @DynamoDBTable(tableName = "UserTable")
    public class User {
    
            @DynamoDBHashKey
            private String userId;
    
            @DynamoDBAttribute
            private String foo;
    
            @DynamoDBAttribute
            private String bar;
    }
    
    0 讨论(0)
  • 2021-02-20 02:56

    withTableNamePrefix is a static method. So this line is creating a new instance of TableNameOverride with the String "test", and then throwing that instance away by using it to call the static withTableNamePrefix method:

    TableNameOverride tbl = new TableNameOverride("test").withTableNamePrefix("dev_");
    

    To answer the deeper question of separating test from prod, I would recommend having 2 separate AWS Accounts entirely, one for dev and one for prod. This is the only way you can:

    • See billing separately
    • Ensure you never leak data between prod and test systems
    • Have high scaling on a dev table prevent you from scaling a prod table higher
    0 讨论(0)
提交回复
热议问题