如何解决TypeScript CDK创建ElastiCache用户组时的用户未找到错误?
问题
在AWS中使用Redis引擎,主作用域外有一系列函数,部署CDK时部分代码未生效,主作用域内已添加cache.node.addDependency(userGroup);确保调用外部代码。
变量userGroup指向要创建用户的Elasticache.CfnUserGroup,相关代码如下:
fetchCacheUserGroup() { const ElasticacheUser = this.createCacheUser(); return new elasticache.CfnUserGroup(this, 'CacheUserGroup', { engine: 'redis', userGroupId: 'foo', userIds: [ ElasticacheUser ], }); }
由于userId字段仅接受字符串值,创建了返回用户名(redis-user)的字符串类型函数,同时用该函数创建elasticache.CfnUser:
createCacheUser(): string { let username = 'redis-user'; const secret = new secretsmanager.Secret(this, 'foobar', { secretName: '/x/x/x/x/x', generateSecretString: { secretStringTemplate: JSON.stringify({ username, password: 'xxx', }), generateStringKey: 'password', excludeCharacters: ' ^%+~`#$&*()|[]{}:;<>?!\'/"\\', }, }); new elasticache.CfnUser(this, 'UserElasticache', { accessString: 'access-string', engine: 'redis', noPasswordRequired: false, passwords: [ secret.secretValueFromJson('password').toString(), ], userId: username, userName: username, }); return username };
部署CDK时出现错误「User redis-user not found」导致终止,明明已经创建了elasticache.CfnUser并返回了字符串,不知道问题出在哪,该如何修复?
解决方案
问题核心是CloudFormation资源的依赖关系没有正确建立,直接使用硬编码字符串传递userId,CDK无法自动处理资源创建顺序,导致UserGroup可能在User创建完成前就开始部署。
修改
createCacheUser返回CfnUser实例而非字符串
不要直接返回用户名,而是返回创建的elasticache.CfnUser对象,让CDK能自动跟踪资源间的依赖:createCacheUser(): elasticache.CfnUser { const username = 'redis-user'; const secret = new secretsmanager.Secret(this, 'foobar', { secretName: '/x/x/x/x/x', generateSecretString: { secretStringTemplate: JSON.stringify({ username, password: 'xxx' }), generateStringKey: 'password', excludeCharacters: ' ^%+~`#$&*()|[]{}:;<>?!\'/"\\', }, }); return new elasticache.CfnUser(this, 'UserElasticache', { accessString: 'access-string', engine: 'redis', noPasswordRequired: false, passwords: [secret.secretValueFromJson('password').toString()], userId: username, userName: username, }); }在
fetchCacheUserGroup中引用CfnUser的属性
从返回的CfnUser实例中获取userId,CDK会自动为UserGroup添加对User的依赖,保证创建顺序:fetchCacheUserGroup() { const elasticacheUser = this.createCacheUser(); return new elasticache.CfnUserGroup(this, 'CacheUserGroup', { engine: 'redis', userGroupId: 'foo', userIds: [elasticacheUser.attrUserId], }); }移除手动添加的冗余依赖
因为CDK已经通过资源引用自动建立了依赖,cache.node.addDependency(userGroup);这行可以删除,避免依赖关系混乱。
原理:直接传递硬编码字符串时,CDK无法识别UserGroup需要依赖User资源,CloudFormation可能并行创建两个资源,导致UserGroup创建时User还未存在,从而抛出错误。返回CfnUser实例并引用其属性,CDK会自动生成正确的CloudFormation依赖关系,确保User先创建完成。
内容的提问来源于stack exchange,提问作者DevBob

