SQL Azure and SQL Server database integration tests (#115)

* Integration test are parameterised (extends IntegrationTest) to run against a remote database with 4 db scripts run @BeforeClass, @Before, @After and @AfterClass.
* SQL script for SQL Azure and SQL Server databases and templates of JDBC configuration.
This commit is contained in:
szymonsztuka
2017-12-01 17:17:51 +00:00
committed by GitHub
parent d81e4809bb
commit 709b3791a3
50 changed files with 606 additions and 105 deletions

View File

@ -19,6 +19,7 @@ sourceSets {
}
resources {
srcDir file('src/integration-test/resources')
srcDir file('../testing/test-utils/src/main/resources')
}
}
}

View File

@ -6,13 +6,11 @@ import net.corda.core.internal.list
import net.corda.core.internal.readLines
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.NodeStartup
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_REGULATOR
import net.corda.testing.*
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
import net.corda.testing.IntegrationTest
import net.corda.testing.node.NotarySpec
import org.assertj.core.api.Assertions.assertThat
import org.junit.ClassRule
import org.junit.Test
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
@ -32,6 +30,10 @@ class DriverTests : IntegrationTest() {
// Check that the port is bound
addressMustNotBeBound(executorService, hostAndPort)
}
@ClassRule @JvmField
val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_NOTARY, DUMMY_REGULATOR)
.map { it.toDatabaseSchemaName() }.toTypedArray())
}
@Test

View File

@ -20,6 +20,7 @@ import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.SignedTransaction
import net.corda.node.VersionInfo
import net.corda.node.internal.StateLoaderImpl
import net.corda.node.internal.configureDatabase
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.services.api.SchemaService
import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage
@ -34,11 +35,17 @@ import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.transactions.InMemoryTransactionVerifierService
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.internal.configureDatabase
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel
import net.corda.testing.*
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_CLASSNAME
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_PASSWORD
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_URL
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_USER
import net.corda.testing.database.DatabaseConstants.SCHEMA
import net.corda.testing.database.DatabaseConstants.TRANSACTION_ISOLATION_LEVEL
import org.bouncycastle.operator.ContentSigner
import rx.Observable
import rx.subjects.PublishSubject
@ -66,22 +73,37 @@ open class MockServices(
@JvmStatic
val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")
private fun readDatabaseConfig(nodeName: String? = null, postifx: String? = null): Config {
val standarizedNodeName = if (nodeName!= null) nodeName.replace(" ", "").replace("-", "_") else null
//in case of H2, the same db instance runs for all integration tests, so adding additional variable postfix to use unique db user/schema each time
val h2InstanceName = if (postifx != null) standarizedNodeName + "_" + postifx else standarizedNodeName
private fun readDatabaseConfig(nodeName: String? = null, postfix: String? = null): Config {
val parseOptions = ConfigParseOptions.defaults()
//read overrides from command line (passed by Gradle as system properties)
val dataSourceKeys = listOf(DATA_SOURCE_URL, DATA_SOURCE_CLASSNAME, DATA_SOURCE_USER, DATA_SOURCE_PASSWORD)
val dataSourceSystemProperties = Properties()
val allSystemProperties = System.getProperties().toList().map { it.first.toString() to it.second.toString() }.toMap()
dataSourceKeys.filter { allSystemProperties.containsKey(it) }.forEach { dataSourceSystemProperties.setProperty(it, allSystemProperties[it]) }
val systemConfigOverride = ConfigFactory.parseProperties(dataSourceSystemProperties, parseOptions)
//read from db vendor specific configuration file
val databaseConfig = ConfigFactory.parseResources(System.getProperty("databaseProvider") + ".conf", parseOptions.setAllowMissing(true))
val fixedOverride = ConfigFactory.parseString("baseDirectory = \"\"")
val nodeOrganizationNameConfig = if (standarizedNodeName != null) configOf("nodeOrganizationName" to standarizedNodeName) else ConfigFactory.empty()
//implied property nodeOrganizationName to fill the potential placeholders in db schema/ db user properties
val standardizedNodeName = if (nodeName!= null) nodeName.replace(" ", "").replace("-", "_") else null
val nodeOrganizationNameConfig = if (standardizedNodeName != null) configOf("nodeOrganizationName" to standardizedNodeName) else ConfigFactory.empty()
//defaults to H2
//for H2 the same db instance runs for all integration tests, so adding additional variable postfix to use unique db user/schema each time
val h2InstanceName = if (postfix != null) standardizedNodeName + "_" + postfix else standardizedNodeName
val defaultProps = Properties()
defaultProps.setProperty("dataSourceProperties.dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
defaultProps.setProperty("dataSourceProperties.dataSource.url", "jdbc:h2:mem:${h2InstanceName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE")
defaultProps.setProperty("dataSourceProperties.dataSource.user", "sa")
defaultProps.setProperty("dataSourceProperties.dataSource.password", "")
defaultProps.setProperty(DATA_SOURCE_CLASSNAME, "org.h2.jdbcx.JdbcDataSource")
defaultProps.setProperty(DATA_SOURCE_URL, "jdbc:h2:mem:${h2InstanceName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE")
defaultProps.setProperty(DATA_SOURCE_USER, "sa")
defaultProps.setProperty(DATA_SOURCE_PASSWORD, "")
val defaultConfig = ConfigFactory.parseProperties(defaultProps, parseOptions)
return databaseConfig.withFallback(fixedOverride)
return systemConfigOverride.withFallback(databaseConfig)
.withFallback(fixedOverride)
.withFallback(nodeOrganizationNameConfig)
.withFallback(defaultConfig)
.resolve()
@ -112,7 +134,10 @@ open class MockServices(
@JvmStatic
fun makeTestDatabaseProperties(nodeName: String? = null): DatabaseConfig {
val config = readDatabaseConfig(nodeName)
return DatabaseConfig(schema = if (config.hasPath("database.schema")) config.getString("database.schema") else "")
val transactionIsolationLevel = if (config.hasPath(TRANSACTION_ISOLATION_LEVEL)) TransactionIsolationLevel.valueOf(config.getString(TRANSACTION_ISOLATION_LEVEL))
else TransactionIsolationLevel.READ_COMMITTED
val schema = if (config.hasPath(SCHEMA)) config.getString(SCHEMA) else ""
return DatabaseConfig(transactionIsolationLevel = transactionIsolationLevel, schema = schema)
}
private fun makeTestIdentityService() = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DEV_TRUST_ROOT)
@ -144,9 +169,9 @@ open class MockServices(
cordappPackages: List<String> = emptyList(),
initialIdentityName: CordaX500Name): Pair<CordaPersistence, MockServices> {
val cordappLoader = CordappLoader.createWithTestPackages(cordappPackages)
val dataSourceProps = makeTestDataSourceProperties()
val dataSourceProps = makeTestDataSourceProperties(initialIdentityName.organisation)
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), identityService, schemaService)
val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(initialIdentityName.organisation), identityService, schemaService)
val mockService = database.transaction {
object : MockServices(cordappLoader, initialIdentityName = initialIdentityName, keys = *(keys.toTypedArray())) {
override val identityService get() = identityService

View File

@ -1,10 +1,12 @@
package net.corda.testing
import net.corda.core.identity.Party
import net.corda.testing.database.DbScriptRunner.runDbScript
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import org.junit.BeforeClass
import org.junit.rules.ExternalResource
/**
* Base class for all integration tests that require common setup and/or teardown.
@ -12,6 +14,8 @@ import org.junit.BeforeClass
*/
abstract class IntegrationTest {
open protected val databaseSchemas = Companion.databaseSchemas
// System properties set in main 'corda-project' build.gradle
// Note: the database provider configuration file for integration tests should specify:
// dataSource.user = ${nodeOrganizationName}
@ -22,19 +26,20 @@ abstract class IntegrationTest {
private val dbProvider = System.getProperty(DATABASE_PROVIDER, "")
private val TEST_DB_SCRIPT_DIR = "test.db.script.dir"
private val testDbScriptDir = System.getProperty(TEST_DB_SCRIPT_DIR, "database-scripts")
var databaseSchemas = mutableListOf<String>()
@BeforeClass
@JvmStatic
fun globalSetUp() {
if (dbProvider.isNotEmpty()) {
runDbScript(dbProvider,"$testDbScriptDir/db-global-setup-${this::class.simpleName}.sql")
runDbScript(dbProvider,"$testDbScriptDir/db-global-setup.sql", databaseSchemas)
}
}
@AfterClass
@JvmStatic
fun globalTearDown() {
if (dbProvider.isNotEmpty()) {
runDbScript(dbProvider,"$testDbScriptDir/db-global-cleanup-${this::class.simpleName}.sql")
runDbScript(dbProvider,"$testDbScriptDir/db-global-cleanup.sql", databaseSchemas)
}
}
}
@ -43,15 +48,31 @@ abstract class IntegrationTest {
@Throws(Exception::class)
open fun setUp() {
if (dbProvider.isNotEmpty()) {
runDbScript(dbProvider,"$testDbScriptDir/db-setup-${this::class.simpleName}.sql")
runDbScript(dbProvider,"$testDbScriptDir/db-setup.sql", databaseSchemas)
}
}
@After
open fun tearDown() {
if (dbProvider.isNotEmpty()) {
runDbScript(dbProvider,"$testDbScriptDir/db-cleanup-${this::class.simpleName}.sql")
runDbScript(dbProvider,"$testDbScriptDir/db-cleanup.sql", databaseSchemas)
}
}
}
class IntegrationTestSchemas(vararg var list : String) : ExternalResource() {
override fun before() {
IntegrationTest.Companion.databaseSchemas.addAll(list)
}
override fun after() {
IntegrationTest.Companion.databaseSchemas.clear()
}
}
fun Party.toDatabaseSchemaName() = this.name.organisation.replace(" ", "").replace("-", "_")
fun Party.toDatabaseSchemaNames(vararg postfixes: String): List<String> {
val nodeName = this.toDatabaseSchemaName()
return postfixes.map { "$nodeName$it" }
}

View File

@ -0,0 +1,10 @@
package net.corda.testing.database
object DatabaseConstants {
const val DATA_SOURCE_URL = "dataSourceProperties.dataSource.url"
const val DATA_SOURCE_CLASSNAME = "dataSourceProperties.dataSourceClassName"
const val DATA_SOURCE_USER = "dataSourceProperties.dataSource.user"
const val DATA_SOURCE_PASSWORD = "dataSourceProperties.dataSource.password"
const val TRANSACTION_ISOLATION_LEVEL = "database.transactionIsolationLevel"
const val SCHEMA = "database.schema"
}

View File

@ -3,10 +3,20 @@ package net.corda.testing.database
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import net.corda.core.utilities.loggerFor
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_CLASSNAME
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_PASSWORD
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_URL
import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_USER
import org.apache.commons.logging.LogFactory
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.support.EncodedResource
import org.springframework.jdbc.datasource.DriverManagerDataSource
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator
import org.springframework.jdbc.datasource.init.*
import org.springframework.util.StringUtils
import java.sql.Connection
import java.sql.SQLException
import java.sql.SQLWarning
import java.util.*
object DbScriptRunner {
private val log = loggerFor<DbScriptRunner>()
@ -15,19 +25,106 @@ object DbScriptRunner {
private const val TEST_DB_ADMIN_USER = "test.db.admin.user"
private const val TEST_DB_ADMIN_PASSWORD = "test.db.admin.password"
fun runDbScript(dbProvider: String, initScript: String) {
private fun createDataSource(dbProvider: String) : DriverManagerDataSource {
val parseOptions = ConfigParseOptions.defaults()
val databaseConfig = ConfigFactory.parseResources("$dbProvider.conf", parseOptions.setAllowMissing(false))
val allSystemProperties = System.getProperties().toList().map { it.first.toString() to it.second.toString() }.toMap()
val dataSourceSystemProperties = Properties()
val dataSourceKeys = listOf(TEST_DB_ADMIN_USER, TEST_DB_ADMIN_PASSWORD, DATA_SOURCE_URL, DATA_SOURCE_CLASSNAME,
DATA_SOURCE_USER, DATA_SOURCE_PASSWORD)
dataSourceKeys.filter { allSystemProperties.containsKey(it) }.forEach { dataSourceSystemProperties.setProperty(it, allSystemProperties[it]) }
val databaseConfig = ConfigFactory.parseProperties(dataSourceSystemProperties, parseOptions)
.withFallback(ConfigFactory.parseResources("$dbProvider.conf", parseOptions.setAllowMissing(false)))
val dataSource = DriverManagerDataSource()
dataSource.setDriverClassName(databaseConfig.getString("dataSourceProperties.dataSourceClassName"))
dataSource.url = databaseConfig.getString("dataSourceProperties.dataSource.url")
dataSource.username = System.getProperty(TEST_DB_ADMIN_USER)
dataSource.password = System.getProperty(TEST_DB_ADMIN_PASSWORD)
val initSchema = ClassPathResource(initScript )
if (initSchema.exists()) {
val databasePopulator = ResourceDatabasePopulator(false, true, null, initSchema)
DatabasePopulatorUtils.execute(databasePopulator, dataSource)
dataSource.setDriverClassName(databaseConfig.getString(DATA_SOURCE_CLASSNAME))
dataSource.url = databaseConfig.getString(DATA_SOURCE_URL)
dataSource.username = databaseConfig.getString(TEST_DB_ADMIN_USER)
dataSource.password = databaseConfig.getString(TEST_DB_ADMIN_PASSWORD)
return dataSource
}
fun runDbScript(dbProvider: String, initScript: String? = null, databaseSchemas: List<String> = emptyList()) {
if (initScript != null) {
val initSchema = ClassPathResource(initScript)
if (initSchema.exists()) {
val encodedResource = EncodedResource(initSchema)
val inputString = encodedResource.inputStream.bufferedReader().use { it.readText().split("\n") }
val resolvedScripts = merge(inputString, databaseSchemas)
log.info("Executing DB Script for schemas $databaseSchemas with ${resolvedScripts.size} statements.")
DatabasePopulatorUtils.execute(ListPopulator(false, true, resolvedScripts),
createDataSource(dbProvider))
} else log.warn("DB Script missing: $initSchema")
}
}
fun merge(scripts: List<String>, schema: String): List<String> =
scripts.map { it.replace("\${schema}", schema) }
fun merge(scripts: List<String>, schemas: List<String>): List<String> =
if(schemas.isEmpty()) scripts else schemas.map { merge(scripts, it) }.flatten()
}
//rewritten version of org.springframework.jdbc.datasource.init.ResourceDatabasePopulator
class ListPopulator(private val continueOnError: Boolean,
private val ignoreFailedDrops: Boolean,
private val statements: List<String>) : DatabasePopulator {
private val logger = LogFactory.getLog(ScriptUtils::class.java)
override fun populate(connection: Connection) {
try {
if (logger.isInfoEnabled) {
logger.info("Executing SQL script " )
}
val startTime = System.currentTimeMillis()
val resource = statements.toString().substring(0,30) + " [...]"
var stmtNumber = 0
val stmt = connection.createStatement()
try {
for (statement in statements) {
stmtNumber++
try {
stmt.execute(statement)
val rowsAffected = stmt.updateCount
if (logger.isDebugEnabled) {
logger.debug(rowsAffected.toString() + " returned as update count for SQL: " + statement)
var warningToLog: SQLWarning? = stmt.warnings
while (warningToLog != null) {
logger.debug("SQLWarning ignored: SQL state '" + warningToLog.sqlState +
"', error code '" + warningToLog.errorCode +
"', message [" + warningToLog.message + "]")
warningToLog = warningToLog.nextWarning
}
}
} catch (ex: SQLException) {
val dropStatement = StringUtils.startsWithIgnoreCase(statement.trim { it <= ' ' }, "drop")
if (continueOnError || dropStatement && ignoreFailedDrops) {
if (logger.isDebugEnabled) {
logger.debug(ex)
}
} else {
throw ex
}
}
}
} finally {
try {
stmt.close()
} catch (ex: Throwable) {
logger.debug("Could not close JDBC Statement", ex)
}
}
val elapsedTime = System.currentTimeMillis() - startTime
if (logger.isInfoEnabled) {
logger.info("Executed SQL script from $resource in $elapsedTime ms.")
}
logger.info("Executed SQL script $resource" )
} catch (ex: Exception) {
if (ex is ScriptException) {
throw ex
}
throw UncategorizedScriptException(
"Failed to execute database script from resource [resource]", ex)
}
else log.warn("DB Script missing: $initSchema")
}
}

View File

@ -0,0 +1,49 @@
DROP TABLE IF EXISTS ${schema}.node_attachments;
DROP TABLE IF EXISTS ${schema}.node_checkpoints;
DROP TABLE IF EXISTS ${schema}.node_transactions;
DROP TABLE IF EXISTS ${schema}.node_message_retry;
DROP TABLE IF EXISTS ${schema}.node_message_ids;
DROP TABLE IF EXISTS ${schema}.vault_states;
DROP TABLE IF EXISTS ${schema}.node_our_key_pairs;
DROP TABLE IF EXISTS ${schema}.node_scheduled_states;
DROP TABLE IF EXISTS ${schema}.node_network_map_nodes;
DROP TABLE IF EXISTS ${schema}.node_network_map_subscribers;
DROP TABLE IF EXISTS ${schema}.node_notary_commit_log;
DROP TABLE IF EXISTS ${schema}.node_transaction_mappings;
DROP TABLE IF EXISTS ${schema}.vault_fungible_states_parts;
DROP TABLE IF EXISTS ${schema}.vault_linear_states_parts;
DROP TABLE IF EXISTS ${schema}.vault_fungible_states;
DROP TABLE IF EXISTS ${schema}.vault_linear_states;
DROP TABLE IF EXISTS ${schema}.node_bft_committed_states;
DROP TABLE IF EXISTS ${schema}.node_raft_committed_states;
DROP TABLE IF EXISTS ${schema}.vault_transaction_notes;
DROP TABLE IF EXISTS ${schema}.link_nodeinfo_party;
DROP TABLE IF EXISTS ${schema}.node_link_nodeinfo_party;
DROP TABLE IF EXISTS ${schema}.node_info_party_cert;
DROP TABLE IF EXISTS ${schema}.node_info_hosts;
DROP TABLE IF EXISTS ${schema}.node_infos;
DROP TABLE IF EXISTS ${schema}.cp_states;
DROP TABLE IF EXISTS ${schema}.node_contract_upgrades;
DROP TABLE IF EXISTS ${schema}.node_identities;
DROP TABLE IF EXISTS ${schema}.node_named_identities;
DROP TABLE IF EXISTS ${schema}.children;
DROP TABLE IF EXISTS ${schema}.parents;
DROP TABLE IF EXISTS ${schema}.contract_cash_states;
DROP TABLE IF EXISTS ${schema}.messages;
DROP TABLE IF EXISTS ${schema}.DummyDealStateSchemaV1$PersistentDummyDealState_participants;
DROP TABLE IF EXISTS ${schema}.DummyLinearStateSchemaV1$PersistentDummyLinearState_participants;
DROP TABLE IF EXISTS ${schema}.DummyLinearStateSchemaV2$PersistentDummyLinearState_participants;
DROP TABLE IF EXISTS ${schema}.SampleCashSchemaV2$PersistentCashState_participants;
DROP TABLE IF EXISTS ${schema}.SampleCashSchemaV3$PersistentCashState_participants;
DROP TABLE IF EXISTS ${schema}.SampleCommercialPaperSchemaV2$PersistentCommercialPaperState_participants;
DROP TABLE IF EXISTS ${schema}.cash_states_v2;
DROP TABLE IF EXISTS ${schema}.cash_states_v3;
DROP TABLE IF EXISTS ${schema}.cp_states_v2;
DROP TABLE IF EXISTS ${schema}.dummy_deal_states;
DROP TABLE IF EXISTS ${schema}.dummy_linear_states;
DROP TABLE IF EXISTS ${schema}.dummy_linear_states_v2;
DROP SEQUENCE IF EXISTS ${schema}.hibernate_sequence;
IF NOT EXISTS (SELECT schema_name FROM information_schema.schemata WHERE schema_name = '${schema}') EXEC('CREATE SCHEMA ${schema}');
IF NOT EXISTS (SELECT * FROM sys.sysusers WHERE name='${schema}') CREATE USER ${schema} FOR LOGIN ${schema} WITH DEFAULT_SCHEMA = ${schema};
GRANT ALTER, DELETE, EXECUTE, INSERT, REFERENCES, SELECT, UPDATE, VIEW DEFINITION ON SCHEMA::${schema} TO ${schema};
GRANT CREATE TABLE, CREATE PROCEDURE, CREATE FUNCTION, CREATE VIEW TO ${schema};

View File

@ -0,0 +1,87 @@
--once off script to run against master database (not a user database)
CREATE LOGIN AliceCorp WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER AliceCorp FROM LOGIN AliceCorp;
CREATE LOGIN AliceCorp_10000 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER AliceCorp_10000 FROM LOGIN AliceCorp_10003;
CREATE LOGIN AliceCorp_10003 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER AliceCorp_10003 FROM LOGIN AliceCorp_10003;
CREATE LOGIN AliceCorp_10006 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER AliceCorp_10006 FROM LOGIN AliceCorp_10006;
CREATE LOGIN BankA WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankA FROM LOGIN BankA;
CREATE LOGIN BankA_10000 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankA_10000 FROM LOGIN BankA_10000;
CREATE LOGIN BankA_10003 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankA_10003 FROM LOGIN BankA_10003;
CREATE LOGIN BankA_10006 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankA_10006 FROM LOGIN BankA_10006;
CREATE LOGIN BankB WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankB FROM LOGIN BankB;
CREATE LOGIN BobPlc WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BobPlc FROM LOGIN BobPlc;
CREATE LOGIN BobPlc_10000 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BobPlc_10000 FROM LOGIN BobPlc_10000;
CREATE LOGIN BobPlc_10003 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BobPlc_10003 FROM LOGIN BobPlc_10003;
CREATE LOGIN BobPlc_10006 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BobPlc_10006 FROM LOGIN BobPlc_10006;
CREATE LOGIN CharlieLtd WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER CharlieLtd FROM LOGIN CharlieLtd;
CREATE LOGIN DistributedService_0 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER DistributedService_0 FROM LOGIN DistributedService_0;
CREATE LOGIN DistributedService_1 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER DistributedService_1 FROM LOGIN DistributedService_1;
CREATE LOGIN NetworkMapService WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NetworkMapService FROM LOGIN NetworkMapService;
CREATE LOGIN Notary WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER Notary FROM LOGIN Notary;
CREATE LOGIN NotaryService WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService FROM LOGIN NotaryService;
CREATE LOGIN NotaryService0 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService0 FROM LOGIN NotaryService0;
CREATE LOGIN NotaryService1 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService1 FROM LOGIN NotaryService1;
CREATE LOGIN NotaryService2 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService2 FROM LOGIN NotaryService2;
CREATE LOGIN NotaryService_0 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService_0 FROM LOGIN NotaryService_0;
CREATE LOGIN NotaryService_1 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService_1 FROM LOGIN NotaryService_1;
CREATE LOGIN NotaryService_2 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER NotaryService_2 FROM LOGIN NotaryService_2;
CREATE LOGIN MegaCorp WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER MegaCorp FOR LOGIN MegaCorp;
CREATE LOGIN node_0 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_0 FOR LOGIN node_0;
CREATE LOGIN node_1 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_1 FOR LOGIN node_1;
CREATE LOGIN node_2 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_2 FOR LOGIN node_2;
CREATE LOGIN node_3 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_3 FOR LOGIN node_3;
CREATE LOGIN node_4 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_4 FOR LOGIN node_4;
CREATE LOGIN node_5 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_5 FOR LOGIN node_5;
CREATE LOGIN node_6 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_6 FOR LOGIN node_6;
CREATE LOGIN node_7 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_7 FOR LOGIN node_7;
CREATE LOGIN node_8 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_8 FOR LOGIN node_8;
CREATE LOGIN node_9 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER node_9 FOR LOGIN node_9;
CREATE LOGIN RAFTNotaryService_0 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER RAFTNotaryService_0 FROM LOGIN RAFTNotaryService_0;
CREATE LOGIN RAFTNotaryService_1 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER RAFTNotaryService_1 FROM LOGIN RAFTNotaryService_1;
CREATE LOGIN RAFTNotaryService_2 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER RAFTNotaryService_2 FROM LOGIN RAFTNotaryService_2;
CREATE LOGIN RegulatorA WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER RegulatorA FROM LOGIN RegulatorA;
CREATE LOGIN AliceCorp_10012 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER AliceCorp_10012 FROM LOGIN AliceCorp_10012;
CREATE LOGIN BobPlc_10012 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BobPlc_10012 FROM LOGIN BobPlc_10012;
CREATE LOGIN BankA_10012 WITH PASSWORD = 'yourStrong(!)Password';
CREATE USER BankA_10012 FROM LOGIN BankA_10012;

View File

@ -0,0 +1,11 @@
dataSourceProperties = {
dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource"
dataSource.url = "jdbc:sqlserver://[HOST]:1433;databaseName=[DATABASE];encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30"
dataSource.user = ${nodeOrganizationName}
dataSource.password = "yourStrong(!)Password"
}
database = {
transactionIsolationLevel = READ_COMMITTED
initDatabase = true
schema = ${nodeOrganizationName}
}

View File

@ -0,0 +1,11 @@
dataSourceProperties = {
dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource"
dataSource.url = "jdbc:sqlserver://[HOST]:[PORT]"
dataSource.user = ${nodeOrganizationName}
dataSource.password = "yourStrong(!)Password"
}
database = {
transactionIsolationLevel = READ_COMMITTED
initDatabase = true
schema = ${nodeOrganizationName}
}