/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

import org.elasticsearch.gradle.VersionProperties

import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask

apply plugin: 'elasticsearch.internal-testclusters'
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.bwc-test'
apply plugin: 'elasticsearch.rest-resources'

dependencies {
  testImplementation project(':x-pack:qa')
}

restResources {
  restApi {
    include '*'
  }
}

tasks.named("forbiddenPatterns").configure {
  exclude '**/system_key'
}

def buildDirectory = layout.buildDirectory
String outputDir = "${buildDirectory.file("generated-resources/${project.name}").get().asFile}"

tasks.register("copyTestNodeKeyMaterial", Copy) {
  from project(':x-pack:plugin:core').files('src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem',
    'src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt')
  into outputDir
}

buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName ->
  String oldVersion = bwcVersion.toString()

  // SearchableSnapshotsRollingUpgradeIT uses a specific repository to not interfere with other tests
  String searchableSnapshotRepository = "${buildDirectory.file("cluster/shared/searchable-snapshots-repo/${baseName}").get().asFile}"
  File repoFolder = buildDirectory.file("cluster/shared/repo/${baseName}").get().asFile
  def baseCluster = testClusters.register(baseName) {
    testDistribution = "DEFAULT"
    versions = [oldVersion, project.version]
    numberOfNodes = 3

    setting 'repositories.url.allowed_urls', 'http://snapshot.test*'
    setting 'path.repo', "['${repoFolder}', '${searchableSnapshotRepository}']"
    setting 'xpack.license.self_generated.type', 'trial'
    setting 'xpack.security.enabled', 'true'
    setting 'xpack.security.transport.ssl.enabled', 'true'
    setting 'xpack.security.authc.token.enabled', 'true'
    setting 'xpack.security.authc.token.timeout', '60m'
    setting 'xpack.security.authc.api_key.enabled', 'true'
    setting 'xpack.security.audit.enabled', 'true'
    setting 'xpack.security.transport.ssl.key', 'testnode.pem'
    setting 'xpack.security.transport.ssl.certificate', 'testnode.crt'
    keystore 'xpack.security.transport.ssl.secure_key_passphrase', 'testnode'

    if (bwcVersion.onOrAfter('7.0.0')) {
      setting 'xpack.security.authc.realms.file.file1.order', '0'
      setting 'xpack.security.authc.realms.native.native1.order', '1'
    } else {
      setting 'xpack.security.authc.realms.file1.type', 'file'
      setting 'xpack.security.authc.realms.file1.order', '0'
      setting 'xpack.security.authc.realms.native1.type', 'native'
      setting 'xpack.security.authc.realms.native1.order', '1'
    }
    if (bwcVersion.onOrAfter('6.6.0')) {
      setting 'ccr.auto_follow.wait_for_metadata_timeout', '1s'
    }
    if (bwcVersion.onOrAfter('7.11.0')) {
      extraConfigFile 'operator_users.yml', file("${project.projectDir}/src/test/resources/operator_users.yml")
      setting 'xpack.security.operator_privileges.enabled', "true"
      user username: "non_operator", password: 'x-pack-test-password', role: "superuser"
    }

    user username: "test_user", password: "x-pack-test-password"

    extraConfigFile 'testnode.pem', file("$outputDir/testnode.pem")
    extraConfigFile 'testnode.crt', file("$outputDir/testnode.crt")

    keystore 'xpack.watcher.encryption_key', file("${project.projectDir}/src/test/resources/system_key")
    setting 'xpack.watcher.encrypt_sensitive_data', 'true'

    // Old versions of the code contain an invalid assertion that trips
    // during tests.  Versions 5.6.9 and 6.2.4 have been fixed by removing
    // the assertion, but this is impossible for released versions.
    // However, released versions run without assertions, so end users won't
    // be suffering the effects.  This argument effectively removes the
    // incorrect assertion from the older versions used in the BWC tests.
    if (bwcVersion.before('5.6.9') || (bwcVersion.onOrAfter('6.0.0') && bwcVersion.before('6.2.4'))) {
      jvmArgs '-da:org.elasticsearch.xpack.monitoring.exporter.http.HttpExportBulk'
    }
    setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'

    if (bwcVersion.onOrAfter('7.12.0')) {
      setting 'xpack.searchable.snapshot.shared_cache.size', '16MB'
      setting 'xpack.searchable.snapshot.shared_cache.region_size', '256KB'
    }
  }

  tasks.register("${baseName}#oldClusterTest", StandaloneRestIntegTestTask) {
    useCluster baseCluster
    mustRunAfter("precommit")
    dependsOn "copyTestNodeKeyMaterial"
    def repoDir = buildDirectory.file("cluster/shared/repo/${baseName}").get().asFile
    doFirst {
      delete(repoDir)
      delete("${searchableSnapshotRepository}")
    }
    systemProperty 'tests.rest.suite', 'old_cluster'
    systemProperty 'tests.upgrade_from_version', oldVersion
    systemProperty 'tests.path.searchable.snapshots.repo', searchableSnapshotRepository
    nonInputProperties.systemProperty('tests.rest.cluster', getClusterInfo(baseName).map { it.allHttpSocketURI.join(",") })
    nonInputProperties.systemProperty('tests.clustername', baseName)
  }

  tasks.register("${baseName}#oneThirdUpgradedTest", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#oldClusterTest"
    useCluster baseCluster
    doFirst {
      getRegistry().get().nextNodeToNextVersion(baseCluster)
    }
    nonInputProperties.systemProperty('tests.rest.cluster', getClusterInfo(baseName).map { it.allHttpSocketURI.join(",") })
    nonInputProperties.systemProperty('tests.clustername', baseName)
    systemProperty 'tests.rest.suite', 'mixed_cluster'
    systemProperty 'tests.first_round', 'true'
    systemProperty 'tests.upgrade_from_version', oldVersion
    systemProperty 'tests.path.searchable.snapshots.repo', searchableSnapshotRepository
  }

  tasks.register("${baseName}#twoThirdsUpgradedTest", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#oneThirdUpgradedTest"
    useCluster baseCluster
    doFirst {
      getRegistry().get().nextNodeToNextVersion(baseCluster)
    }
    nonInputProperties.systemProperty('tests.rest.cluster', getClusterInfo(baseName).map { it.allHttpSocketURI.join(",") })
    nonInputProperties.systemProperty('tests.clustername', baseName)
    systemProperty 'tests.rest.suite', 'mixed_cluster'
    systemProperty 'tests.first_round', 'false'
    systemProperty 'tests.upgrade_from_version', oldVersion
    systemProperty 'tests.path.searchable.snapshots.repo', searchableSnapshotRepository
  }

  tasks.register("${baseName}#upgradedClusterTest", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#twoThirdsUpgradedTest"
    useCluster baseCluster
    doFirst {
      getRegistry().get().nextNodeToNextVersion(baseCluster)
    }
    nonInputProperties.systemProperty('tests.rest.cluster', getClusterInfo(baseName).map { it.allHttpSocketURI.join(",") })
    nonInputProperties.systemProperty('tests.clustername', baseName)
    systemProperty 'tests.rest.suite', 'upgraded_cluster'
    systemProperty 'tests.upgrade_from_version', oldVersion
    systemProperty 'tests.path.searchable.snapshots.repo', searchableSnapshotRepository
  }

  tasks.register(bwcTaskName(bwcVersion)) {
    dependsOn "${baseName}#upgradedClusterTest"
  }
}
