diff --git a/build.gradle.kts b/build.gradle.kts index 005b823..6a5fa56 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ val spaceMavenRepositoryUrl: String by project val sonatypeUsername: String by project val sonatypePassword: String by project val sdkVersion: String by project +val junitVersion: String by project group = "com.jeliuc" version = System.getenv("SDK_VERSION") ?: sdkVersion @@ -33,11 +34,22 @@ repositories { mavenCentral() } +sourceSets { + create("integrationTest") { + kotlin.srcDir("src/integrationTest/kotlin") + resources.srcDir("src/integrationTest/resources") + + compileClasspath += sourceSets["main"].output + runtimeClasspath += output + compileClasspath + } +} + dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:5.11.4") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") testRuntimeOnly("org.junit.platform:junit-platform-launcher") testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("io.ktor:ktor-client-mock:$ktorVersion") + dokkaHtmlPlugin("org.jetbrains.dokka:versioning-plugin:2.0.0") implementation("io.ktor:ktor-client-core:$ktorVersion") @@ -45,6 +57,22 @@ dependencies { implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") implementation("org.jetbrains.kotlinx:kotlinx-datetime-jvm:$dateTimeVersion") + + add("integrationTestImplementation", kotlin("test")) + add("integrationTestImplementation", "org.junit.jupiter:junit-jupiter:5.10.0") + add("integrationTestRuntimeOnly", "org.junit.platform:junit-platform-launcher") +} + +configurations["integrationTestImplementation"].extendsFrom(configurations["testImplementation"]) +configurations["integrationTestRuntimeOnly"].extendsFrom(configurations["testRuntimeOnly"]) + +tasks.register("integrationTest") { + description = "Runs integration tests." + group = "verification" + testClassesDirs = sourceSets["integrationTest"].output.classesDirs + classpath = sourceSets["integrationTest"].runtimeClasspath + useJUnitPlatform() + shouldRunAfter(tasks.named("test")) } tasks.test { diff --git a/gradle.properties b/gradle.properties index c2b52db..af9a84e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,10 +2,11 @@ kotlin.code.style=official ktorVersion=3.0.3 dateTimeVersion=0.6.1 sdkVersion=0.3.0 +junitVersion=5.11.4 spaceUsername= spacePassword= spaceMavenRepositoryUrl= sonatypeUsername= sonatypePassword= org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled -org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true \ No newline at end of file +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true diff --git a/src/integrationTest/kotlin/DatabasesIntegrationTest.kt b/src/integrationTest/kotlin/DatabasesIntegrationTest.kt new file mode 100644 index 0000000..498d6d6 --- /dev/null +++ b/src/integrationTest/kotlin/DatabasesIntegrationTest.kt @@ -0,0 +1,174 @@ +package com.jeliuc.turso.sdk + +import com.jeliuc.turso.sdk.model.ConfigurationResponse +import com.jeliuc.turso.sdk.model.CreateDatabase +import com.jeliuc.turso.sdk.model.CreateDatabaseResponse +import com.jeliuc.turso.sdk.model.DatabaseUsageResponse +import com.jeliuc.turso.sdk.model.DeleteDatabaseResponse +import com.jeliuc.turso.sdk.model.InstanceResponse +import com.jeliuc.turso.sdk.model.ListDatabasesResponse +import com.jeliuc.turso.sdk.model.ListInstancesResponse +import com.jeliuc.turso.sdk.model.RetrieveDatabaseResponse +import com.jeliuc.turso.sdk.model.StatsResponse +import com.jeliuc.turso.sdk.model.UpdateConfigurationRequest +import com.jeliuc.turso.sdk.resource.databases +import io.ktor.client.engine.cio.CIO +import kotlinx.coroutines.runBlocking +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertIs +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class DatabasesIntegrationTest { + val token by lazy { + System.getenv("TURSO_TOKEN") + } + + val organization by lazy { + System.getenv("TURSO_ORGANIZATION") + } + + val group = "default" + + val newDatabaseName = "integration-test-db" + + /** + * Manipulate Databases suite + * + * * Creates new database + * * List databases and find in list newly created database + * * Retrieve database by name + * * Retrieve configuration + * * Update configuration + * * Retrieve usage + * * Stats + * * List instances + * * Retrieve instance + * * Delete database + * + */ + @Test + fun `can manipulate database`() { + val client = TursoClient.using(CIO.create(), token) + + val newDatabase = + CreateDatabase( + name = newDatabaseName, + group = group, + isSchema = false, + sizeLimit = "2M", + ) + + val createDatabaseResponse = + runBlocking { + client.databases.create( + organization, + newDatabase, + ) + } + + assertIs(createDatabaseResponse, "Not create database response") + + val listOfAvailableDatabases = + runBlocking { + client.databases.list(organization) + } + + assertIs(listOfAvailableDatabases, "Not list databases response") + assertNotNull(listOfAvailableDatabases.databases.firstOrNull { it.name == newDatabaseName }, "New database is not in the list") + + val retrievedResponse = + runBlocking { + client.databases.retrieve( + organization, + newDatabaseName, + ) + } + + assertIs(retrievedResponse, "Not retrieve database response") + assertEquals(newDatabaseName, retrievedResponse.database.name, "Incorrect db name retrieved") + + val configuration = + runBlocking { + client.databases.retrieveConfiguration(organization, newDatabaseName) + } + + assertIs(configuration, "Not a configuration response") + + val configurationUpdate = + UpdateConfigurationRequest( + blockReads = false, + blockWrites = false, + sizeLimit = "1M", + allowAttach = false, + ) + + val updateConfigurationResponse = + runBlocking { + client.databases.updateConfiguration(organization, newDatabaseName, configurationUpdate) + } + + assertIs(updateConfigurationResponse, "Not a configuration update response") + + val retrievedConfiguration = + runBlocking { + client.databases.retrieveConfiguration( + organization, + newDatabaseName, + ) + } + + assertIs(retrievedConfiguration, "No a configuration response") + + val retrievedUsage = + runBlocking { + client.databases.usage( + organization, + newDatabaseName, + ) + } + + assertIs(retrievedUsage, "Not a usage response") + + val statsResponse = + runBlocking { + client.databases.stats(organization, newDatabaseName) + } + + assertIs(statsResponse, "Not a stats response") + + val instances = + runBlocking { + client.databases.listInstances( + organization, + newDatabaseName, + ) + } + + assertIs(instances, "Can't deserialize list instances response") + assertTrue(instances.instances.size > 0, "Zero instances") + + val instanceName = instances.instances.first()!!.name + val retrievedInstance = + runBlocking { + client.databases.retrieveInstance( + organization, + newDatabaseName, + instanceName, + ) + } + + assertIs(retrievedInstance, "Not an instance response") + + val deleteResponse = + runBlocking { + client.databases.delete( + organization, + newDatabaseName, + ) + } + + assertIs(deleteResponse, "Not a delete response") + } +} diff --git a/src/main/kotlin/model/Database.kt b/src/main/kotlin/model/Database.kt index c4ff134..1f3f938 100644 --- a/src/main/kotlin/model/Database.kt +++ b/src/main/kotlin/model/Database.kt @@ -90,6 +90,8 @@ data class ConfigurationResponse( @Serializable data class UpdateConfigurationRequest( + @SerialName("block_reads") val blockReads: Boolean, + @SerialName("block_writes") val blockWrites: Boolean, @SerialName("size_limit") val sizeLimit: String, @SerialName("allow_attach") val allowAttach: Boolean, ) @@ -99,6 +101,7 @@ data class Usage( @SerialName("rows_read") val rowsRead: Long, @SerialName("rows_written") val rowsWritten: Long, @SerialName("storage_bytes") val storageBytes: Long, + @SerialName("bytes_synced") val bytesSynced: Long, ) @Serializable @@ -111,7 +114,7 @@ data class InstanceUsage( data class Instances( @SerialName("uuid") val uuid: String, @SerialName("instances") val instances: List, - @SerialName("total") val total: Usage, + @SerialName("usage") val usage: InstanceUsage, ) @Serializable @@ -125,7 +128,8 @@ data class Instance( @Serializable data class DatabaseUsageResponse( - @SerialName("database") val database: Instances, + // @SerialName("database") val database: Instances, + @SerialName("total") val total: Usage, ) @Serializable @@ -145,7 +149,7 @@ data class InstanceResponse( @Serializable data class StatsResponse( - @SerialName("top_queries") val topQueries: List, + @SerialName("top_queries") val topQueries: List? = null, ) @Serializable diff --git a/src/main/kotlin/model/Organization.kt b/src/main/kotlin/model/Organization.kt index 9d12dc3..f8f9155 100644 --- a/src/main/kotlin/model/Organization.kt +++ b/src/main/kotlin/model/Organization.kt @@ -100,7 +100,6 @@ data class OrganizationDatabaseUsage( data class DatabaseUsage( @SerialName("uuid") val uuid: String, @SerialName("instances") val instances: List, - @SerialName("total") val total: Usage, ) @Serializable @@ -109,9 +108,9 @@ data class OrganizationUsage( @SerialName("rows_written") val rowsWritten: Long, @SerialName("databases") val databases: Int, @SerialName("locations") val locations: Int, - @SerialName("storage") val storage: Long, @SerialName("groups") val groups: Int, @SerialName("bytes_synced") val bytesSynced: Long, + @SerialName("storage_bytes") val storage: Long, ) @Serializable diff --git a/src/test/kotlin/resource/DatabasesTest.kt b/src/test/kotlin/resource/DatabasesTest.kt index 9aff7aa..83b1c2e 100644 --- a/src/test/kotlin/resource/DatabasesTest.kt +++ b/src/test/kotlin/resource/DatabasesTest.kt @@ -230,7 +230,13 @@ class DatabasesTest { @Test fun `can update database configuration`() { runBlocking { - val configurationUpdate = UpdateConfigurationRequest(sizeLimit = "20M", allowAttach = true) + val configurationUpdate = + UpdateConfigurationRequest( + blockReads = true, + blockWrites = false, + sizeLimit = "20M", + allowAttach = true, + ) val configuration = client(mockEngine()).databases.updateConfiguration("test", "test-database", configurationUpdate) assertIs(configuration) } diff --git a/src/test/resources/fixtures/database/list.json b/src/test/resources/fixtures/database/list.json index cf88631..31072ed 100644 --- a/src/test/resources/fixtures/database/list.json +++ b/src/test/resources/fixtures/database/list.json @@ -59,26 +59,6 @@ "sleeping": false, "archived": false, "schema": null - }, - { - "Name": "some-org", - "DbId": "7984ca66-28b0-4244-8ba9-392e5c835fc6", - "Hostname": "some-org-a2xchip.turso.io", - "is_schema": false, - "block_reads": false, - "block_writes": false, - "allow_attach": false, - "regions": [ - "otp" - ], - "primaryRegion": "otp", - "type": "logical", - "hostname": "some-org-a2xchip.turso.io", - "version": "0.24.29", - "group": "default", - "sleeping": false, - "archived": false, - "schema": "3ffbf4dd-958d-4c87-b89d-3bf1499c7a94" } ] -} \ No newline at end of file +} diff --git a/src/test/resources/fixtures/database/usage.json b/src/test/resources/fixtures/database/usage.json index 18f4981..2199163 100644 --- a/src/test/resources/fixtures/database/usage.json +++ b/src/test/resources/fixtures/database/usage.json @@ -1,28 +1 @@ -{ - "database": { - "uuid": "0eb771dd-6906-11ee-8553-eaa7715aeaf2", - "instances": [ - { - "uuid": "cd831986-94e5-11ee-a6fe-7a52e1f7759a", - "usage": { - "rows_read": 0, - "rows_written": 0, - "storage_bytes": 4096 - } - }, - { - "uuid": "0be90471-6906-11ee-8553-eaa7715aeaf2", - "usage": { - "rows_read": 0, - "rows_written": 0, - "storage_bytes": 4096 - } - } - ], - "total": { - "rows_read": 0, - "rows_written": 0, - "storage_bytes": 8192 - } - } -} \ No newline at end of file +{"database":{"uuid":"4f0d8f65-e2e8-4ce8-8af5-6da211188b35","instances":[{"uuid":"9f182703-bfd7-11ee-897f-822b15a0bd8c","usage":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}}],"usage":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}},"instances":{"9f182703-bfd7-11ee-897f-822b15a0bd8c":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}},"total":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}} diff --git a/src/test/resources/fixtures/organization/usage.json b/src/test/resources/fixtures/organization/usage.json index 16f97ce..52076c7 100644 --- a/src/test/resources/fixtures/organization/usage.json +++ b/src/test/resources/fixtures/organization/usage.json @@ -1,42 +1,474 @@ { "organization": { - "uuid": "fa72ba58-7db3-436b-bcab-14b83eb1dd88", + "uuid": "5852473d-5d99-49bf-80d2-a6843a68c061", "usage": { - "rows_read": 1000000000, - "rows_written": 25000000, - "databases": 500, - "locations": 3, - "storage": 9000000000, - "groups": 1, - "bytes_synced": 3000000000 + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 49152, + "bytes_synced": 0, + "databases": 5, + "locations": 1, + "groups": 1 }, "databases": [ { - "uuid": "0eb771dd-6906-11ee-8553-eaa7715aeaf2", + "uuid": "3ffbf4dd-958d-4c87-b89d-3bf1499c7a94", "instances": [ { - "uuid": "cd831986-94e5-11ee-a6fe-7a52e1f7759a", + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", "usage": { "rows_read": 0, "rows_written": 0, - "storage_bytes": 4096 + "storage_bytes": 12288, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + { + "uuid": "66d389af-8fdb-11ee-81d8-dad4a36c3ccf", + "instances": [ + { + "uuid": "61329d5d-8fdb-11ee-81d8-dad4a36c3ccf", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 } }, { - "uuid": "0be90471-6906-11ee-8553-eaa7715aeaf2", + "uuid": "82a05b76-8fdc-11ee-81d8-dad4a36c3ccf", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "a2f1d1c8-bfd7-11ee-897f-822b15a0bd8c", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + { + "uuid": "ec97c157-5c8e-47ad-abe3-2b0af4079af8", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + { + "uuid": "f88629b3-caf3-44f7-9f6a-ea8719ad6a25", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "2c00f407-3c64-430d-af15-c16cb12589b1", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "464ac7ea-d4dd-11ee-aff8-920d20afefa2", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "4f0d8f65-e2e8-4ce8-8af5-6da211188b35", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + { + "uuid": "7984ca66-28b0-4244-8ba9-392e5c835fc6", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 16384, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 16384, + "bytes_synced": 0 + } + }, + { + "uuid": "8e78c7e0-c517-11ee-9386-e26d5524e301", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "abaf9c85-4d55-4cce-9ad0-ebc20c87776e", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + } + ], + "usage": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + { + "uuid": "fca3e897-6c5d-4975-9f29-e8bbf5f433f5", + "instances": [ + { + "uuid": "9f182703-bfd7-11ee-897f-822b15a0bd8c", "usage": { "rows_read": 0, "rows_written": 0, - "storage_bytes": 4096 + "storage_bytes": 4096, + "bytes_synced": 0 } } ], - "total": { + "usage": { "rows_read": 0, "rows_written": 0, - "storage_bytes": 8192 + "storage_bytes": 0, + "bytes_synced": 0 } } ] + }, + "databases": { + "2c00f407-3c64-430d-af15-c16cb12589b1": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "3ffbf4dd-958d-4c87-b89d-3bf1499c7a94": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + "464ac7ea-d4dd-11ee-aff8-920d20afefa2": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "4f0d8f65-e2e8-4ce8-8af5-6da211188b35": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "66d389af-8fdb-11ee-81d8-dad4a36c3ccf": { + "instances": { + "61329d5d-8fdb-11ee-81d8-dad4a36c3ccf": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + }, + "82a05b76-8fdc-11ee-81d8-dad4a36c3ccf": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "7984ca66-28b0-4244-8ba9-392e5c835fc6": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 16384, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 16384, + "bytes_synced": 0 + } + }, + "8e78c7e0-c517-11ee-9386-e26d5524e301": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "a2f1d1c8-bfd7-11ee-897f-822b15a0bd8c": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 12288, + "bytes_synced": 0 + } + }, + "abaf9c85-4d55-4cce-9ad0-ebc20c87776e": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "ec97c157-5c8e-47ad-abe3-2b0af4079af8": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "f88629b3-caf3-44f7-9f6a-ea8719ad6a25": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + }, + "fca3e897-6c5d-4975-9f29-e8bbf5f433f5": { + "instances": { + "9f182703-bfd7-11ee-897f-822b15a0bd8c": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 4096, + "bytes_synced": 0 + } + }, + "total": { + "rows_read": 0, + "rows_written": 0, + "storage_bytes": 0, + "bytes_synced": 0 + } + } + }, + "total": { + "rows_read": 9, + "rows_written": 0, + "storage_bytes": 49152, + "bytes_synced": 0, + "databases": 5, + "locations": 1, + "groups": 1 } -} \ No newline at end of file +}