![](/img/trans.png)
[英]Permission denied in getting spanner session create in a java spring boot project using spanner emulator
[英]How to provide credentials for Spanner integration tests with Spring Boot, R2DBC and TestContainers (Spanner Emulator)
这是执行集成测试的错误:
com.google.cloud.spanner.SpannerException:
UNAUTHENTICATED: com.google.api.gax.rpc.UnauthenticatedException: io.grpc.StatusRuntimeException:
UNAUTHENTICATED: Request is missing required authentication credential.
Expected OAuth 2 access token, login cookie or other valid authentication credential.
See https://developers.google.com/identity/sign-in/web/devconsole-project.
代码(为了更容易和更快的复制而简化):
@ExtendWith(SpringExtension.class)
@SpringBootTest
@ActiveProfiles("it")
@DirtiesContext
public class SpannerIT {
static final String PROJECT_ID = "emulator-config";
static final String INSTANCE_ID = "test-instance";
static final String DATABASE_NAME = "test-database";
static SpannerEmulatorContainer spannerContainer;
@Autowired
private R2dbcEntityTemplate template;
@DynamicPropertySource
static void properties(DynamicPropertyRegistry r) {
r.add("spring.cloud.gcp.spanner.emulator-host", spannerContainer::getEmulatorGrpcEndpoint);
r.add("spring.r2dbc.url", () -> "r2dbc:cloudspanner://" + spannerContainer.getEmulatorHttpEndpoint() +
"/projects/" + PROJECT_ID + "/instances/" + INSTANCE_ID + "/databases/" + DATABASE_NAME);
}
@BeforeAll
public static void beforeAll() {
spannerContainer = new SpannerEmulatorContainer(
DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator").withTag("1.4.1"));
spannerContainer.start();
}
@AfterAll
public static void afterAll() {
spannerContainer.stop();
}
@Test
void test() {
StepVerifier.create(
template.select(Query.query(CriteriaDefinition.empty()), SomeClazz.class)
)
.verifyComplete();
}
@Data
@Table("test")
public class SomeClazz {
@Column("column")
private String column;
}
}
和配置(application-it.yml):
spring:
cloud:
gcp:
spanner:
project-id: emulator-config
r2dbc:
url: overwritten_in_tests
properties:
usePlainText: true
autoConfigEmulator: true
通过将usePlainText
设置为 r2dbc URL 理论上我们应该绕过凭据问题。 凭据提供程序已正确配置为NoCredentials
( SpannerConnectionFactoryProvider#extractCredentials
)。
Github repo 完整代码:
https://github.com/magiccrafter/spanner-spring-boot-r2jdbc-app
您收到的错误实际上是在暗示您的凭据选项正在运行,但有些东西正在尝试在没有凭据的情况下连接到 Cloud Spanner(或其他一些云产品)。 模拟器通常不会返回Unauthenticated
错误,因为它不需要任何凭据。 你能检查一下:
NoCredentials
访问其他一些云产品。感谢elefeint的提示:
您还必须设置环境变量 export SPANNER_EMULATOR_HOST=localhost:9010,以便 Spanner 客户端库选择非生产主机,类似于 jdbc 驱动程序。
Upvote #200 允许以编程方式自定义模拟器。
有关详细信息,请查看Github 问题 #200
这是我想出的解决方法,可以在集成测试运行之前绕过对 SPANNER_EMULATOR_HOST 环境变量的要求:
@Testcontainers
@ExtendWith(SystemStubsExtension.class)
@ExtendWith(SpringExtension.class)
@SpringBootTest
@ActiveProfiles("it")
@DirtiesContext
public class SpannerIT {
static final String PROJECT_ID = "nv-local";
static final String INSTANCE_ID = "test-instance";
static final String DATABASE_NAME = "trades";
@Container
private static final SpannerEmulatorContainer spannerContainer =
new SpannerEmulatorContainer(
DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator").withTag("1.4.1"));
@SystemStub
private static EnvironmentVariables environmentVariables;
@Autowired
ConnectionFactory connectionFactory;
@DynamicPropertySource
static void properties(DynamicPropertyRegistry r) {
environmentVariables.set("SPANNER_EMULATOR_HOST", spannerContainer.getEmulatorGrpcEndpoint());
r.add("spring.r2dbc.url", () -> "r2dbc:cloudspanner://" +
"/projects/" + PROJECT_ID + "/instances/" + INSTANCE_ID + "/databases/" + DATABASE_NAME);
}
这样,我们就可以在 Testcontainers 中拥有 Spanner 模拟器,而无需单独启动 Spanner 模拟器并映射具体端口。 完整的源代码可以在这里找到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.