From 087d869bac68f0fbd97d350fe79425c3ea62b8d1 Mon Sep 17 00:00:00 2001 From: Sven Kiesewetter Date: Tue, 6 Feb 2024 16:01:40 +0100 Subject: [PATCH] feat!: upgrade bmuschko docker plugin (#93001) * gradle tasks to start a container have been split into the 3 different aspects: 1. *find* the container by name 2. if not existing: *create* 3. if not running: *start* --- README.asciidoc | 48 ++-- build.gradle.kts | 4 +- .../docker/ICMDockerCustomizationPlugin.kt | 21 +- .../gradle/icm/docker/ICMDockerPlugin.kt | 27 +-- .../icm/docker/ICMDockerReadmePushPlugin.kt | 28 +-- .../gradle/icm/docker/ICMGebTestPlugin.kt | 8 +- .../gradle/icm/docker/ICMSolrCloudPlugin.kt | 4 +- .../gradle/icm/docker/ICMTestDockerPlugin.kt | 2 +- .../extension/DevelopmentConfiguration.kt | 24 +- .../gradle/icm/docker/extension/Images.kt | 5 +- .../icm/docker/tasks/AbstractContainerTask.kt | 5 +- .../icm/docker/tasks/AbstractPullImage.kt | 8 +- .../gradle/icm/docker/tasks/BuildImage.kt | 2 +- .../icm/docker/tasks/ContainerHandle.kt | 73 ++++++ .../icm/docker/tasks/CreateASContainer.kt | 217 ++++++++++++++++++ .../icm/docker/tasks/CreateExtraContainer.kt | 132 +++++++++++ .../gradle/icm/docker/tasks/FindContainer.kt | 79 +++++++ .../icm/docker/tasks/GenICMProperties.kt | 71 +----- .../icm/docker/tasks/StartExtraContainer.kt | 203 ++++++---------- ...raImage.kt => StartMailServerContainer.kt} | 69 +++--- .../icm/docker/tasks/StartServerContainer.kt | 178 -------------- .../gradle/icm/docker/tasks/WaitForServer.kt | 4 +- .../tasks/utils/ContainerEnvironment.kt | 19 +- .../utils/ICMContainerEnvironmentBuilder.kt | 12 + .../tasks/utils/TaskAuthLocatorHelper.kt | 13 +- .../icm/docker/utils/AbstractTaskPreparer.kt | 155 ++++++++++--- .../gradle/icm/docker/utils/Configuration.kt | 14 -- ...erverTaskPreparer.kt => ASTaskPreparer.kt} | 74 +++--- .../appsrv/ASTestContainerTaskPreparer.kt | 147 ++++++++++++ .../utils/appsrv/AbstractASTaskPreparer.kt | 167 ++++++++------ .../utils/appsrv/CustomizationPreparer.kt | 22 +- .../utils/appsrv/ICMServerTaskPreparer.kt | 110 --------- .../icm/docker/utils/appsrv/TaskPreparer.kt | 8 +- .../docker/utils/appsrv/TestTaskPreparer.kt | 8 +- ...skPreparer.kt => WaitingAsTaskPreparer.kt} | 53 ++--- .../icm/docker/utils/mail/TaskPreparer.kt | 75 +++--- .../icm/docker/utils/mssql/TaskPreparer.kt | 163 +++++-------- .../icm/docker/utils/nginx/TaskPreparer.kt | 142 ++++++------ .../icm/docker/utils/oracle/TaskPreparer.kt | 85 ------- .../icm/docker/utils/redis/TaskPreparer.kt | 23 +- .../docker/utils/solrcloud/SolrPreparer.kt | 94 ++++---- .../icm/docker/utils/solrcloud/ZKPreparer.kt | 96 ++++---- .../docker/utils/webserver/TaskPreparer.kt | 4 +- .../docker/utils/webserver/WAATaskPreparer.kt | 68 ++---- .../docker/utils/webserver/WATaskPreparer.kt | 109 ++++----- .../ICMDockerPluginIntegegrationSpec.groovy | 21 +- .../ICMDockerTaskIntegrationSpec.groovy | 2 +- .../gradle/icm/docker/TaskICMGenSpec.groovy | 86 +------ 48 files changed, 1536 insertions(+), 1446 deletions(-) create mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/tasks/ContainerHandle.kt create mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateASContainer.kt create mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateExtraContainer.kt create mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/tasks/FindContainer.kt rename src/main/kotlin/com/intershop/gradle/icm/docker/tasks/{PullExtraImage.kt => StartMailServerContainer.kt} (50%) rename src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/{ServerTaskPreparer.kt => ASTaskPreparer.kt} (72%) create mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTestContainerTaskPreparer.kt delete mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ICMServerTaskPreparer.kt rename src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/{ContainerTaskPreparer.kt => WaitingAsTaskPreparer.kt} (77%) delete mode 100644 src/main/kotlin/com/intershop/gradle/icm/docker/utils/oracle/TaskPreparer.kt diff --git a/README.asciidoc b/README.asciidoc index aa8b811..ea3a8b5 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -1,5 +1,6 @@ = Intershop Commerce Management - Docker Plugins -:latestRevision: 4.1.0 +:latestRevision: 5.0.0 +:gradlePluginVersion: 6.0.0 :toc: :icons: font @@ -27,7 +28,7 @@ The plugins must be applied to the root project. [subs=+attributes] ---- plugins { - id 'com.intershop.gradle.icm.base' version '3.4.14' + id 'com.intershop.gradle.icm.base' version '{gradlePluginVersion}' id 'com.intershop.gradle.icm.docker' version '{latestRevision}' } @@ -39,11 +40,10 @@ intershop { intershop_docker { images { - webadapter = 'intershophub/icm-webadapter:2.1.0' - webadapteragent = 'intershophub/icm-webadapteragent:3.1.0' + webadapter = 'intershophub/icm-webadapter:2.4.9' + webadapteragent = 'intershophub/icm-webadapteragent:4.0.0' mssql = 'intershophub/mssql-intershop:2019-latest' - oracle = 'intershophub/oracle-intershop:latest' mailsrv = 'mailhog/mailhog:latest' } @@ -86,7 +86,7 @@ intershop_docker { [subs=+attributes] ---- plugins { - id("com.intershop.gradle.icm.base") version "3.4.14" + id("com.intershop.gradle.icm.base") version "{gradlePluginVersion}" id("com.intershop.gradle.icm.docker") version "{latestRevision}" } @@ -98,11 +98,10 @@ intershop { intershop_docker { images { - webadapter.set("'intershophub/icm-webadapter:2.1.0") - webadapteragent.set("intershophub/icm-webadapteragent:3.1.0") + webadapter.set("'intershophub/icm-webadapter:2.4.9") + webadapteragent.set("intershophub/icm-webadapteragent:4.0.0") mssql.set("intershophub/mssql-intershop:2019-latest") - oracle.set("intershophub/oracle-intershop:latest") mailsrv.set("mailhog/mailhog:latest") } @@ -210,7 +209,6 @@ imageBuild { |`webadapter` | `Property` | `docker.intershop.de/intershop/icm-webadapter:latest` | The image contains the web server of the Intershop Commerce Management application with a special Intershop Apache module. |`webadapteragent` | `Property` | `docker.intershop.de/intershop/icm-webadapteragent:latest` | The web adapter agent image of the Intershop Commerce Management application. |`mssqldb` | `Property` | `mcr.microsoft.com/mssql/server:2019-latest` | The Microsoft SQL server image. There will be also a build file available. -|`oracledb` | `Property` | `docker.intershop.de/intershop/oracle-xe-server:18.4.0` | This image is only available internally. The build files will be provided. |`mailsrv` | `Property` | `mailhog/mailhog:latest` | A mail server for testing the mail feature of the application. |`solr` | `Property` | `solr/latest` | This image is used for the Solr Cloud configuration with a single node. |`zookeeper` | `Property` | `zookeeper:latest` | This image is used for the Solr Cloud configuration with a single node. @@ -278,7 +276,6 @@ For all properties configurations methods with a closure or an action are availa | *prepareNetwork* | Creates a network with the specified name -network. All start tasks are dependend on this task. | *removeNetwork* | Removes the network from the Docker configuration. | **MSSQL* | These tasks pull, start, stop and remove the MSSQL image. -| **Oracle* | These tasks pull, start, stop and remove the Oracle DB image. | **MailSrv* | These tasks pull, start, stop and remove the Mail server image. | **SolrCloud* | These tasks orchestrate all Solr Cloud related tasks. | **ZK* | These tasks pull, start, stop and remove the Zookeeper image. @@ -306,8 +303,6 @@ The task can be called with the following parameters: | Parameter |Description | --db | Option for the used database. The following values are possible: + - _oracle-container_ - Oracle configuration for database provided by a container + - _oracle_ - Oracle configuration for an external database + _mssql-container_ - MSSQL configuration for database provided by a container + _mssql_ - MSSQL configuration for an external database | --icmas | If this parameter specified, the properties file will be generated for app server development. @@ -352,17 +347,6 @@ The following properties are part of the <>. | `intershop.jdbc.password` | the password of the actual DB user to be created | String | Optional | `intershop` + |=== -===== Oracle [[OracleConfiguration]] - -[cols="10%,60%,10%,10%,10%", width="99%, options="header"] -|=== -| Key | Description | Co-domain | Mandatory/Optional | Default value - -| `intershop.db.oracle.listenerport` | Exposed listener port of the database. | Integer | Optional | `1521` + -| `intershop.db.oracle.port` | Exposed enterprise manager port of the oracle db. | Integer | Optional | `1521` + -| `intershop.db.oracle.useHostUser` | controls if the host system's current user is used for the container start | Boolean | Optional | `false` + -|=== - ===== WA [[WAConfiguration]] [cols="10%,60%,10%,10%,10%", width="99%, options="header"] @@ -503,7 +487,7 @@ The plugins must be applied to the root project. |=== | Task name |Description -| **Container* | These tasks pull, start, stop and remove the ICM application server image with a special command. There is no running process inside, but it uses the same configuration like the appserver container. +| **Container* | These tasks pull, start, stop and remove the ICM application server image with a special command. There is no running process inside, but it uses the same configuration as the appserver container. | **AS* | These tasks pull, start, stop and remove the ICM application server image. | **Server* | These tasks orchestrate all ICM server related tasks (web server and app server) | *dbPrepare* | This task starts dbPrepare inside the running "Container" docker container. @@ -531,7 +515,7 @@ The following properties are part of the <>. | `intershop.servletEngine.managementConnector.port` | the host port to be used for the appserver management connector http port | Integer | Optional | `7743` + | `intershop.as.jmx.connector.port` | the host port to be used for the appserver JMX port | Integer | Optional | `7747` + | `intershop.as.debug.port` | the host port to be used for the appserver debug port | Integer | Optional | `7746` + -| `intershop.databaseType` | database type to be used | { `mssql`, `oracle` } | Mandatory | + +| `intershop.databaseType` | database type to be used | { `mssql` } | Mandatory | + | `intershop.jdbc.url` | JDBC URL pointing to the database to be used | URL | Mandatory | + | `intershop.jdbc.user` | JDBC database user | String | Mandatory | + | `intershop.jdbc.password` | JDBC database password | String | Mandatory | + @@ -540,7 +524,8 @@ The following properties are part of the <>. |=== -- -The referenced database can either be an externally running database or an instance started using the gradle <> `startMSSQL` respectively `startOracle`. In either case the properties `intershop.databaseType` and `intershop.jdbc.*` have to be defined properly (when using the gradle tasks the hostname equals the container name). +The referenced database can either be an externally running database or an instance started using the gradle <> `startMSSQL`. +In either case the properties `intershop.databaseType` and `intershop.jdbc.*` have to be defined properly (when using the gradle tasks the hostname equals the container name). -- ===== Application Server [[StartASConfiguration]] @@ -601,6 +586,9 @@ NOTE: To make the `classpathLayout` `sourceJar` work the gradle-property `localV ===== Application Server [[StartASParameters]] +IMPORTANT: The following parameters actually belong to the task `createAS` (not `startAS`). +But if you just call for example `./gradlew startAS --debug-icm=suspend` the parameter(s) are also applied to the `createAS`-task (task `startAS` depends on `createAS`). + [cols="10%,70%,10%,10%", width="99%, options="header"] |=== | Parameter | Description | Co-domain | Default value @@ -975,8 +963,6 @@ The plugin set the following system properties for the test: | `geb.build.baseUrl` | The url will be calculated from the base configuration of the web server image. If the container framework is used, the internal network name is used. |=== -Furthermore the host - ==== Extension 'gebConfiguration' *Properties* @@ -1086,8 +1072,8 @@ icm.properties [subs=+attributes] ---- # database connection configuration -intershop.databaseType = oracle|mssql -intershop.jdbc.url = jdbc:oracle:thin:@host:1521:XE | jdbc:sqlserver://host:1433;databaseName=dbname +intershop.databaseType = mssql +intershop.jdbc.url = jdbc:sqlserver://host:1433;databaseName=dbname intershop.jdbc.user = user intershop.jdbc.password = password diff --git a/build.gradle.kts b/build.gradle.kts index f135682..9dbd366 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -303,8 +303,8 @@ dependencies { implementation(gradleKotlinDsl()) implementation("org.apache.solr:solr-solrj:9.4.0") - implementation("com.bmuschko:gradle-docker-plugin:8.1.0") - implementation("com.intershop.gradle.icm:icm-gradle-plugin:6.0.0") + implementation("com.bmuschko.docker-remote-api:com.bmuschko.docker-remote-api.gradle.plugin:9.3.6") + implementation("com.intershop.gradle.icm:icm-gradle-plugin:6.0.1") implementation("com.intershop.gradle.jobrunner:icmjobrunner:1.0.5") } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerCustomizationPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerCustomizationPlugin.kt index fa5cd88..625aea4 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerCustomizationPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerCustomizationPlugin.kt @@ -27,7 +27,6 @@ import com.intershop.gradle.icm.docker.utils.CustomizationImageBuildPreparer import com.intershop.gradle.icm.docker.utils.ISHUnitTestRegistry import com.intershop.gradle.icm.docker.utils.appsrv.AbstractASTaskPreparer import com.intershop.gradle.icm.docker.utils.network.TaskPreparer -import com.intershop.gradle.icm.docker.utils.appsrv.TaskPreparer as AppSrvPreparer import com.intershop.gradle.icm.docker.utils.webserver.WATaskPreparer import com.intershop.gradle.icm.extension.IntershopExtension import org.gradle.api.GradleException @@ -38,6 +37,7 @@ import org.gradle.api.UnknownTaskException import org.gradle.api.artifacts.DependencySet import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.getByType +import com.intershop.gradle.icm.docker.utils.appsrv.TaskPreparer as AppSrvPreparer /** * Main plugin class of the customization plugin. @@ -91,11 +91,9 @@ open class ICMDockerCustomizationPlugin : Plugin { val icmExtension = project.extensions.getByType() val mssqlDatabase = tasks.named( - "start${com.intershop.gradle.icm.docker.utils.mssql.TaskPreparer.extName}") - val oracleDatabase = tasks.named( - "start${com.intershop.gradle.icm.docker.utils.oracle.TaskPreparer.extName}") + "start${com.intershop.gradle.icm.docker.utils.mssql.TaskPreparer.EXT_NAME}") val mailSrvTask = tasks.named( - "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.extName}", + "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.EXT_NAME}", StartExtraContainer::class.java) val startSolrCloud = tasks.named( "start${com.intershop.gradle.icm.docker.utils.solrcloud.TaskPreparer.TASK_EXT_SERVER}") @@ -158,10 +156,10 @@ open class ICMDockerCustomizationPlugin : Plugin { } val dbPrepare: TaskProvider = getDBPrepare(this, - containerPreparer, mssqlDatabase, oracleDatabase) + containerPreparer, mssqlDatabase) configureISHUnitTest(this, - dockerExtension, containerPreparer, dbPrepare, mssqlDatabase, oracleDatabase) + dockerExtension, containerPreparer, dbPrepare, mssqlDatabase) addTestReportConfiguration(this) @@ -181,7 +179,7 @@ open class ICMDockerCustomizationPlugin : Plugin { } /** - * Determines the name of the customization that is associated the project this plugin is applied to. + * Determines the name of the customization that is associated to the project this plugin is applied to. * * __Attention__: extends the class [Project] by this function */ @@ -191,7 +189,6 @@ open class ICMDockerCustomizationPlugin : Plugin { project: Project, containerPreparer: AbstractASTaskPreparer, mssqlDatabase: TaskProvider, - oracleDatabase: TaskProvider, ): TaskProvider { return project.tasks.register(DBPrepareTask.TASK_NAME, DBPrepareTask::class.java) { task -> task.group = ICMDockerPlugin.GROUP_SERVERBUILD @@ -199,7 +196,7 @@ open class ICMDockerCustomizationPlugin : Plugin { task.executeUsing(containerPreparer.startTask) task.finalizedBy(containerPreparer.removeTask) - task.mustRunAfter(mssqlDatabase, oracleDatabase) + task.mustRunAfter(mssqlDatabase) } } @@ -209,7 +206,7 @@ open class ICMDockerCustomizationPlugin : Plugin { containerPreparer: AbstractASTaskPreparer, dbPrepare: TaskProvider, mssqlDatabase: TaskProvider, - oracleDatabase: TaskProvider) { + ) { project.gradle.sharedServices.registerIfAbsent(ISHUNIT_REGISTRY, ISHUnitTestRegistry::class.java) { it.maxParallelUsages.set(1) @@ -232,7 +229,7 @@ open class ICMDockerCustomizationPlugin : Plugin { task.testSuite.set(suite.testSuite) task.finalizedBy(containerPreparer.removeTask) - task.mustRunAfter(dbPrepare, mssqlDatabase, oracleDatabase) + task.mustRunAfter(dbPrepare, mssqlDatabase) } ishUnitTest.configure { task -> diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerPlugin.kt index ce10a66..0ab434b 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerPlugin.kt @@ -38,8 +38,6 @@ import com.intershop.gradle.icm.docker.utils.mssql.TaskPreparer as MSSQLPreparer import com.intershop.gradle.icm.docker.utils.mssql.TaskPreparer as MSSQLTaskPreparer import com.intershop.gradle.icm.docker.utils.network.TaskPreparer as NetworkPreparer import com.intershop.gradle.icm.docker.utils.nginx.TaskPreparer as NginxTaskPreparer -import com.intershop.gradle.icm.docker.utils.oracle.TaskPreparer as OraclePreparer -import com.intershop.gradle.icm.docker.utils.oracle.TaskPreparer as OracleTaskPreparer import com.intershop.gradle.icm.docker.utils.redis.TaskPreparer as RedisTaskPreparer import com.intershop.gradle.icm.docker.utils.solrcloud.TaskPreparer as SolrCloudPreparer import com.intershop.gradle.icm.docker.utils.solrcloud.TaskPreparer as SolrTaskPreparer @@ -80,7 +78,6 @@ open class ICMDockerPlugin : Plugin { val networkTasks = NetworkPreparer(project, extension) val mssqlTasks = MSSQLPreparer(project, networkTasks.createNetworkTask) - val oracleTasks = OraclePreparer(project, networkTasks.createNetworkTask) val mailSrvTask = MailSrvPreparer(project, networkTasks.createNetworkTask) val solrcloudPreparer = SolrCloudPreparer(project, networkTasks) @@ -91,7 +88,6 @@ open class ICMDockerPlugin : Plugin { try { tasks.named("dbPrepare").configure { it.mustRunAfter(mssqlTasks.startTask) - it.mustRunAfter(oracleTasks.startTask) } } catch (ex: UnknownTaskException) { project.logger.info("No dbPrepare task available!") @@ -106,7 +102,6 @@ open class ICMDockerPlugin : Plugin { mailSrvTask.removeTask, webServerTasks.removeTask, nginxTasks.removeTask, - oracleTasks.removeTask, solrcloudPreparer.removeTask, redisTasks.removeTask) } @@ -143,7 +138,7 @@ open class ICMDockerPlugin : Plugin { task.group = GROUP_CONTAINER task.description = "Start all container from Docker for the selected environment" if (list.contains("mail")) { - task.dependsOn("start${MailTaskPreparer.extName}") + task.dependsOn("start${MailTaskPreparer.EXT_NAME}") } if (list.contains("webserver")) { task.dependsOn("start${WebTaskPreparer.TASK_EXT_SERVER}") @@ -152,16 +147,13 @@ open class ICMDockerPlugin : Plugin { task.dependsOn("start${SolrTaskPreparer.TASK_EXT_SERVER}") } if (list.contains("mssql")) { - task.dependsOn("start${MSSQLTaskPreparer.extName}") - } - if (list.contains("oracle")) { - task.dependsOn("start${OracleTaskPreparer.extName}") + task.dependsOn("start${MSSQLTaskPreparer.EXT_NAME}") } if (list.contains("nginx")) { - task.dependsOn("start${NginxTaskPreparer.extName}") + task.dependsOn("start${NginxTaskPreparer.EXT_NAME}") } if (list.contains("redis")) { - task.dependsOn("start${RedisTaskPreparer.extName}") + task.dependsOn("start${RedisTaskPreparer.EXT_NAME}") } } @@ -169,7 +161,7 @@ open class ICMDockerPlugin : Plugin { task.group = GROUP_CONTAINER task.description = "Stops all container from Docker for the selected environment" if (list.contains("mail")) { - task.dependsOn("stop${MailTaskPreparer.extName}") + task.dependsOn("stop${MailTaskPreparer.EXT_NAME}") } if (list.contains("webserver")) { task.dependsOn("stop${WebTaskPreparer.TASK_EXT_SERVER}") @@ -178,16 +170,13 @@ open class ICMDockerPlugin : Plugin { task.dependsOn("stop${SolrTaskPreparer.TASK_EXT_SERVER}") } if (list.contains("mssql")) { - task.dependsOn("stop${MSSQLTaskPreparer.extName}") - } - if (list.contains("oracle")) { - task.dependsOn("stop${OracleTaskPreparer.extName}") + task.dependsOn("stop${MSSQLTaskPreparer.EXT_NAME}") } if (list.contains("nginx")) { - task.dependsOn("stop${NginxTaskPreparer.extName}") + task.dependsOn("stop${NginxTaskPreparer.EXT_NAME}") } if (list.contains("redis")) { - task.dependsOn("stop${RedisTaskPreparer.extName}") + task.dependsOn("stop${RedisTaskPreparer.EXT_NAME}") } } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerReadmePushPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerReadmePushPlugin.kt index 81f3e22..616a125 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerReadmePushPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMDockerReadmePushPlugin.kt @@ -19,7 +19,7 @@ package com.intershop.gradle.icm.docker import com.bmuschko.gradle.docker.tasks.container.DockerStartContainer import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension import com.intershop.gradle.icm.docker.extension.readme.push.ImageConfiguration -import com.intershop.gradle.icm.docker.tasks.PullExtraImage +import com.intershop.gradle.icm.docker.tasks.PullImage import com.intershop.gradle.icm.docker.tasks.readmepush.CreateToolContainer import com.intershop.gradle.icm.docker.tasks.readmepush.LogToolContainer import org.gradle.api.Plugin @@ -46,7 +46,7 @@ open class ICMDockerReadmePushPlugin : Plugin { IntershopDockerExtension::class.java ) ?: extensions.create("intershop_docker", IntershopDockerExtension::class.java, project) - val pullImg = project.tasks.register("pullReadmePush", PullExtraImage::class.java) { task -> + val pullImg = project.tasks.register("pullReadmePush", PullImage::class.java) { task -> task.group = "icm container readme push" task.description = "Pull image from registry for pushing readme" task.image.set(extension.readmePush.toolImage) @@ -80,11 +80,13 @@ open class ICMDockerReadmePushPlugin : Plugin { } } - private fun createContainerTask(project: Project, - ext: String, - baseImg: Property, - conf: ImageConfiguration, - pullTask: Provider): Provider = + private fun createContainerTask( + project: Project, + ext: String, + baseImg: Property, + conf: ImageConfiguration, + pullTask: Provider, + ): Provider = project.tasks.register("createReadmePush${ext}", CreateToolContainer::class.java) { task -> task.description = "Create image for pushing readme for $ext container" @@ -115,12 +117,12 @@ open class ICMDockerReadmePushPlugin : Plugin { task.onlyIf { val returnValue = conf.enabled.getOrElse(false) if (!returnValue) { - project.logger.quiet("Task {} skipped, because it is not enabled.") + project.logger.quiet("Task {} skipped, because it is not enabled.", it.name) } val runOnCICheck = project.hasProperty("runOnCI") && project.property("runOnCI") == "true" if (!runOnCICheck) { - project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.") + project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.", it.name) } runOnCICheck && returnValue } @@ -141,12 +143,12 @@ open class ICMDockerReadmePushPlugin : Plugin { task.onlyIf { val returnValue = conf.enabled.getOrElse(false) if(! returnValue) { - project.logger.quiet("Task {} skipped, because it is not enabled.") + project.logger.quiet("Task {} skipped, because it is not enabled.", it.name) } val runOnCICheck = project.hasProperty("runOnCI") && project.property("runOnCI") == "true" if (!runOnCICheck) { - project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.") + project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.", it.name) } runOnCICheck && returnValue } @@ -165,12 +167,12 @@ open class ICMDockerReadmePushPlugin : Plugin { task.onlyIf { val returnValue = conf.enabled.getOrElse(false) if (!returnValue) { - project.logger.quiet("Task {} skipped, because it is not enabled.") + project.logger.quiet("Task {} skipped, because it is not enabled.", it.name) } val runOnCICheck = project.hasProperty("runOnCI") && project.property("runOnCI") == "true" if (!runOnCICheck) { - project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.") + project.logger.quiet("Task {} skipped, because runOnCI is false or not configured.", it.name) } runOnCICheck && returnValue } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMGebTestPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMGebTestPlugin.kt index e0a181c..1e3c47c 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMGebTestPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMGebTestPlugin.kt @@ -27,8 +27,8 @@ import com.intershop.gradle.icm.docker.utils.Configuration import com.intershop.gradle.icm.docker.utils.Configuration.GEB_LOCAL_DRIVER import com.intershop.gradle.icm.docker.utils.Configuration.GEB_LOCAL_ENVIRONMENT import com.intershop.gradle.icm.docker.utils.OS -import com.intershop.gradle.icm.docker.utils.appsrv.ICMServerTaskPreparer -import com.intershop.gradle.icm.docker.utils.appsrv.ServerTaskPreparer +import com.intershop.gradle.icm.docker.utils.appsrv.ASTaskPreparer +import com.intershop.gradle.icm.docker.utils.appsrv.ASTestContainerTaskPreparer import com.intershop.gradle.icm.docker.utils.webserver.WATaskPreparer import com.intershop.gradle.icm.extension.IntershopExtension import org.gradle.api.Plugin @@ -156,7 +156,7 @@ class ICMGebTestPlugin : Plugin { val startTaskName = if (hasProperty(SRVSTARTTASK)) { property(SRVSTARTTASK).toString() } else { - "start${ServerTaskPreparer.extName}" + "start${ASTaskPreparer.extName}" } if (useLocalServer == true && !useBuildContainer) { @@ -167,7 +167,7 @@ class ICMGebTestPlugin : Plugin { } } else { val serverTaskName = if (useBuildContainer) { - "start${ICMServerTaskPreparer.extName}" + "start${ASTestContainerTaskPreparer.EXT_NAME}" } else { startTaskName } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMSolrCloudPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMSolrCloudPlugin.kt index af34c81..7ab3b20 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMSolrCloudPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMSolrCloudPlugin.kt @@ -30,7 +30,7 @@ import com.intershop.gradle.icm.docker.utils.Configuration.AS_ADMIN_USER_PASSWOR import com.intershop.gradle.icm.docker.utils.Configuration.SOLR_CLOUD_HOSTLIST import com.intershop.gradle.icm.docker.utils.Configuration.SOLR_CLOUD_INDEXPREFIX import com.intershop.gradle.icm.docker.utils.Configuration.SSL_VERIFICATION -import com.intershop.gradle.icm.docker.utils.appsrv.ServerTaskPreparer +import com.intershop.gradle.icm.docker.utils.appsrv.ASTaskPreparer import com.intershop.gradle.icm.docker.utils.webserver.WATaskPreparer import org.gradle.api.Plugin import org.gradle.api.Project @@ -63,7 +63,7 @@ class ICMSolrCloudPlugin : Plugin { StartExtraContainer::class.java ) val startASProvider = tasks.named( - "start${ServerTaskPreparer.extName}", + "start${ASTaskPreparer.extName}", StartServerContainer::class.java ) diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMTestDockerPlugin.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMTestDockerPlugin.kt index d97b245..4d8428c 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/ICMTestDockerPlugin.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/ICMTestDockerPlugin.kt @@ -44,7 +44,7 @@ class ICMTestDockerPlugin: Plugin { val createNetworkTask = project.tasks.named(TaskPreparer.PREPARE_NETWORK, PrepareNetwork::class.java) val mailSrvTask = tasks.named( - "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.extName}", + "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.EXT_NAME}", StartExtraContainer::class.java) diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/extension/DevelopmentConfiguration.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/extension/DevelopmentConfiguration.kt index d4178d9..6b4d651 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/extension/DevelopmentConfiguration.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/extension/DevelopmentConfiguration.kt @@ -210,15 +210,26 @@ open class DevelopmentConfiguration get() = File(configDirectory, CONFIG_FILE_NAME).absolutePath fun getConfigProperty(property: String): String { - return configProperties.getProperty(property, "") + return getConfigProperty(property, "") } fun getConfigProperty(property: String, defaultValue: String): String { - return configProperties.getProperty(property, defaultValue) + return getConfigProperty(property, defaultValue) { + it.isNullOrBlank() + } + } + + fun getConfigProperty(property: String, defaultValue: String, isEmpty: (String?) -> Boolean): String { + val value = configProperties.getProperty(property) + return if (isEmpty.invoke(value)) { + defaultValue + } else { + value + } } fun getIntProperty(property: String, defaultValue: Int): Int { - val strValue = configProperties.getProperty(property, defaultValue.toString()) + val strValue = getConfigProperty(property, defaultValue.toString()) try { return strValue.toInt() } catch (e: NumberFormatException) { @@ -228,7 +239,7 @@ open class DevelopmentConfiguration } fun getBooleanProperty(property: String, defaultValue: Boolean): Boolean { - val strValue = configProperties.getProperty(property, defaultValue.toString()) + val strValue = getConfigProperty(property, defaultValue.toString()) return strValue.toBoolean() } @@ -236,6 +247,11 @@ open class DevelopmentConfiguration return Duration.ofSeconds(getIntProperty (property, defaultSeconds).toLong()) } + fun getFileProperty(property: String, defaultValue: File): File { + val strValue = getConfigProperty(property, defaultValue.absolutePath) + return File(strValue) + } + /** * The database configuration (initialized lazily) */ diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/extension/Images.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/extension/Images.kt index 3099410..10dcd3f 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/extension/Images.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/extension/Images.kt @@ -37,6 +37,10 @@ open class Images @Inject constructor(objectFactory: ObjectFactory) { val mssqldb: Property = objectFactory.property(String::class.java) + @Deprecated( + message = "DB vendor Oracle unsupported since 5.0.0 and no longer used", + level = DeprecationLevel.WARNING + ) val oracledb: Property = objectFactory.property(String::class.java) val mailsrv: Property = objectFactory.property(String::class.java) @@ -56,7 +60,6 @@ open class Images @Inject constructor(objectFactory: ObjectFactory) { solr.convention("solr:latest") zookeeper.convention("zookeeper:latest") mssqldb.convention("intershophub/mssql-intershop:2019-latest") - oracledb.convention("intershophub/oracle-intershop:latest") mailsrv.convention("mailhog/mailhog:latest") diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractContainerTask.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractContainerTask.kt index 1943fdc..924e2e8 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractContainerTask.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractContainerTask.kt @@ -40,7 +40,8 @@ abstract class AbstractContainerTask : AbstractDockerRemoteApiTask() { fun executeUsing(startContainerTaskProvider: TaskProvider) { containerId.set(project.provider { startContainerTaskProvider.get().containerId.get() }) - containerNameProperty.set(project.provider { startContainerTaskProvider.get().containerName.get() }) + containerNameProperty.set( + project.provider { startContainerTaskProvider.get().container.get().getContainerName() }) dependsOn(startContainerTaskProvider) } @@ -51,7 +52,7 @@ abstract class AbstractContainerTask : AbstractDockerRemoteApiTask() { protected fun waitForExit(localExecId: String): Long { // create progressLogger for pretty printing of terminal log progression. - val progressLogger = IOUtils.getProgressLogger(project, this.javaClass) + val progressLogger = IOUtils.getProgressLogger(services, this.javaClass) progressLogger.started() // if no livenessProbe defined then create a default diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractPullImage.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractPullImage.kt index e2be26d..e00d3bf 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractPullImage.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/AbstractPullImage.kt @@ -68,11 +68,7 @@ abstract class AbstractPullImage @get:Option(option = "forcePull", description = "Call pull always also if the image is available.") @get:Input - val force: Property = objectFactory.property(Boolean::class.java) - - init { - force.set(false) - } + val force: Property = objectFactory.property(Boolean::class.java).convention(false) /** * Executes the remote Docker command. @@ -91,7 +87,7 @@ abstract class AbstractPullImage if(! force.get()) { val listImagesCmd = dockerClient.listImagesCmd() - listImagesCmd.filters["reference"] = listOf(image.get()) + listImagesCmd.filters?.set("reference", listOf(image.get())) val images = listImagesCmd.exec() pull = images.size < 1 } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/BuildImage.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/BuildImage.kt index da1e051..9084c17 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/BuildImage.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/BuildImage.kt @@ -202,7 +202,7 @@ open class BuildImage onlyIf { val returnValue = enabled.getOrElse(false) if(! returnValue) { - project.logger.quiet("Task {} skipped, because it is not enabled.") + project.logger.quiet("Task {} skipped, because it is not enabled.", it.name) } returnValue } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/ContainerHandle.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/ContainerHandle.kt new file mode 100644 index 0000000..d2a2ca1 --- /dev/null +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/ContainerHandle.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2020 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.tasks + +import com.github.dockerjava.api.model.Container +import org.gradle.api.provider.Provider + +interface ContainerHandle { + companion object { + fun of(container: Container): ContainerHandle { + return object : ContainerHandle { + override fun isRunning(): Boolean = container.state == "running" + override fun getContainerId(): String = container.id + override fun getContainerName(): String = container.names.first().removePrefix("/") + override fun getContainerImage(): String = container.image + override fun toString(): String { + return "Container '${getContainerName()}' with ID '${getContainerId()}'" + } + } + } + + fun notRunning(id: Provider, name: Provider, image: Provider): ContainerHandle { + + return object : ContainerHandle { + override fun isRunning(): Boolean = false + override fun getContainerId(): String = id.get() + override fun getContainerName(): String = name.get() + override fun getContainerImage(): String = image.get() + override fun toString(): String { + return "Container '${getContainerName()}' with ID '${getContainerId()}'" + } + } + } + + fun desired(name: Provider, image: Provider): ContainerHandle { + + return object : ContainerHandle { + override fun isRunning(): Boolean = false + override fun getContainerId(): String = + throw IllegalStateException("Desired containers to not have an id assigned") + + override fun getContainerName(): String = name.get() + override fun getContainerImage(): String = image.get() + override fun toString(): String { + return "Desired container '${getContainerName()}'" + } + } + } + } + + fun isRunning(): Boolean + + fun getContainerId(): String + + fun getContainerName(): String + + fun getContainerImage(): String + +} \ No newline at end of file diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateASContainer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateASContainer.kt new file mode 100644 index 0000000..d3cef76 --- /dev/null +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateASContainer.kt @@ -0,0 +1,217 @@ +/* + * Copyright 2020 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.tasks + +import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension +import com.intershop.gradle.icm.docker.tasks.utils.ClasspathLayout +import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder +import com.intershop.gradle.icm.docker.utils.Configuration +import com.intershop.gradle.icm.docker.utils.HostAndPort +import com.intershop.gradle.icm.tasks.CopyLibraries +import com.intershop.gradle.icm.utils.JavaDebugSupport +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.options.Option +import org.gradle.api.tasks.options.OptionValues +import org.gradle.kotlin.dsl.getByType + +import javax.inject.Inject + +abstract class CreateASContainer @Inject constructor(objectFactory: ObjectFactory) : + CreateExtraContainer(objectFactory) { + private val debugProperty: Property = + objectFactory.property(JavaDebugSupport::class.java).convention(JavaDebugSupport.defaults(project)) + private val gcLogProperty: Property = objectFactory.property(Boolean::class.java).convention(false) + private val heapDumpProperty: Property = objectFactory.property(Boolean::class.java).convention(false) + private val appserverNameProperty: Property = objectFactory.property(String::class.java).convention("") + private val classpathLayoutProperty: SetProperty = project.objects + .setProperty(ClasspathLayout::class.java) + .convention(ClasspathLayout.default()) + + companion object { + const val PATTERN_READINESS_PROBE_URL = "http://localhost:%d/status/ReadinessProbe" + } + + /** + * Enable debugging for the JVM running the ICM-AS inside the container. This option defaults to the value + * of the JVM property `SYSPROP_DEBUG_JVM` respectively `false` if not set. + * The port on the host can be configured using the property `icm.properties/intershop.as.debug.port` + * + * @property debug is the task property + * @see com.intershop.gradle.icm.docker.utils.Configuration.AS_DEBUG_PORT + */ + @set:Option( + option = "debug-icm", + description = """ + Enable/control debugging for the process. The following values are supported: + ${JavaDebugSupport.TASK_OPTION_VALUE_TRUE}/${JavaDebugSupport.TASK_OPTION_VALUE_YES} - enable debugging, + ${JavaDebugSupport.TASK_OPTION_VALUE_SUSPEND} - enable debugging in suspend-mode, + - disable debugging. + The debugging port is controlled by icm-property '${Configuration.AS_DEBUG_PORT}'. + """ + ) + @get:Input + var debug: String + get() = debugProperty.map { it.renderTaskOptionValue() }.getOrElse("") + set(value) { + val debugOptions = JavaDebugSupport.parse(project, value) + debugProperty.set(debugOptions) + withEnvironment( + project.provider { ICMContainerEnvironmentBuilder().withDebugOptions(debugOptions).build() }) + } + + /** + * Return the possible values for the task option [debug] + */ + @OptionValues("debug-icm") + fun getDebugOptionValues(): Collection = listOf(JavaDebugSupport.TASK_OPTION_VALUE_TRUE, + JavaDebugSupport.TASK_OPTION_VALUE_YES, + JavaDebugSupport.TASK_OPTION_VALUE_SUSPEND, + JavaDebugSupport.TASK_OPTION_VALUE_FALSE, + JavaDebugSupport.TASK_OPTION_VALUE_NO) + + /** + * Enable GC logging for the process. + * + * @property gcLog is the task property + */ + @set:Option( + option = "gclog", + description = "Enable gclog for the process." + ) + @get:Input + var gcLog: Boolean + get() = gcLogProperty.get() + set(value) { + gcLogProperty.set(value) + withEnvironment(project.provider { ICMContainerEnvironmentBuilder().enableGCLog(value).build() }) + } + + /** + * Enable heap dumps for the process. + * + * @property heapDump is the task property + */ + @set:Option( + option = "heapdump", + description = "Enable heapdump creation for the process." + ) + @get:Input + var heapDump: Boolean + get() = heapDumpProperty.get() + set(value) { + heapDumpProperty.set(value) + withEnvironment(project.provider { ICMContainerEnvironmentBuilder().enableHeapDump(value).build() }) + } + + /** + * Set a special name for the appserver + */ + @set:Option( + option = "appserver-name", + description = "Provide a special name for the appserver." + ) + @get:Input + var appserverName: String + get() = appserverNameProperty.get() + set(value) { + appserverNameProperty.set(value) + withEnvironment(project.provider { ICMContainerEnvironmentBuilder().withServerName(value).build() }) + } + + /** + * Provide a custom classpath layout. Default value is `sourceJar,release`. + * + * @property classpathLayout is the task property + */ + @set:Option( + option = "classpathLayout", + description = "Provide a custom classpath layout (comma separated list of " + + "{release,source,sourceJar,eclipse}, default value is 'sourceJar,release')." + ) + @get:Optional + @get:Input + var classpathLayout: String? + get() = ClasspathLayout.render(classpathLayoutProperty.get()) + set(value) { + classpathLayoutProperty.set(ClasspathLayout.parse(value)) + withEnvironment(project.provider { + ICMContainerEnvironmentBuilder().withClasspathLayout(classpathLayoutProperty.get()).build() + }) + } + + /** + * Provide the host list of the Zookeeper required by Solr Cloud + */ + fun withSolrCloudZookeeperHostList(solrCloudZookeeperHostList: Provider) { + withEnvironment(project.provider { + ICMContainerEnvironmentBuilder().withSolrCloudZookeeperHostList(solrCloudZookeeperHostList).build() + }) + } + + /** + * Provide the mail host+port + */ + fun withMailServer(hostAndPort: Provider) { + withEnvironment(project.provider { ICMContainerEnvironmentBuilder().withMailServer(hostAndPort).build() }) + } + + init { + val devConfig = project.extensions.getByType().developmentConfig + withEnvironment( + project.provider { + ICMContainerEnvironmentBuilder() + .withContainerName(containerName.get()) + .withDatabaseConfig(devConfig.databaseConfiguration) + .withDevelopmentConfig(devConfig.developmentProperties) + .withEnvironmentProperties(devConfig.intershopEnvironmentProperties) + .withEnvironment(devConfig.asEnvironment) + .withWebserverConfig(devConfig.webserverConfiguration) + .withPortConfig(devConfig.asPortConfiguration) + .withCartridgeList(devConfig.cartridgeList.get()) + .withClasspathLayout(classpathLayoutProperty.get()) + .build() + } + ) + } + + fun forCustomization(containerPrefix: String) { + // if there are customizations add some more volumes + withVolumes( + // build a volumes-Provider that + // 1. adds a task dependency: CreateASContainer -> each CopyLibraries + // 2. adds a volume CopyLibraries-directory -> `-libs/lib` + project.provider { + val customizationVolumes = mutableMapOf() + project.tasks.withType(CopyLibraries::class.java) { cl -> + // ensure `CopyLibraries`-tasks get executed prior to this task + dependsOn(cl) + + // "add" the volume + val dir = cl.librariesDirectory.get().asFile + customizationVolumes[dir.absolutePath] = + "/intershop/customizations/${containerPrefix}-${dir.name}-libs/lib" + } + customizationVolumes + } + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateExtraContainer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateExtraContainer.kt new file mode 100644 index 0000000..d277666 --- /dev/null +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/CreateExtraContainer.kt @@ -0,0 +1,132 @@ +/* + * Copyright 2020 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.tasks + +import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment +import com.intershop.gradle.icm.docker.utils.PortMapping +import org.gradle.api.GradleException +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.Optional +import javax.inject.Inject + +abstract class CreateExtraContainer +@Inject constructor(objectFactory: ObjectFactory) : DockerCreateContainer(objectFactory) { + + private val portMappings: MapProperty = + objectFactory.mapProperty(String::class.java, PortMapping::class.java) + + @get:Input + @get:Optional + val existingContainer: Property = objectFactory.property(ContainerHandle::class.java) + + @get:Internal + val createdContainer: Property = + objectFactory.property(ContainerHandle::class.java).convention(project.provider { + // if container does not exist yet, just use a desired-ContainerHandle + if (existingContainer.isPresent) { + existingContainer.get() + } else { + ContainerHandle.desired(containerName, image) + } + }) + + /** + * Returns a [Provider] that provides the primary port mapping if there is such a port mapping otherwise + * [Provider.get] will fail + */ + @Internal + fun getPrimaryPortMapping(): Provider = project.provider { + this.portMappings.get().values.firstOrNull { mapping -> mapping.primary } + } + + /** + * Returns all port mappings + */ + @Internal + fun getPortMappings(): Set = + this.portMappings.get().values.toSet() + + /** + * Adds port mappings to be used with the container + */ + fun withPortMappings(vararg portMappings: PortMapping) { + portMappings.forEach { currPortMapping -> + // check if there's already a primary port mapping + if (currPortMapping.primary && getPrimaryPortMapping().isPresent) { + throw GradleException("Duplicate primary port mapping detected for task $name") + } + + this.portMappings.put(currPortMapping.name, currPortMapping) + hostConfig.portBindings.add(project.provider { currPortMapping.render() }) + } + } + + /** + * Same as [CreateExtraContainer.withEnvironment(Provider)] but using a [Provider] + */ + fun withEnvironment(environment: ContainerEnvironment) { + withEnvironment(project.provider { environment }) + } + + /** + * Applies the given `environment` to this task's [DockerCreateContainer.envVars] (using [MapProperty.putAll]). + */ + fun withEnvironment(environment: Provider) { + envVars.putAll( + project.provider { // use a provider around environment.get() to defer the execution until actual usage + environment.get().toMap() + }) + } + + fun withVolumes(volumes: Map) { + withVolumes(project.provider { volumes }) + } + + fun withVolumes(volumes: Provider>) { + this.hostConfig.binds.putAll(volumes) + } + + init { + @Suppress("LeakingThis") + onlyIf("Container does not exist") { + val containerExists = existingContainer.isPresent + if (containerExists) { + project.logger.quiet("{} still exists, skipping creation", existingContainer.get()) + } + !containerExists + } + } + + override fun runRemoteCommand() { + if (existingContainer.isPresent) { + throw GradleException("Expecting ${existingContainer.get()} to not currently exist but it does.") + } + + logger.info("Creating container '{}' using the following port mappings: {}", + containerName.get(), getPortMappings()) + logger.info("Creating container '{}' using volumes: {}", + containerName.get(), volumes.get()) + super.runRemoteCommand() + createdContainer.set(ContainerHandle.notRunning(containerId, containerName, image)) + } +} diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/FindContainer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/FindContainer.kt new file mode 100644 index 0000000..03647f9 --- /dev/null +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/FindContainer.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2020 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.tasks + +import com.bmuschko.gradle.docker.tasks.AbstractDockerRemoteApiTask +import com.github.dockerjava.api.model.Container +import org.gradle.api.GradleException +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.Optional + +abstract class FindContainer : AbstractDockerRemoteApiTask() { + + @get:Input + val containerName: Property = project.objects.property(String::class.java) + + @get:Optional + @get:Input + val expectedImage: Property = project.objects.property(String::class.java) + + @get:Internal + val foundContainer: Property = project.objects.property(ContainerHandle::class.java) + + /** + * Checks if the container exists + * @return `true` if the container exists + */ + fun containerExists(): Boolean = foundContainer.isPresent + + @Internal + fun getContainer(): ContainerHandle = foundContainer.get() + + override fun runRemoteCommand() { + foundContainer.set(null as ContainerHandle?) + + val containers: MutableList = + dockerClient.listContainersCmd().withShowAll(true).withNameFilter(listOf("/${containerName.get()}")) + .exec() + + for (c in containers) { + if (c.names.contains("/${containerName.get()}")) { + if (expectedImage.isPresent && c.image != expectedImage.get()) { + throw GradleException( + "The running container was started with image '${c.image}', but the configured image is " + + "'${expectedImage.get()}'. Please remove running containers!") + } + foundContainer.set(ContainerHandle.of(c)) + + break + } + } + + if (foundContainer.isPresent) { + project.logger.quiet("Container '{}' exists using id={} ({})", containerName.get(), + getContainer().getContainerId(), if (getContainer().isRunning()) { + "RUNNING" + } else { + "NOT RUNNING" + }) + } else { + project.logger.quiet("Container '{}' does not exist", containerName.get()) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/GenICMProperties.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/GenICMProperties.kt index 05d41e7..a2de65b 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/GenICMProperties.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/GenICMProperties.kt @@ -35,7 +35,6 @@ import java.net.UnknownHostException import javax.inject.Inject import com.intershop.gradle.icm.docker.utils.mail.TaskPreparer as MailTaskPreparer import com.intershop.gradle.icm.docker.utils.mssql.TaskPreparer as MSSQLTaskPreparer -import com.intershop.gradle.icm.docker.utils.oracle.TaskPreparer as OracleTaskPreparer open class GenICMProperties @Inject constructor( objectFactory: ObjectFactory, @@ -125,8 +124,6 @@ open class GenICMProperties @Inject constructor( @get:Option(option = "db", description = """Option for the used database. The following values are possible: - oracle-container - Oracle configuration for database provided by a container - oracle - Oracle configuration for an external database mssql-container - MSSQL configuration for database provided by a container mssql - MSSQL configuration for an external database """) @@ -161,8 +158,6 @@ open class GenICMProperties @Inject constructor( val db = dbOption.get() when { - db.startsWith("oracle-c") -> writeOracleProps(outputFile, true) - db == "oracle" -> writeOracleProps(outputFile, false) db.startsWith("mssql-c") -> writeMSSQLProps(outputFile, true) db == "mssql" -> writeMSSQLProps(outputFile, false) else -> project.logger.quiet("No database option is specified!") @@ -179,7 +174,6 @@ open class GenICMProperties @Inject constructor( addTo(envListTasks, "mail", optList.contains("mail")) addTo(envListTasks, "solr", optList.contains("solr")) - addTo(envListTasks, "oracle", db.startsWith("oracle-c")) addTo(envListTasks, "mssql", db.startsWith("mssql-c")) addTo(envListTasks, "webserver", true) @@ -227,67 +221,6 @@ open class GenICMProperties @Inject constructor( file.appendText("\n\n", Charsets.UTF_8) } - private fun writeOracleProps(file: File, container: Boolean) { - val icmas = icmasOption.get() - - val host = if (icmas) { - if (container) { - "localhost" - } else { - "" - } - } else { - if (container) { - "${extension.containerPrefix}-${OracleTaskPreparer.extName.lowercase()}" - } else { - "" - } - } - val port = if (icmas) { - if (container) { - Configuration.DB_ORACLE_LISTENERPORT_VALUE - } else { - "" - } - } else { - if (container) { - Configuration.DB_ORACLE_CONTAINER_LISTENERPORT_VALUE - } else { - "" - } - } - - val sid = if (container) { - "XE" - } else { - "" - } - - val text = - """ - # oracle base configuration - $databaseTypeProp = oracle - $databaseJDBCUrlProp = jdbc:oracle:thin:@$host:$port:$sid - """.trimIndent() - - file.appendText(text, Charsets.UTF_8) - file.appendText("\n", Charsets.UTF_8) - writeDBUserConfig(file, container) - - if (container) { - val ctext = - """ - # mssql container configuration - do not change this value if the default images is used - ${Configuration.DB_ORACLE_LISTENERPORT} = ${Configuration.DB_ORACLE_LISTENERPORT_VALUE} - ${Configuration.DB_ORACLE_CONTAINER_LISTENERPORT} = ${Configuration.DB_ORACLE_CONTAINER_LISTENERPORT_VALUE} - ${Configuration.DB_ORACLE_PORT} = ${Configuration.DB_ORACLE_PORT_VALUE} - ${Configuration.DB_ORACLE_CONTAINER_PORT} = ${Configuration.DB_ORACLE_CONTAINER_PORT_VALUE} - """.trimIndent() - file.appendText(ctext, Charsets.UTF_8) - file.appendText("\n\n", Charsets.UTF_8) - } - } - private fun writeMSSQLProps(file: File, container: Boolean) { val icmas = icmasOption.get() @@ -299,7 +232,7 @@ open class GenICMProperties @Inject constructor( } } else { if (container) { - "${extension.containerPrefix}-${MSSQLTaskPreparer.extName.lowercase()}" + "${extension.containerPrefix}-${MSSQLTaskPreparer.EXT_NAME.lowercase()}" } else { "" } @@ -455,7 +388,7 @@ open class GenICMProperties @Inject constructor( } } else { if (container) { - "${extension.containerPrefix}-${MailTaskPreparer.extName.lowercase()}" + "${extension.containerPrefix}-${MailTaskPreparer.EXT_NAME.lowercase()}" } else { "" } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartExtraContainer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartExtraContainer.kt index 52c2408..a529ab0 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartExtraContainer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartExtraContainer.kt @@ -19,20 +19,16 @@ package com.intershop.gradle.icm.docker.tasks import com.bmuschko.gradle.docker.domain.ExecProbe import com.bmuschko.gradle.docker.internal.IOUtils -import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer -import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment +import com.bmuschko.gradle.docker.tasks.container.DockerStartContainer import com.intershop.gradle.icm.docker.tasks.utils.ContainerLogWatcher import com.intershop.gradle.icm.docker.tasks.utils.LogContainerCallback -import com.intershop.gradle.icm.docker.utils.PortMapping import com.intershop.gradle.icm.utils.HttpProbe import com.intershop.gradle.icm.utils.Probe import com.intershop.gradle.icm.utils.SocketProbe import org.gradle.api.GradleException import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional @@ -43,69 +39,22 @@ import javax.inject.Inject import kotlin.concurrent.thread open class StartExtraContainer -@Inject constructor(objectFactory: ObjectFactory) : DockerCreateContainer(objectFactory) { - - private val finishedCheckProperty: Property = objectFactory.property(String::class.java) - private val timeoutProperty: Property = objectFactory.property(Long::class.java) - private val portMappings: MapProperty = - objectFactory.mapProperty(String::class.java, PortMapping::class.java) +@Inject constructor(objectFactory: ObjectFactory) : DockerStartContainer() { /** - * Set an string for log file check. Log is displayed as long + * Set a string for log file check. Log is displayed as long * the string was not part of the output. */ @get:Optional @get:Input - var finishedCheck: String - get() = finishedCheckProperty.get() - set(value) = finishedCheckProperty.set(value) + val finishedCheck: Property = objectFactory.property(String::class.java) /** - * Milliseconds for waiting on the finish string. - * Default is 600000. + * Max duration for the container to start up (only evaluated if [finishedCheck] is set) */ @get:Input - var timeout: Long - get() = timeoutProperty.get() - set(value) = timeoutProperty.set(value) - - /** - * Returns a [Provider] that provides the primary port mapping if there is such a port mapping otherwise - * [Provider.get] will fail - */ - @Internal - fun getPrimaryPortMapping(): Provider = project.provider { - this.portMappings.get().values.firstOrNull { mapping -> mapping.primary } - } - - /** - * Returns all port mappings - */ - @Internal - fun getPortMappings(): Set = - this.portMappings.get().values.toSet() - - /** - * Adds port mappings to be used with the container - */ - fun withPortMappings(vararg portMappings: PortMapping) { - portMappings.forEach { currPortMapping -> - // check if there's already a primary port mapping - if (currPortMapping.primary && getPrimaryPortMapping().isPresent) { - throw GradleException("Duplicate primary port mapping detected for task $name") - } - - this.portMappings.put(currPortMapping.name, currPortMapping) - hostConfig.portBindings.add(project.provider { currPortMapping.render() }) - } - } - - /** - * Applies the given `environment` to this task's [DockerCreateContainer.envVars] (using [MapProperty.putAll]) - */ - fun withEnvironment(environment: ContainerEnvironment) { - envVars.putAll(environment.toMap()) - } + val startupTimeout: Property = + objectFactory.property(Duration::class.java).convention(Duration.ofSeconds(900)) @get:Input val probes: ListProperty = project.objects.listProperty(Probe::class.java) @@ -136,95 +85,83 @@ open class StartExtraContainer @get:Input val enableLogWatcher: Property = objectFactory.property(Boolean::class.java).convention(false) + @get:Input + val container: Property = project.objects.property(ContainerHandle::class.java) + init { - finishedCheckProperty.convention("") - timeoutProperty.convention(900000) + containerId.convention(project.provider { + if (container.isPresent) { + container.get().getContainerId() + } else { + null + } + }) + @Suppress("LeakingThis") + onlyIf("Container not running") { + val containerRuns = isAlreadyRunning() + if (containerRuns) { + project.logger.quiet("{} still is running, skipping to start it", container.get()) + } + !containerRuns + } } override fun runRemoteCommand() { - var containerCreated = false - var containerRunning = false - - val iterator = - dockerClient.listContainersCmd().withShowAll(true).withNameFilter(listOf("/${containerName.get()}")) - .exec().iterator() - - while (iterator.hasNext()) { - val container = iterator.next() - if (container.names.contains("/${containerName.get()}")) { - if (container.image != image.get()) { - throw GradleException( - "The running container was started with image '" + container.image + - "', but the configured image is '" + image.get() + - "'. Please remove running containers!" - ) - } - - containerId.set(container.id) - containerCreated = true - containerRunning = (container.state == "running") - } + if (isAlreadyRunning()) { + throw GradleException("Expecting ${container.get()} to not currently run but it does.") } - if (!containerRunning) { - if (!containerCreated) { - super.runRemoteCommand() - } else { - logger.quiet("Container '{}' still exists.", containerName.get()) - } - - logger.info("Starting container '{}' with ID '{}' using the following port mappings: {}.", - containerName.get(), containerId.get(), getPortMappings()) - logger.info("Starting container '{}' with ID '{}' using volumes: {}", - containerName.get(), containerId.get(), volumes.get()) + logger.quiet("Starting {}.", container.get()) - val startCommand = dockerClient.startContainerCmd(containerId.get()) - startCommand.exec() + val startCommand = dockerClient.startContainerCmd(containerId.get()) + startCommand.exec() - val logWatcherHandle: AutoCloseable? = if (enableLogWatcher.get()) { - ContainerLogWatcher(project, dockerClient).start(containerId.get()) - } else { - null - } + val logWatcherHandle: AutoCloseable? = if (enableLogWatcher.get()) { + ContainerLogWatcher(project, dockerClient).start(containerId.get()) + } else { + null + } - try { - with(probes.get()) { - forEach { probe -> - val success = probe.execute() - if (!success) { - throw GradleException( - "Container '${containerName.get()}' failed to start properly probe $probe failed") - } - project.logger.debug("Probe '{}' was executed successfully on container '{}'.", - probe, containerName.get()) + try { + with(probes.get()) { + forEach { probe -> + val success = probe.execute() + if (!success) { + throw GradleException( + "Container ${container.get()} failed to start properly: probe $probe failed") } - project.logger.quiet("Container '{}' started properly.", containerName.get()) + project.logger.debug("Probe '{}' was executed successfully on {}.", + probe, container.get()) } + project.logger.quiet("{} started properly.", container.get()) + } - // TODO remove when all containers use probes - if (finishedCheckProperty.get().isNotBlank()) { - try { - Thread.sleep(5000) - } catch (e: Exception) { - throw e - } - - waitForLogout() + // TODO remove when all containers use probes + if (finishedCheck.isPresent) { + try { + Thread.sleep(5000) + } catch (e: Exception) { + throw e } - } catch (e: Exception) { - onFailure(e) - } finally { - logWatcherHandle?.close() - } - } else { - logger.quiet("Container '{}' is still running.", containerName.get()) + waitForLogout() + } + } catch (e: Exception) { + onFailure(e) + } finally { + logWatcherHandle?.close() } } + @Internal + protected fun getContainerName(): String? = container.map { c -> c.getContainerName() }.orNull + + @Internal + protected fun isAlreadyRunning(): Boolean = container.map { c -> c.isRunning() }.getOrElse(false) + protected fun waitForLogout() { - if (finishedCheckProperty.isPresent && finishedCheckProperty.get().isNotEmpty()) { + if (finishedCheck.isPresent && finishedCheck.get().isNotEmpty()) { logger.quiet("Starting logging for container with ID '${containerId.get()}'.") val logCommand = dockerClient.logContainerCmd(containerId.get()) logCommand.withStdErr(true) @@ -232,16 +169,16 @@ open class StartExtraContainer logCommand.withTailAll() logCommand.withFollowStream(true) - val localProbe = ExecProbe(timeoutProperty.get(), 5000) + val localProbe = ExecProbe(startupTimeout.get().toMillis(), 5000) // create progressLogger for pretty printing of terminal log progression. - val progressLogger = IOUtils.getProgressLogger(project, this.javaClass) + val progressLogger = IOUtils.getProgressLogger(services, this.javaClass) try { var localPollTime = localProbe.pollTime var pollTimes = 0 progressLogger.started() - val containerCallback = LogContainerCallback(project.logger, finishedCheckProperty.get()) + val containerCallback = LogContainerCallback(project.logger, finishedCheck.get()) thread(start = true) { try { @@ -283,8 +220,8 @@ open class StartExtraContainer } protected fun onFailure(cause: Exception) { - project.logger.quiet("Stopping failed container '{}'", containerName.get()) - dockerClient.stopContainerCmd(containerId.get()).exec() + project.logger.quiet("Stopping failed {}", container.get()) + dockerClient.stopContainerCmd(container.get().getContainerId()).exec() throw cause } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/PullExtraImage.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartMailServerContainer.kt similarity index 50% rename from src/main/kotlin/com/intershop/gradle/icm/docker/tasks/PullExtraImage.kt rename to src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartMailServerContainer.kt index f9e2e8e..65a037a 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/PullExtraImage.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartMailServerContainer.kt @@ -1,30 +1,39 @@ -/* - * Copyright 2020 Intershop Communications AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.intershop.gradle.icm.docker.tasks - -import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import javax.inject.Inject - -open class PullExtraImage - @Inject constructor(objectFactory: ObjectFactory) : AbstractPullImage(objectFactory) { - - @get:Input - override val image: Property = objectFactory.property(String::class.java) -} +/* + * Copyright 2020 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.tasks + +import com.intershop.gradle.icm.docker.utils.HostAndPort +import com.intershop.gradle.icm.docker.utils.PortMapping +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Internal +import javax.inject.Inject + +abstract class StartMailServerContainer @Inject constructor(objectFactory: ObjectFactory) : + StartExtraContainer(objectFactory) { + private val primaryPortMapping: Property = objectFactory.property(PortMapping::class.java) + + fun withPrimaryPortMapping(portMapping: Provider) { + primaryPortMapping.set(portMapping) + } + + @Internal + fun getPrimaryHostAndPort(): HostAndPort { + return HostAndPort(container.get().getContainerName(), primaryPortMapping.get().containerPort) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartServerContainer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartServerContainer.kt index a489f2e..2aa06a7 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartServerContainer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/StartServerContainer.kt @@ -17,192 +17,14 @@ package com.intershop.gradle.icm.docker.tasks -import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension -import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder -import com.intershop.gradle.icm.docker.tasks.utils.ClasspathLayout -import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.HostAndPort -import com.intershop.gradle.icm.utils.JavaDebugSupport -import com.intershop.gradle.icm.utils.JavaDebugSupport.Companion.TASK_OPTION_VALUE_SUSPEND -import com.intershop.gradle.icm.utils.JavaDebugSupport.Companion.TASK_OPTION_VALUE_TRUE -import com.intershop.gradle.icm.utils.JavaDebugSupport.Companion.TASK_OPTION_VALUE_YES import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider -import org.gradle.api.provider.SetProperty -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.options.Option -import org.gradle.api.tasks.options.OptionValues -import org.gradle.kotlin.dsl.getByType import javax.inject.Inject open class StartServerContainer @Inject constructor(objectFactory: ObjectFactory) : StartExtraContainer(objectFactory) { - private val debugProperty: Property = objectFactory.property(JavaDebugSupport::class.java) - private val gcLogProperty: Property = objectFactory.property(Boolean::class.java) - private val heapDumpProperty: Property = objectFactory.property(Boolean::class.java) - private val appserverNameProperty: Property = objectFactory.property(String::class.java) - private val solrCloudZookeeperHostListProperty: Property = objectFactory.property(String::class.java) - private val mailServerProperty: Property = objectFactory.property(HostAndPort::class.java) - private val classpathLayoutProperty: SetProperty = project.objects - .setProperty(ClasspathLayout::class.java) - .convention(ClasspathLayout.default()) - - companion object { - const val PATTERN_READINESS_PROBE_URL = "http://localhost:%d/status/ReadinessProbe" - } - - /** - * Enable debugging for the JVM running the ICM-AS inside the container. This option defaults to the value - * of the JVM property [SYSPROP_DEBUG_JVM] respectively `false` if not set. - * The port on the host can be configured using the property `icm.properties/intershop.as.debug.port` - * - * @property debug is the task property - * @see com.intershop.gradle.icm.docker.utils.Configuration.AS_DEBUG_PORT - */ - @set:Option( - option = "debug-icm", - description = """ - Enable/control debugging for the process. The following values are supported: - $TASK_OPTION_VALUE_TRUE/$TASK_OPTION_VALUE_YES - enable debugging, - $TASK_OPTION_VALUE_SUSPEND - enable debugging in suspend-mode, - - disable debugging. - The debugging port is controlled by icm-property '${Configuration.AS_DEBUG_PORT}'. - """ - ) - @get:Input - var debug: String - get() = debugProperty.map { it.renderTaskOptionValue() }.getOrElse("") - set(value) { - val debugOptions = JavaDebugSupport.parse(project, value) - debugProperty.set(debugOptions) - withEnvironment(ICMContainerEnvironmentBuilder().withDebugOptions(debugOptions).build()) - } - - /** - * Return the possible values for the task option [debug] - */ - @OptionValues("debug-icm") - fun getDebugOptionValues(): Collection = listOf(TASK_OPTION_VALUE_TRUE, - TASK_OPTION_VALUE_YES, - TASK_OPTION_VALUE_SUSPEND, - JavaDebugSupport.TASK_OPTION_VALUE_FALSE, - JavaDebugSupport.TASK_OPTION_VALUE_NO) - - /** - * Enable GC logging for the process. - * - * @property gcLog is the task property - */ - @set:Option( - option = "gclog", - description = "Enable gclog for the process." - ) - @get:Input - var gcLog: Boolean - get() = gcLogProperty.get() - set(value) { - gcLogProperty.set(value) - withEnvironment(ICMContainerEnvironmentBuilder().enableGCLog(value).build()) - } - - /** - * Enable heap dumps for the process. - * - * @property heapDump is the task property - */ - @set:Option( - option = "heapdump", - description = "Enable heapdump creation for the process." - ) - @get:Input - var heapDump: Boolean - get() = heapDumpProperty.get() - set(value) { - heapDumpProperty.set(value) - withEnvironment(ICMContainerEnvironmentBuilder().enableHeapDump(value).build()) - } - - /** - * Set a special name for the appserver - */ - @set:Option( - option = "appserver-name", - description = "Provide a special name for the appserver." - ) - @get:Input - var appserverName: String - get() = appserverNameProperty.get() - set(value) { - appserverNameProperty.set(value) - withEnvironment(ICMContainerEnvironmentBuilder().withServerName(value).build()) - } - - /** - * Provide the host list of the Zookeeper required by Solr Cloud - */ - @get:Optional - @get:Input - var solrCloudZookeeperHostList : Provider - get() = solrCloudZookeeperHostListProperty - set(value) { - solrCloudZookeeperHostListProperty.set(value) - withEnvironment(ICMContainerEnvironmentBuilder().withSolrCloudZookeeperHostList(value).build()) - } - - /** - * Provide the smtp host - */ - @get:Optional - @get:Input - var mailServer : Provider - get() = mailServerProperty - set(value) { - mailServerProperty.set(value) - withEnvironment(ICMContainerEnvironmentBuilder().withMailServer(value).build()) - } - - /** - * Provide a custom classpath layout. Default value is `sourceJar,release`. - * - * @property classpathLayout is the task property - */ - @set:Option( - option = "classpathLayout", - description = "Provide a custom classpath layout (comma separated list of " + - "{release,source,sourceJar,eclipse}, default value is 'sourceJar,release')." - ) - @get:Optional - @get:Input - var classpathLayout: String? - get() = ClasspathLayout.render(classpathLayoutProperty.get()) - set(value) { - classpathLayoutProperty.set(ClasspathLayout.parse(value)) - withEnvironment(ICMContainerEnvironmentBuilder().withClasspathLayout(classpathLayoutProperty.get()).build()) - } - init { - debugProperty.convention(JavaDebugSupport.defaults(project)) - gcLogProperty.convention(false) - heapDumpProperty.convention(false) - appserverNameProperty.convention("") enableLogWatcher.convention(true) - - val devConfig = project.extensions.getByType().developmentConfig - withEnvironment( - ICMContainerEnvironmentBuilder() - .withDatabaseConfig(devConfig.databaseConfiguration) - .withDevelopmentConfig(devConfig.developmentProperties) - .withEnvironmentProperties(devConfig.intershopEnvironmentProperties) - .withEnvironment(devConfig.asEnvironment) - .withWebserverConfig(devConfig.webserverConfiguration) - .withPortConfig(devConfig.asPortConfiguration) - .withCartridgeList(devConfig.cartridgeList.get()) - .withClasspathLayout(classpathLayoutProperty.get()) - .build() - ) } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/WaitForServer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/WaitForServer.kt index a57f830..8e38f91 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/WaitForServer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/WaitForServer.kt @@ -21,13 +21,13 @@ import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty -import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import javax.inject.Inject open class WaitForServer @Inject constructor(objectFactory: ObjectFactory) : DefaultTask() { - @get:Input + @get:Internal val probes: ListProperty = objectFactory.listProperty(Probe::class.java) @TaskAction diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ContainerEnvironment.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ContainerEnvironment.kt index 0ac7f8d..b7d2610 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ContainerEnvironment.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ContainerEnvironment.kt @@ -18,7 +18,6 @@ package com.intershop.gradle.icm.docker.tasks.utils import org.gradle.api.provider.Provider import java.io.Serializable -import java.lang.IllegalStateException /** * Encapsulates environment variables to be used when starting a container. If [Provider]s are added they are stored @@ -48,6 +47,24 @@ open class ContainerEnvironment : Serializable { return this } + + /** + * Just calls [ContainerEnvironment.add] with `key=Pair.first` and `value=Pair.second` + */ + fun add(entry: Pair): ContainerEnvironment { + return add(entry.first, entry.second) + } + + /** + * Adds multiply environment variables calling [ContainerEnvironment.add] for each + */ + fun addAll(vararg entries: Pair): ContainerEnvironment { + entries.forEach { + add(it) + } + return this + } + fun toList(): List { return toMap().map { entry -> "${entry.key}=${entry.value}" }.toList() } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ICMContainerEnvironmentBuilder.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ICMContainerEnvironmentBuilder.kt index 72fbc7a..1e86f55 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ICMContainerEnvironmentBuilder.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/ICMContainerEnvironmentBuilder.kt @@ -54,6 +54,7 @@ class ICMContainerEnvironmentBuilder { const val ENV_ENABLE_HEAPDUMP = "ENABLE_HEAPDUMP" const val ENV_ENABLE_GCLOG = "ENABLE_GCLOG" const val ENV_MAIL = "ISH_ENV_MAIL" + const val ENV_SOLR_CLUSTERINDEXPREFIX = "SOLR_CLUSTERINDEXPREFIX" const val PROP_MAIL_HOST = "mail.smtp.host" const val PROP_MAIL_PORT = "mail.smtp.port" } @@ -72,6 +73,7 @@ class ICMContainerEnvironmentBuilder { private var enableHeapDump: Boolean? = null private var enableGCLog: Boolean? = null private var solrCloudTZookeeperHostList : Provider? = null + private var solrClusterIndexPrefix: Provider? = null private var mailServer : Provider? = null private var developmentProperties: DevelopmentProperties? = null private var intershopEnvironmentProperties: EnvironmentProperties? = null @@ -147,6 +149,11 @@ class ICMContainerEnvironmentBuilder { return this } + fun withSolrClusterIndexPrefix(solrClusterIndexPrefix: Provider): ICMContainerEnvironmentBuilder { + this.solrClusterIndexPrefix = solrClusterIndexPrefix + return this + } + fun withMailServer(mailServer : Provider) : ICMContainerEnvironmentBuilder { this.mailServer = mailServer return this @@ -235,6 +242,11 @@ class ICMContainerEnvironmentBuilder { env.add(ContainerEnvironment.propertyNameToEnvName(Configuration.SOLR_CLOUD_HOSTLIST), this) } } + solrClusterIndexPrefix?.run { + if (isPresent) { + env.add(ENV_SOLR_CLUSTERINDEXPREFIX, this) + } + } mailServer?.run { if (isPresent) { val value : HostAndPort = get() diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/TaskAuthLocatorHelper.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/TaskAuthLocatorHelper.kt index 9da10da..0726564 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/TaskAuthLocatorHelper.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/tasks/utils/TaskAuthLocatorHelper.kt @@ -18,19 +18,18 @@ package com.intershop.gradle.icm.docker.tasks.utils import com.bmuschko.gradle.docker.internal.RegistryAuthLocator import org.gradle.api.Project -import java.io.File object TaskAuthLocatorHelper { fun getLocator(project: Project, registryAuthLocator: RegistryAuthLocator) : RegistryAuthLocator { var regAuthLocator = registryAuthLocator - if (project.findProperty("icm.docker.config") != null) { - val configFilePath = project.property("icm.docker.config").toString() - val configFile = File(File(configFilePath), "config.json") - regAuthLocator = RegistryAuthLocator(configFile) - project.logger.info("This docker configuration is used: '{}'", configFile.absolutePath) - } +// if (project.findProperty("icm.docker.config") != null) { +// val configFilePath = project.property("icm.docker.config").toString() +// val configFile = File(File(configFilePath), "config.json") +// regAuthLocator = RegistryAuthLocator(configFile) +// project.logger.info("This docker configuration is used: '{}'", configFile.absolutePath) +// } return regAuthLocator } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/AbstractTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/AbstractTaskPreparer.kt index be4063e..ce2b62e 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/AbstractTaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/AbstractTaskPreparer.kt @@ -17,14 +17,16 @@ package com.intershop.gradle.icm.docker.utils -import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension import com.intershop.gradle.icm.docker.tasks.AbstractPullImage +import com.intershop.gradle.icm.docker.tasks.CreateExtraContainer +import com.intershop.gradle.icm.docker.tasks.FindContainer import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.PullExtraImage +import com.intershop.gradle.icm.docker.tasks.PullImage import com.intershop.gradle.icm.docker.tasks.RemoveContainerByName import com.intershop.gradle.icm.docker.tasks.StartExtraContainer import com.intershop.gradle.icm.docker.tasks.StopExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.extension.IntershopExtension import org.gradle.api.Project import org.gradle.api.provider.Property @@ -33,10 +35,11 @@ import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.getByType import org.gradle.nativeplatform.platform.OperatingSystem import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform +import java.io.File abstract class AbstractTaskPreparer( protected val project: Project, - networkTask: Provider, + private val networkTask: Provider, ) { protected abstract fun getExtensionName(): String @@ -50,63 +53,157 @@ abstract class AbstractTaskPreparer( protected val dockerExtension = project.extensions.getByType() protected val icmExtension = project.extensions.getByType() + protected val devConfig = dockerExtension.developmentConfig fun getContainerName(): String = "${dockerExtension.containerPrefix}-${getContainerExt()}" + protected fun taskNameOf(operation: String): String = operation + getExtensionName() + + protected val taskGroup: String by lazy { "icm container ${getTaskGroupExt()}" } + protected open fun getTaskGroupExt(): String = getContainerExt() + protected fun initBaseTasks() { - project.tasks.register("pull${getExtensionName()}", PullExtraImage::class.java) { task -> - task.group = "icm container ${getContainerExt()}" + project.tasks.register(taskNameOf("pull"), PullImage::class.java) { task -> + task.group = taskGroup task.description = "Pull image from registry" task.image.set(getImage()) } - project.tasks.register("stop${getExtensionName()}", StopExtraContainer::class.java) { task -> - task.group = "icm container ${getContainerExt()}" + project.tasks.register(taskNameOf("stop"), StopExtraContainer::class.java) { task -> + task.group = taskGroup task.description = "Stop running container" task.containerName.set(getContainerName()) } - project.tasks.register("remove${getExtensionName()}", RemoveContainerByName::class.java) { task -> - task.group = "icm container ${getContainerExt()}" + project.tasks.register(taskNameOf("remove"), RemoveContainerByName::class.java) { task -> + task.group = taskGroup task.description = "Remove container from Docker" task.containerName.set(getContainerName()) } + + project.tasks.register(taskNameOf("find"), FindContainer::class.java) { task -> + task.group = taskGroup + task.description = "Finds the ${getContainerExt()}-container to check if it exists and is running" + task.dependsOn(pullTask) + task.containerName.set(getContainerName()) + task.expectedImage.set(project.provider { pullTask.get().image.get() }) + } } val pullTask: TaskProvider by lazy { - project.tasks.named("pull${getExtensionName()}", AbstractPullImage::class.java) + project.tasks.named(taskNameOf("pull"), AbstractPullImage::class.java) } val stopTask: TaskProvider by lazy { - project.tasks.named("stop${getExtensionName()}", StopExtraContainer::class.java) + project.tasks.named(taskNameOf("stop"), StopExtraContainer::class.java) } val removeTask: TaskProvider by lazy { - project.tasks.named("remove${getExtensionName()}", RemoveContainerByName::class.java) + project.tasks.named(taskNameOf("remove"), RemoveContainerByName::class.java) + } + + val findTask: TaskProvider by lazy { + project.tasks.named(taskNameOf("find"), FindContainer::class.java) + } + + val createTask: TaskProvider by lazy { + project.tasks.named(taskNameOf("create"), CreateExtraContainer::class.java) } val startTask: TaskProvider by lazy { - project.tasks.named("start${getExtensionName()}", StartExtraContainer::class.java) + project.tasks.named(taskNameOf("start"), StartExtraContainer::class.java) } protected val networkId: Property = networkTask.get().networkId - protected fun configureContainerTask(task: DockerCreateContainer) { - task.group = "icm container ${getContainerExt()}" - task.attachStderr.set(true) - task.attachStdout.set(true) - task.hostConfig.autoRemove.set(true) - - task.containerName.set(getContainerName()) - - val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() - if(useHostUser() && !os.isWindows) { - val system = com.sun.security.auth.module.UnixSystem() - val uid = system.uid - val userName = system.username - val gid = system.gid - project.logger.info("Using user {}({}:{}) to start container {}", userName, uid, gid, getContainerName()) - task.user.set(uid.toString()) + /** + * Same as [registerCreateContainerTask] using `taskType == CreateExtraContainer`. `volumes` and `env` are wrapped into [Provider]s. + */ + protected fun registerCreateContainerTask( + findTask: TaskProvider, volumes: Map, + env: ContainerEnvironment, + ): TaskProvider { + return registerCreateContainerTask(findTask, CreateExtraContainer::class.java, project.provider { volumes }, + project.provider { env }) + } + + /** + * Registers the task that creates the container + * @param findTask a [TaskProvider] pointing to the [FindContainer]-task + * @param taskType the actual task type to be created + * @param volumes a [Provider] for the volumes to be bound. Local directories are created on demand. + * @param env a [Provider] for the container environment to be used + * @return a [TaskProvider] pointing to the registered task + */ + protected fun registerCreateContainerTask( + findTask: TaskProvider, taskType: Class, + volumes: Provider>, + env: Provider, + ): TaskProvider where T : CreateExtraContainer { + return project.tasks.register(taskNameOf("create"), taskType) { task -> + task.group = taskGroup + task.description = "Creates the ${getContainerExt()}-container is not already existing" + task.attachStderr.set(true) + task.attachStdout.set(true) + task.hostConfig.autoRemove.set(true) + + task.targetImageId(project.provider { pullTask.get().image.get() }) + task.image.set(project.provider { pullTask.get().image.get() }) + + task.hostConfig.network.set(networkId) + task.withEnvironment(env) + + task.dependsOn(findTask, networkTask) + task.existingContainer.set(project.provider { findTask.get().foundContainer.orNull }) + task.containerName.set(getContainerName()) + + val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() + if (useHostUser() && !os.isWindows) { + val system = com.sun.security.auth.module.UnixSystem() + val uid = system.uid + val userName = system.username + val gid = system.gid + project.logger.info("Using user {}({}:{}) to start container {}", userName, uid, gid, + getContainerName()) + task.user.set(uid.toString()) + } + + task.withVolumes(volumes) + + task.doFirst { + volumes.get().forEach { (path, _) -> File(path).mkdirs() } + } + } + } + + /** + * Same as [registerStartContainerTask] using `taskType == StartExtraContainer`. + */ + protected fun registerStartContainerTask( + createTask: TaskProvider, + ): TaskProvider { + return registerStartContainerTask(createTask, StartExtraContainer::class.java) + } + + /** + * Registers the task that starts the container + * @param createTask a [TaskProvider] pointing to the [CreateExtraContainer]-task + * @param taskType the actual task type to be created + * @return a [TaskProvider] pointing to the registered task + */ + protected fun registerStartContainerTask( + createTask: TaskProvider, + taskType: Class, + ): TaskProvider where T : StartExtraContainer { + return project.tasks.register(taskNameOf("start"), taskType) { task -> + task.group = taskGroup + task.description = "Starts the ${getContainerExt()}-container if not already running" + + + task.dependsOn(createTask, networkTask) + task.container.set(project.provider { + createTask.get().createdContainer.orNull + }) } } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/Configuration.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/Configuration.kt index f2705d8..baa481a 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/Configuration.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/Configuration.kt @@ -41,20 +41,6 @@ object Configuration { const val DB_MSSQL_USE_HOST_USER = "intershop.db.mssql.useHostUser" - const val DB_ORACLE_LISTENERPORT = "intershop.db.oracle.listenerport" - const val DB_ORACLE_CONTAINER_LISTENERPORT = "intershop.db.container.oracle.listenerport" - - const val DB_ORACLE_PORT = "intershop.db.oracle.port" - const val DB_ORACLE_CONTAINER_PORT = "intershop.db.container.oracle.port" - - const val DB_ORACLE_LISTENERPORT_VALUE = "1521" - const val DB_ORACLE_CONTAINER_LISTENERPORT_VALUE = "1521" - - const val DB_ORACLE_PORT_VALUE = "5500" - const val DB_ORACLE_CONTAINER_PORT_VALUE = "5500" - - const val DB_ORACLE_USE_HOST_USER = "intershop.db.oracle.useHostUser" - const val DB_TYPE = "intershop.databaseType" const val DB_JDBC_URL = "intershop.jdbc.url" diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ServerTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTaskPreparer.kt similarity index 72% rename from src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ServerTaskPreparer.kt rename to src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTaskPreparer.kt index 1f798be..4f4a496 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ServerTaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTaskPreparer.kt @@ -16,42 +16,60 @@ */ package com.intershop.gradle.icm.docker.utils.appsrv -import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension +import com.intershop.gradle.icm.docker.tasks.CreateASContainer import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer import com.intershop.gradle.icm.docker.tasks.StartServerContainer -import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.HostAndPort -import com.intershop.gradle.icm.docker.utils.solrcloud.ZKPreparer import org.gradle.api.Project -import org.gradle.api.UnknownTaskException import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.getByType import java.net.URI -class ServerTaskPreparer( - project: Project, - val networkTask: Provider) : AbstractASTaskPreparer(project, networkTask) { +class ASTaskPreparer( + project: Project, + val networkTask: Provider, +) : AbstractASTaskPreparer(project, networkTask) { companion object { const val extName: String = "AS" } - override fun getImage(): Provider { - if(dockerExtension.developmentConfig.getConfigProperty( - Configuration.AS_USE_TESTIMAGE, - Configuration.AS_USE_TESTIMAGE_VALUE - ).toBoolean()) { - return icmExtension.projectConfig.base.testImage - } - return icmExtension.projectConfig.base.image - } - override fun getExtensionName(): String = extName init { - project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> + val volumes = project.provider { getServerVolumes() } + + val createTask = registerCreateASContainerTask(findTask, volumes) + createTask.configure { task -> + task.withPortMappings(*getPortMappings().toTypedArray()) + task.forCustomization(dockerExtension.containerPrefix) + } + + registerStartContainerTask(createTask, StartServerContainer::class.java).configure { task -> + task.description = """ + Starts Production Application Server in a container. + ATTENTION: task ${ + taskNameOf("create") + } is executed in preparation of this task and supports parameters that you may expect to get supported by this task. + """.trimIndent() + task.withHttpProbe( + URI.create( + CreateASContainer.PATTERN_READINESS_PROBE_URL.format( + devConfig.asPortConfiguration.managementConnector.get().hostPort + ) + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_INTERVAL, + Configuration.AS_READINESS_PROBE_INTERVAL_VALUE + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_TIMEOUT, + Configuration.AS_READINESS_PROBE_TIMEOUT_VALUE + ) + ) + } + + /* FIXME SKR project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> + configureContainerTask(task) task.description = "Starts Production Application Server in a container" @@ -130,19 +148,9 @@ class ServerTaskPreparer( HostAndPort(mailHost, mailPort.toInt()) } } - } - } - private val zkTaskProvider: Provider? by lazy { - try { - project.tasks.named( - "start${ZKPreparer.extName}", - StartExtraContainer::class.java - ) - } catch (ex: UnknownTaskException) { - project.logger.info("ZooKeeper tasks not found") - null - } + + }*/ } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTestContainerTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTestContainerTaskPreparer.kt new file mode 100644 index 0000000..51a9b52 --- /dev/null +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ASTestContainerTaskPreparer.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2022 Intershop Communications AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.intershop.gradle.icm.docker.utils.appsrv + +import com.intershop.gradle.icm.docker.ICMDockerPlugin +import com.intershop.gradle.icm.docker.tasks.BuildImage +import com.intershop.gradle.icm.docker.tasks.CreateASContainer +import com.intershop.gradle.icm.docker.tasks.PrepareNetwork +import com.intershop.gradle.icm.docker.tasks.StartServerContainer +import com.intershop.gradle.icm.docker.utils.Configuration +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import java.net.URI + + +class ASTestContainerTaskPreparer( + project: Project, + val networkTask: Provider, +) : AbstractASTaskPreparer(project, networkTask) { + + companion object { + const val EXT_NAME: String = "AsTestContainer" + } + + override fun getExtensionName(): String = EXT_NAME + + /** + * Calculates the image from the output of the task [ICMDockerPlugin.BUILD_TEST_IMAGE] + */ + override fun getImage(): Provider { + val buildTestImageTask = project.tasks.named(ICMDockerPlugin.BUILD_TEST_IMAGE, BuildImage::class.java) + val imageProvider = project.provider { buildTestImageTask.get().images.get() } + return imageProvider.map { it.first() } + } + + init { + val volumes = project.provider { getServerVolumes() } + + val createTask = registerCreateASContainerTask(findTask, volumes) + createTask.configure { task -> + task.withPortMappings(*getPortMappings().toTypedArray()) + } + + registerStartContainerTask(createTask, StartServerContainer::class.java).configure { task -> + task.description = """ + Starts Production Application Server in a container - only for use in icm-as. + ATTENTION: task ${ + taskNameOf("create") + } is executed in preparation of this task and supports parameters that you may expect to get supported by this task. + """.trimIndent() + task.withHttpProbe( + URI.create( + CreateASContainer.PATTERN_READINESS_PROBE_URL.format( + devConfig.asPortConfiguration.managementConnector.get().hostPort + ) + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_INTERVAL, + Configuration.AS_READINESS_PROBE_INTERVAL_VALUE + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_TIMEOUT, + Configuration.AS_READINESS_PROBE_TIMEOUT_VALUE + ) + ) + + } + + + /* FIXME SKR project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> + + configureContainerTask(task) + + task.description = "Starts Production Application Server in a container - only for use in icm-as" + + task.targetImageId(project.provider { pullTask.get().image.get() }) + task.image.set(pullTask.get().image) + + task.hostConfig.binds.set(project.provider { + getServerVolumes(task, false).apply { + project.logger.info( + "Using the following volume binds for container startup in task {}: {}", + task.name, this + ) + } + }) + + task.withPortMappings(*getPortMappings().toTypedArray()) + + task.hostConfig.network.set(networkId) + task.withEnvironment( + ICMContainerEnvironmentBuilder() + .withContainerName(getContainerName()) + .build() + ) + + val devConfig = project.extensions.getByType().developmentConfig + task.withHttpProbe( + URI.create( + StartServerContainer.PATTERN_READINESS_PROBE_URL.format( + devConfig.asPortConfiguration.managementConnector.get().hostPort + ) + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_INTERVAL, + Configuration.AS_READINESS_PROBE_INTERVAL_VALUE + ), + devConfig.getDurationProperty( + Configuration.AS_READINESS_PROBE_TIMEOUT, + Configuration.AS_READINESS_PROBE_TIMEOUT_VALUE + ) + ) + + val mailPort = devConfig.getConfigProperty(Configuration.MAIL_SMTP_PORT) + val mailHost = devConfig.getConfigProperty(Configuration.MAIL_SMTP_HOST) + + if(mailServerTaskProvider != null && mailPort.isEmpty() && mailHost.isEmpty()) { + task.mailServer = project.provider { + HostAndPort( + mailServerTaskProvider!!.get().containerName.get(), + mailServerTaskProvider!!.get().getPrimaryPortMapping().get().containerPort + ) + } + } else if (mailPort.isNotEmpty() && mailHost.isNotEmpty()){ + task.mailServer = project.provider { + HostAndPort(mailHost, mailPort.toInt()) + } + } + + + } */ + } +} diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/AbstractASTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/AbstractASTaskPreparer.kt index 8282445..217ba57 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/AbstractASTaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/AbstractASTaskPreparer.kt @@ -16,16 +16,18 @@ */ package com.intershop.gradle.icm.docker.utils.appsrv +import com.intershop.gradle.icm.docker.tasks.CreateASContainer +import com.intershop.gradle.icm.docker.tasks.CreateExtraContainer +import com.intershop.gradle.icm.docker.tasks.FindContainer import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.PullImage -import com.intershop.gradle.icm.docker.tasks.RemoveContainerByName -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer -import com.intershop.gradle.icm.docker.tasks.StopExtraContainer +import com.intershop.gradle.icm.docker.tasks.StartMailServerContainer +import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration +import com.intershop.gradle.icm.docker.utils.HostAndPort import com.intershop.gradle.icm.docker.utils.OS import com.intershop.gradle.icm.docker.utils.PortMapping -import com.intershop.gradle.icm.tasks.CopyLibraries +import com.intershop.gradle.icm.docker.utils.solrcloud.ZKPreparer import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.Task @@ -37,11 +39,25 @@ import java.io.File import java.util.concurrent.TimeUnit abstract class AbstractASTaskPreparer( - project: Project, - networkTask: Provider) : AbstractTaskPreparer(project, networkTask) { + project: Project, + networkTask: Provider, +) : AbstractTaskPreparer(project, networkTask) { init { - initAppTasks() + initBaseTasks() + } + + /** + * Calculates the image from [com.intershop.gradle.icm.docker.extension.DevelopmentConfiguration], property [Configuration.AS_USE_TESTIMAGE] + */ + override fun getImage(): Provider { + if (dockerExtension.developmentConfig.getConfigProperty( + Configuration.AS_USE_TESTIMAGE, + Configuration.AS_USE_TESTIMAGE_VALUE + ).toBoolean()) { + return icmExtension.projectConfig.base.testImage + } + return icmExtension.projectConfig.base.image } override fun getUseHostUserConfigProperty(): String = Configuration.AS_USE_HOST_USER @@ -49,26 +65,6 @@ abstract class AbstractASTaskPreparer( val prepareServer: TaskProvider by lazy { project.tasks.named(TaskPreparer.TASK_PREPARESERVER) } - private fun initAppTasks() { - project.tasks.register("pull${getExtensionName()}", PullImage::class.java) { task -> - task.group = "icm container ${getContainerExt()}" - task.description = "Pull image from registry" - task.image.set(getImage()) - } - - project.tasks.register("stop${getExtensionName()}", StopExtraContainer::class.java) { task -> - task.group = "icm container ${getContainerExt()}" - task.description = "Stop running container" - task.containerName.set(getContainerName()) - } - - project.tasks.register("remove${getExtensionName()}", RemoveContainerByName::class.java) { task -> - task.group = "icm container ${getContainerExt()}" - task.description = "Remove container from Docker" - - task.containerName.set(getContainerName()) - } - } /** * Determines the port mappings using @@ -79,13 +75,71 @@ abstract class AbstractASTaskPreparer( setOf( serviceConnector.get(), managementConnector.get(), debug.get(), jmx.get() ) } - protected fun getServerVolumes(task: Task, customization: Boolean): Map { - addDirectories.forEach { (_, path) -> - path.get().asFile.mkdirs() - } + /** + * Registers the task that creates application server the container + * @param findTask a [TaskProvider] pointing to the [FindContainer]-task + * @param volumes a [Provider] for the volumes to be bound. Local directories are created on demand. + * @param forCustomization if `true` the created container will take customizations into account + * @return a [TaskProvider] pointing to the registered task + * @see registerCreateContainerTask + */ + protected fun registerCreateASContainerTask( + findTask: TaskProvider, + volumes: Provider>, + ): TaskProvider { + val env = project.provider { ICMContainerEnvironmentBuilder().withContainerName(getContainerName()).build() } + val createTask = super.registerCreateContainerTask(findTask, CreateASContainer::class.java, volumes, env) + createTask.configure { task -> + task.doFirst { + addDirectories.forEach { (_, path) -> + path.get().asFile.mkdirs() + } + + prepareSitesFolder() + } - prepareSitesFolder() + // ensure AS knows connection to mail server + val mailPort = devConfig.getConfigProperty(Configuration.MAIL_SMTP_PORT) + val mailHost = devConfig.getConfigProperty(Configuration.MAIL_SMTP_HOST) + if (mailServerTaskProvider != null && mailPort.isEmpty() && mailHost.isEmpty()) { + // either: take host+port form MailSrv-container + task.withMailServer(project.provider { + mailServerTaskProvider!!.get().getPrimaryHostAndPort() + }) + } else if (mailPort.isNotEmpty() && mailHost.isNotEmpty()) { + // or: use configuration values + task.withMailServer(project.provider { + HostAndPort(mailHost, mailPort.toInt()) + }) + } + + // ensure AS knows connection to Solr/ZK + val solrCloudHostList = devConfig.getConfigProperty(Configuration.SOLR_CLOUD_HOSTLIST) + val solrCloudIndexPrefix = devConfig.getConfigProperty(Configuration.SOLR_CLOUD_INDEXPREFIX) + + if (zkTaskProvider != null && solrCloudHostList.isEmpty()) { + task.withSolrCloudZookeeperHostList(project.provider { + val containerPort = zkTaskProvider!!.get().getPortMappings().stream() + .filter { it.name == ZKPreparer.CONTAINER_PORTMAPPING } + .findFirst().get().containerPort + "${zkTaskProvider!!.get().containerName.get()}:${containerPort}" + }) + } else if (solrCloudHostList.isNotEmpty()) { + task.withSolrCloudZookeeperHostList(project.provider { + solrCloudHostList + }) + + if (solrCloudIndexPrefix.isNotEmpty()) { + task.withEnvironment(ICMContainerEnvironmentBuilder().withSolrClusterIndexPrefix( + project.provider { solrCloudIndexPrefix }).build()) + } + } + } + return createTask + } + + protected fun getServerVolumes(): Map { val default = project.layout.buildDirectory.dir("sites_folder").get().asFile.absolutePath val sitesFolderPath = dockerExtension.developmentConfig.getConfigProperty( Configuration.SITES_FOLDER_PATH, @@ -111,36 +165,9 @@ abstract class AbstractASTaskPreparer( "${dockerExtension.containerPrefix}-customizations" to "/intershop/customizations" ) - - if(customization) { - project.tasks.withType(CopyLibraries::class.java) { - task.dependsOn(it) - - val dir = it.librariesDirectory.get().asFile - volumes[dir.absolutePath] = - "/intershop/customizations/${dockerExtension.containerPrefix}-${dir.name}-libs/lib" - } - } return volumes } - private fun getOutputPathFor(taskName: String, path: String): String { - return if(path.isNotEmpty()) { - File(getOutputDirFor(taskName), path).absolutePath - } else { - getOutputDirFor(taskName).absolutePath - } - } - - private fun getOutputDirFor(taskName: String): File { - try { - val task = project.tasks.named(taskName) - return task.get().outputs.files.first() - } catch (ex: UnknownTaskException) { - throw GradleException("Task name '${taskName}' not found in project.") - } - } - private val addDirectories: Map> by lazy { mapOf( TaskPreparer.SERVERLOGS to project.layout.buildDirectory.dir(TaskPreparer.SERVERLOGS_PATH), @@ -217,14 +244,26 @@ abstract class AbstractASTaskPreparer( } } - val mailServerTaskProvider: Provider? by lazy { + private val mailServerTaskProvider: Provider? by lazy { + try { + project.tasks.named( + "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.EXT_NAME}", + StartMailServerContainer::class.java + ) + } catch (ex: UnknownTaskException) { + project.logger.warn("MailSrv task not found") + null + } + } + + private val zkTaskProvider: Provider? by lazy { try { project.tasks.named( - "start${com.intershop.gradle.icm.docker.utils.mail.TaskPreparer.extName}", - StartExtraContainer::class.java + "create${ZKPreparer.EXT_NAME}", + CreateExtraContainer::class.java ) } catch (ex: UnknownTaskException) { - project.logger.info("MailSrv tasks not found") + project.logger.info("ZooKeeper tasks not found") null } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/CustomizationPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/CustomizationPreparer.kt index a3bd9bd..070b342 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/CustomizationPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/CustomizationPreparer.kt @@ -17,7 +17,7 @@ package com.intershop.gradle.icm.docker.utils.appsrv import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import org.gradle.api.Project import org.gradle.api.provider.Provider @@ -28,10 +28,10 @@ class CustomizationPreparer(project: Project, private val imagePath: Provider) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extPrefix: String = "Customization" + const val EXT_PREFIX: String = "Customization" } - override fun getExtensionName(): String = "${customizationName}$extPrefix" + override fun getExtensionName(): String = "${customizationName}$EXT_PREFIX" override fun getImage(): Provider = imagePath override fun getUseHostUserConfigProperty(): String = getExtensionName()+".useHostUser" @@ -39,7 +39,17 @@ class CustomizationPreparer(project: Project, init { initBaseTasks() - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> + val volumes = mapOf("${dockerExtension.containerPrefix}-customizations" to "/customizations") + val env = ContainerEnvironment() // empty + + val createTask = registerCreateContainerTask(findTask, volumes, env) + registerStartContainerTask(createTask).configure { task -> + task.description = "Starts customization '${customizationName}'" + } + + + /* FIXME SKR project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> + configureContainerTask(task) task.description = "Starts customization '${customizationName}'" @@ -53,6 +63,8 @@ class CustomizationPreparer(project: Project, ) task.dependsOn(pullTask, networkTask) - } + + + }*/ } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ICMServerTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ICMServerTaskPreparer.kt deleted file mode 100644 index c693f9f..0000000 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ICMServerTaskPreparer.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2022 Intershop Communications AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.intershop.gradle.icm.docker.utils.appsrv - -import com.intershop.gradle.icm.docker.ICMDockerPlugin -import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension -import com.intershop.gradle.icm.docker.tasks.BuildImage -import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartServerContainer -import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder -import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.HostAndPort -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.getByType -import java.net.URI - - -class ICMServerTaskPreparer( - project: Project, - val networkTask: Provider) : AbstractASTaskPreparer(project, networkTask) { - - companion object { - const val extName: String = "AsTestContainer" - } - - override fun getExtensionName(): String = extName - - override fun getImage(): Provider { - val buildTestImageTask = project.tasks.named(ICMDockerPlugin.BUILD_TEST_IMAGE, BuildImage::class.java) - val imageProvider = project.provider { buildTestImageTask.get().images.get() } - return imageProvider.map { it.first() } - } - - init{ - project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> - configureContainerTask(task) - - task.description = "Starts Production Application Server in a container - only for use in icm-as" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - task.hostConfig.binds.set(project.provider { - getServerVolumes(task, false).apply { - project.logger.info( - "Using the following volume binds for container startup in task {}: {}", - task.name, this - ) - } - }) - - task.withPortMappings(*getPortMappings().toTypedArray()) - - task.hostConfig.network.set(networkId) - task.withEnvironment( - ICMContainerEnvironmentBuilder() - .withContainerName(getContainerName()) - .build() - ) - - val devConfig = project.extensions.getByType().developmentConfig - task.withHttpProbe( - URI.create( - StartServerContainer.PATTERN_READINESS_PROBE_URL.format( - devConfig.asPortConfiguration.managementConnector.get().hostPort - ) - ), - devConfig.getDurationProperty( - Configuration.AS_READINESS_PROBE_INTERVAL, - Configuration.AS_READINESS_PROBE_INTERVAL_VALUE - ), - devConfig.getDurationProperty( - Configuration.AS_READINESS_PROBE_TIMEOUT, - Configuration.AS_READINESS_PROBE_TIMEOUT_VALUE - ) - ) - - val mailPort = devConfig.getConfigProperty(Configuration.MAIL_SMTP_PORT) - val mailHost = devConfig.getConfigProperty(Configuration.MAIL_SMTP_HOST) - - if(mailServerTaskProvider != null && mailPort.isEmpty() && mailHost.isEmpty()) { - task.mailServer = project.provider { - HostAndPort( - mailServerTaskProvider!!.get().containerName.get(), - mailServerTaskProvider!!.get().getPrimaryPortMapping().get().containerPort - ) - } - } else if (mailPort.isNotEmpty() && mailHost.isNotEmpty()){ - task.mailServer = project.provider { - HostAndPort(mailHost, mailPort.toInt()) - } - } - } - } -} diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/TaskPreparer.kt index 33b2998..27b863a 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/TaskPreparer.kt @@ -79,14 +79,14 @@ class TaskPreparer (val project: Project, private val networkTask: Provider + startCustomization.dependsOn(createVolumes) } customizationStartTasks.add(cp.startTask) customizationRemoveTasks.add(cp.removeTask) } - containerTaskPreparer = ContainerTaskPreparer(project, networkTask) + containerTaskPreparer = WaitingAsTaskPreparer(project, networkTask) containerTaskPreparer.startTask.configure { it.dependsOn( project.tasks.named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME), // ensure all jars are built @@ -107,7 +107,7 @@ class TaskPreparer (val project: Project, private val networkTask: Provider + startCustomization.dependsOn(createVolumes) } customizationStartTasks.add(cp.startTask) customizationRemoveTasks.add(cp.removeTask) } - icmServerTaskPreparer = ICMServerTaskPreparer(project, networkTask) + icmServerTaskPreparer = ASTestContainerTaskPreparer(project, networkTask) icmServerTaskPreparer.startTask.configure { it.dependsOn( project.tasks.named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME), // ensure all jars are built @@ -99,7 +99,7 @@ class TestTaskPreparer (val project: Project, private val networkTask: Provider< fun getICMServerTaskPreparer() = icmServerTaskPreparer private fun configureASTasks(task: Task, description: String) { - task.group = "icm container appserver " + task.group = "icm container appserver" task.description = description } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ContainerTaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/WaitingAsTaskPreparer.kt similarity index 77% rename from src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ContainerTaskPreparer.kt rename to src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/WaitingAsTaskPreparer.kt index 1548de7..6b4be46 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/ContainerTaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/appsrv/WaitingAsTaskPreparer.kt @@ -16,26 +16,19 @@ */ package com.intershop.gradle.icm.docker.utils.appsrv -import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer import com.intershop.gradle.icm.docker.tasks.StartServerContainer -import com.intershop.gradle.icm.docker.tasks.utils.ICMContainerEnvironmentBuilder import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.HostAndPort -import com.intershop.gradle.icm.docker.utils.solrcloud.ZKPreparer import org.gradle.api.Project -import org.gradle.api.UnknownTaskException import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.getByType -class ContainerTaskPreparer( - project: Project, - networkTask: Provider +class WaitingAsTaskPreparer( + project: Project, + networkTask: Provider, ) : AbstractASTaskPreparer(project, networkTask) { companion object { - const val extName: String = "Container" + const val EXT_NAME: String = "WaitingAs" } override fun getImage(): Provider { @@ -48,11 +41,30 @@ class ContainerTaskPreparer( return icmExtension.projectConfig.base.image } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME init { - project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> - configureContainerTask(task) + val volumes = project.provider { getServerVolumes() } + + val createTask = registerCreateASContainerTask(findTask, volumes) + createTask.configure { task -> + task.withPortMappings(*getPortMappings().toTypedArray()) + task.forCustomization(dockerExtension.containerPrefix) + task.entrypoint.set(listOf("/intershop/bin/startAndWait.sh")) + } + + registerStartContainerTask(createTask, StartServerContainer::class.java).configure { task -> + task.description = """ + Starts a container without any special command (wait/sleep) + ATTENTION: task ${ + taskNameOf("create") + } is executed in preparation of this task and supports parameters that you may expect to get supported by this task. + """.trimIndent() + } + + + /* FIXME SKR project.tasks.register("start${this.getExtensionName()}", StartServerContainer::class.java) { task -> + configureContainerTask(task) task.description = "Start container without any special command (sleep)" @@ -110,18 +122,7 @@ class ContainerTaskPreparer( } } - } + }*/ } - private val zkTaskProvider: Provider? by lazy { - try { - project.tasks.named( - "start${ZKPreparer.extName}", - StartExtraContainer::class.java - ) - } catch (ex: UnknownTaskException) { - project.logger.info("ZooKeeper tasks not found") - null - } - } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mail/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mail/TaskPreparer.kt index 7e7fe4f..228d1a8 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mail/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mail/TaskPreparer.kt @@ -16,58 +16,57 @@ */ package com.intershop.gradle.icm.docker.utils.mail -import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.StartMailServerContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration import org.gradle.api.Project import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.getByType + class TaskPreparer(project: Project, networkTask: Provider) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extName: String = "MailSrv" + const val EXT_NAME: String = "MailSrv" const val SMTP_CONTAINER_PORT = 1025 const val ADMIN_CONTAINER_PORT = 8025 } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.mailsrv override fun getUseHostUserConfigProperty(): String = Configuration.MAIL_USE_HOST_USER init { initBaseTasks() - project.tasks.register ("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.description = "Starts an local mail server for testing" - - task.targetImageId( project.provider { pullTask.get().image.get() } ) - task.image.set(pullTask.get().image) + val mailOutputDir = project.layout.buildDirectory.dir("mailoutput").get().asFile - task.envVars.set(mutableMapOf( - "MH_STORAGE" to "maildir", - "MH_MAILDIR_PATH" to "/maildir")) + val volumes = mapOf(mailOutputDir.absolutePath to "/maildir") + val env = ContainerEnvironment().addAll("MH_STORAGE" to "maildir", "MH_MAILDIR_PATH" to "/maildir") + val devConfig = dockerExtension.developmentConfig + val smtpPortMapping = devConfig.getPortMapping( + "SMTP", + Configuration.MAIL_SMTP_HOST_PORT, + Configuration.MAIL_SMTP_HOST_PORT_VALUE, + SMTP_CONTAINER_PORT, + true + ) + val adminPortMapping = devConfig.getPortMapping( + "ADMIN", + Configuration.MAIL_ADMIN_HOST_PORT, + Configuration.MAIL_ADMIN_HOST_PORT_VALUE, + ADMIN_CONTAINER_PORT, + false + ) - val devConfig = project.extensions.getByType().developmentConfig - val smtpPortMapping = devConfig.getPortMapping( - "SMTP", - Configuration.MAIL_SMTP_HOST_PORT, - Configuration.MAIL_SMTP_HOST_PORT_VALUE, - SMTP_CONTAINER_PORT, - true - ) - val adminPortMapping = devConfig.getPortMapping( - "ADMIN", - Configuration.MAIL_ADMIN_HOST_PORT, - Configuration.MAIL_ADMIN_HOST_PORT_VALUE, - ADMIN_CONTAINER_PORT, - false - ) + val createTask = registerCreateContainerTask(findTask, volumes, env) + createTask.configure { task -> task.withPortMappings(smtpPortMapping, adminPortMapping) + } + + registerStartContainerTask(createTask, StartMailServerContainer::class.java).configure { task -> task.withSocketProbe( smtpPortMapping.hostPort, devConfig.getDurationProperty( @@ -79,23 +78,7 @@ class TaskPreparer(project: Project, Configuration.MAIL_READINESS_PROBE_TIMEOUT_VALUE ) ) - - if(! project.layout.buildDirectory.dir("mailoutput").get().asFile.exists()) { - project.layout.buildDirectory.dir("mailoutput").get().asFile.mkdir() - } - - task.hostConfig.binds.set( project.provider { - mutableMapOf( - project.layout.buildDirectory.dir("mailoutput").get().asFile.absolutePath - to "/maildir" - ) - }) - - task.hostConfig.network.set(networkId) - - task.dependsOn(pullTask, networkTask) + task.withPrimaryPortMapping(createTask.get().getPrimaryPortMapping()) } } - - } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mssql/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mssql/TaskPreparer.kt index d2c40a7..2ce16bd 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mssql/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/mssql/TaskPreparer.kt @@ -17,128 +17,89 @@ package com.intershop.gradle.icm.docker.utils.mssql import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.PortMapping import org.gradle.api.Project import org.gradle.api.provider.Provider -import java.io.File class TaskPreparer(project: Project, networkTask: Provider) : AbstractTaskPreparer(project, networkTask){ companion object { - const val extName: String = "MSSQL" + const val EXT_NAME: String = "MSSQL" } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.mssqldb override fun getUseHostUserConfigProperty(): String = Configuration.DB_MSSQL_USE_HOST_USER init { initBaseTasks() - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.description = "Starts an MSSQL server" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - val portMapping : PortMapping - val dbName : String - with(dockerExtension.developmentConfig) { - portMapping = getPortMapping("JDBC", - Configuration.DB_MSSQL_PORT, - Configuration.DB_MSSQL_PORT_VALUE, - Configuration.DB_MSSQL_CONTAINER_PORT, - Configuration.DB_MSSQL_CONTAINER_PORT_VALUE, - true - ) - task.withPortMappings(portMapping) - task.hostConfig.network.set(networkId) - - dbName = getConfigProperty( - Configuration.DB_MSSQL_DBNAME, - Configuration.DB_MSSQL_DBNAME_VALUE + val portMapping = devConfig.getPortMapping( + "JDBC", + Configuration.DB_MSSQL_PORT, + Configuration.DB_MSSQL_PORT_VALUE, + Configuration.DB_MSSQL_CONTAINER_PORT, + Configuration.DB_MSSQL_CONTAINER_PORT_VALUE, + true + ) + val dbName = devConfig.getConfigProperty( + Configuration.DB_MSSQL_DBNAME, + Configuration.DB_MSSQL_DBNAME_VALUE + ) + val env = ContainerEnvironment().addAll( + "ACCEPT_EULA" to "Y", + "SA_PASSWORD" to devConfig.getConfigProperty(Configuration.DB_MSSQL_SA_PASSWORD, + Configuration.DB_MSSQL_SA_PASSWORD_VALUE), "MSSQL_PID" to "Developer", + "RECREATEDB" to devConfig.getConfigProperty( + Configuration.DB_MSSQL_RECREATE_DB, + Configuration.DB_MSSQL_RECREATE_DB_VALUE + ), + "RECREATEUSER" to devConfig.getConfigProperty( + Configuration.DB_MSSQL_RECREATE_USER, + Configuration.DB_MSSQL_RECREATE_USER_VALUE + ), + "ICM_DB_NAME" to dbName, + "ICM_DB_USER" to devConfig.getConfigProperty( + Configuration.DB_USER_NAME, + Configuration.DB_USER_NAME_VALUE + ), + "ICM_DB_PASSWORD" to devConfig.getConfigProperty( + Configuration.DB_USER_PASSWORD, + Configuration.DB_USER_PASSWORD_VALUE ) + ) + val dataPath = devConfig.getFileProperty(Configuration.DATA_FOLDER_PATH, + project.layout.buildDirectory.dir("data_folder").get().asFile).absolutePath + val backupPath = devConfig.getFileProperty(Configuration.BACKUP_FOLDER_PATH, + project.layout.buildDirectory.dir("data_backup_folder").get().asFile).absolutePath + val volumes = mutableMapOf( + dataPath to devConfig.getConfigProperty(Configuration.DATA_FOLDER_VOLUME, + Configuration.DATA_FOLDER_VOLUME_VALUE), + backupPath to devConfig.getConfigProperty(Configuration.BACKUP_FOLDER_VOLUME, + Configuration.BACKUP_FOLDER_VOLUME_VALUE) + ) + + val createTask = registerCreateContainerTask(findTask, volumes, env) + createTask.configure { task -> + task.withPortMappings(portMapping) + } - task.envVars.set( - mutableMapOf( - "ACCEPT_EULA" to - "Y", - "SA_PASSWORD" to - getConfigProperty( - Configuration.DB_MSSQL_SA_PASSWORD, - Configuration.DB_MSSQL_SA_PASSWORD_VALUE - ), - "MSSQL_PID" to - "Developer", - "RECREATEDB" to - getConfigProperty( - Configuration.DB_MSSQL_RECREATE_DB, - Configuration.DB_MSSQL_RECREATE_DB_VALUE - ), - "RECREATEUSER" to - getConfigProperty( - Configuration.DB_MSSQL_RECREATE_USER, - Configuration.DB_MSSQL_RECREATE_USER_VALUE - ), - "ICM_DB_NAME" to dbName, - "ICM_DB_USER" to - getConfigProperty( - Configuration.DB_USER_NAME, - Configuration.DB_USER_NAME_VALUE - ), - "ICM_DB_PASSWORD" to - getConfigProperty( - Configuration.DB_USER_PASSWORD, - Configuration.DB_USER_PASSWORD_VALUE - ) - ) + registerStartContainerTask(createTask).configure { task -> + // TODO #72420 replace by probe (SocketProbe will not help: socket gets available too early) + task.finishedCheck.set("Parallel redo is shutdown for database") + + task.doLast { + project.logger.quiet( + "The database can be connected with jdbc:sqlserver://{}:{};databaseName={}", + getContainerName(), + portMapping.containerPort, + dbName ) - - val volumeMap = mutableMapOf() - - // add data path if configured - val dataPath = getConfigProperty(Configuration.DATA_FOLDER_PATH,"") - val dataPahtFP = if(dataPath.isBlank()) { - project.layout.buildDirectory.dir("data_folder").get().asFile - } else { - File(dataPath) - } - - volumeMap[dataPahtFP.absolutePath] = dockerExtension.developmentConfig.getConfigProperty( - Configuration.DATA_FOLDER_VOLUME, - Configuration.DATA_FOLDER_VOLUME_VALUE) - - // add backup folder - default is build directory - val backupPath = getConfigProperty(Configuration.BACKUP_FOLDER_PATH) - val backupPathFP = if(backupPath.isBlank()) { - project.layout.buildDirectory.dir("data_backup_folder").get().asFile - } else { - File(backupPath) - } - volumeMap[backupPathFP.absolutePath] = dockerExtension.developmentConfig.getConfigProperty( - Configuration.BACKUP_FOLDER_VOLUME, - Configuration.BACKUP_FOLDER_VOLUME_VALUE) - - volumeMap.forEach { path, _ -> File(path).mkdirs() } - - task.hostConfig.binds.set(volumeMap) } - - // TODO #72420 replace by probe (SocketProbe will not help: socket gets available too early) - task.finishedCheck = "Parallel redo is shutdown for database" - - project.logger.quiet( - "The database can be connected with jdbc:sqlserver://{}:{};databaseName={}", - task.containerName.get(), - portMapping.containerPort, - dbName - ) - task.dependsOn(pullTask, networkTask) } + } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/nginx/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/nginx/TaskPreparer.kt index d83bb9b..6f0dea2 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/nginx/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/nginx/TaskPreparer.kt @@ -16,8 +16,9 @@ */ package com.intershop.gradle.icm.docker.utils.nginx +import com.intershop.gradle.icm.docker.tasks.CreateExtraContainer import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration import org.gradle.api.GradleException @@ -31,7 +32,7 @@ class TaskPreparer( ) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extName: String = "NGINX" + const val EXT_NAME: String = "NGINX" const val HTTP_CONTAINER_PORT: Int = 80 const val HTTPS_CONTAINER_PORT: Int = 443 @@ -43,7 +44,7 @@ class TaskPreparer( const val VOLUME_SSL = "/etc/nginx/ssl" } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.nginx override fun getUseHostUserConfigProperty(): String = Configuration.NGINX_USE_HOST_USER @@ -51,89 +52,82 @@ class TaskPreparer( init { initBaseTasks() - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.description = "Starts an NGINX server configured as a reverse proxy" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - with(dockerExtension.developmentConfig) { - val httpPortMapping = getPortMapping( - "HTTP", - Configuration.NGINX_HTTP_PORT, - Configuration.NGINX_HTTP_PORT_VALUE, - HTTP_CONTAINER_PORT, - false - ) - val httpsPortMapping = getPortMapping( - "HTTPS", - Configuration.NGINX_HTTPS_PORT, - Configuration.NGINX_HTTPS_PORT_VALUE, - HTTPS_CONTAINER_PORT, - true - ) - task.withPortMappings(httpPortMapping, httpsPortMapping) - task.hostConfig.network.set(networkId) - - task.envVars.set( - mutableMapOf( - ENV_UPSTREAM_HOST to getConfigProperty( + val httpPortMapping = devConfig.getPortMapping( + "HTTP", + Configuration.NGINX_HTTP_PORT, + Configuration.NGINX_HTTP_PORT_VALUE, + HTTP_CONTAINER_PORT, + false + ) + val httpsPortMapping = devConfig.getPortMapping( + "HTTPS", + Configuration.NGINX_HTTPS_PORT, + Configuration.NGINX_HTTPS_PORT_VALUE, + HTTPS_CONTAINER_PORT, + true + ) + val env = project.provider { + ContainerEnvironment().addAll( + ENV_UPSTREAM_HOST to devConfig.getConfigProperty( Configuration.LOCAL_CONNECTOR_HOST, Configuration.LOCAL_CONNECTOR_HOST_VALUE - ), - ENV_UPSTREAM_PORT to getConfigProperty( + ), + ENV_UPSTREAM_PORT to devConfig.getConfigProperty( Configuration.AS_SERVICE_CONNECTOR_PORT, Configuration.AS_SERVICE_CONNECTOR_PORT_VALUE.toString() - ), - ENV_SSL_CERTIFICATEFILENAME to - getConfigProperty( + ), + ENV_SSL_CERTIFICATEFILENAME to + devConfig.getConfigProperty( Configuration.NGINX_CERT_FILENAME, Configuration.NGINX_CERT_FILENAME_VALUE - ), - ENV_SSL_PRIVATEKEYFILENAME to - getConfigProperty( + ), + ENV_SSL_PRIVATEKEYFILENAME to + devConfig.getConfigProperty( Configuration.NGINX_PRIVATEKEY_FILENAME, Configuration.NGINX_PRIVATEKEY_FILENAME_VALUE - ) - ) - ) - - val nginxCertPath = dockerExtension.developmentConfig.getConfigProperty(Configuration.NGINX_CERT_PATH) - val wsCertPath = dockerExtension.developmentConfig.getConfigProperty(Configuration.WS_CERT_PATH) + ) + ) + } + val volumes = project.provider { mapOf(getCertDir().absolutePath to VOLUME_SSL) } - // if NginxCertPath is not set, we take the webserver certificate path instead - val certPath: String - val configOption: String - if (nginxCertPath.isBlank() && wsCertPath.isBlank()) { - throw GradleException( - "Missing or empty property '${Configuration.NGINX_CERT_PATH}' in your " + - "icm.properties!" - ) - } else { - certPath = if (nginxCertPath.isNotBlank()) { - configOption = Configuration.NGINX_CERT_PATH - nginxCertPath - } else { - configOption = Configuration.WS_CERT_PATH - wsCertPath - } - } + val createTask = registerCreateContainerTask(findTask, CreateExtraContainer::class.java, volumes, env) + createTask.configure { task -> + task.withPortMappings(httpPortMapping, httpsPortMapping) + } - val certDir = File(certPath) - if (!certDir.exists()) { - throw GradleException( - "Property '${configOption}' in your icm.properties " + - "points to a non-existing or non-accessible path: '${certPath}'" - ) - } + registerStartContainerTask(createTask) + } - task.hostConfig.binds.set( - mutableMapOf(certDir.absolutePath to VOLUME_SSL) - ) + private fun getCertDir(): File { + val nginxCertPath = devConfig.getConfigProperty(Configuration.NGINX_CERT_PATH) + val wsCertPath = devConfig.getConfigProperty(Configuration.WS_CERT_PATH) + + // if NginxCertPath is not set, we take the webserver certificate path instead + val certPath: String + val configOption: String + if (nginxCertPath.isBlank() && wsCertPath.isBlank()) { + throw GradleException( + "Missing or empty property '${Configuration.NGINX_CERT_PATH}' in your " + + "icm.properties!" + ) + } else { + certPath = if (nginxCertPath.isNotBlank()) { + configOption = Configuration.NGINX_CERT_PATH + nginxCertPath + } else { + configOption = Configuration.WS_CERT_PATH + wsCertPath } - task.dependsOn(pullTask, networkTask) } - } + val certDir = File(certPath) + if (!certDir.exists()) { + throw GradleException( + "Property '${configOption}' in your icm.properties " + + "points to a non-existing or non-accessible path: '${certPath}'" + ) + } + + return certDir + } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/oracle/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/oracle/TaskPreparer.kt deleted file mode 100644 index 1a52a53..0000000 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/oracle/TaskPreparer.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020 Intershop Communications AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.intershop.gradle.icm.docker.utils.oracle - -import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer -import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer -import com.intershop.gradle.icm.docker.utils.Configuration -import org.gradle.api.Project -import org.gradle.api.provider.Provider - -class TaskPreparer(project: Project, - networkTask: Provider) : AbstractTaskPreparer(project, networkTask) { - - companion object { - const val extName: String = "Oracle" - } - - override fun getExtensionName(): String = extName - override fun getImage(): Provider = dockerExtension.images.oracledb - override fun getUseHostUserConfigProperty(): String = Configuration.DB_ORACLE_USE_HOST_USER - - init { - initBaseTasks() - - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.description = "Starts an Oracle XE server" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - with(dockerExtension.developmentConfig) { - val port = getConfigProperty( - Configuration.DB_ORACLE_PORT, - Configuration.DB_ORACLE_PORT_VALUE - ) - val containerPort = getConfigProperty( - Configuration.DB_ORACLE_CONTAINER_PORT, - Configuration.DB_ORACLE_CONTAINER_PORT_VALUE - ) - - val listenerPort = getConfigProperty( - Configuration.DB_ORACLE_LISTENERPORT, - Configuration.DB_ORACLE_LISTENERPORT_VALUE - ) - val containerListenerPort = getConfigProperty( - Configuration.DB_ORACLE_CONTAINER_LISTENERPORT, - Configuration.DB_ORACLE_CONTAINER_LISTENERPORT_VALUE - ) - - task.hostConfig.portBindings.set( - listOf("${port}:${containerPort}", - "${listenerPort}:${containerListenerPort}") - ) - } - with(dockerExtension.developmentConfig) { - project.logger.quiet( - "The database can be connected with jdbc:oracle:thin:@{}:{}:XE", - task.containerName.get(), - getConfigProperty( - Configuration.DB_ORACLE_PORT, - Configuration.DB_ORACLE_PORT_VALUE - ) - ) - } - task.dependsOn(pullTask, networkTask) - } - } -} diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/redis/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/redis/TaskPreparer.kt index b6dbf48..87fd814 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/redis/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/redis/TaskPreparer.kt @@ -17,7 +17,7 @@ package com.intershop.gradle.icm.docker.utils.redis import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration import com.intershop.gradle.icm.docker.utils.PortMapping @@ -30,31 +30,24 @@ class TaskPreparer( ) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extName: String = "Redis" - const val containerPort = 6379 + const val EXT_NAME: String = "Redis" + const val CONTAINER_PORT = 6379 } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.redis override fun getUseHostUserConfigProperty(): String = Configuration.REDIS_USE_HOST_USER init { initBaseTasks() + val portMapping = PortMapping(EXT_NAME, CONTAINER_PORT, CONTAINER_PORT, true) - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.description = "Starts a Redis instance for p.e PageCache" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - val portMapping = PortMapping(extName, containerPort, containerPort, true) + val createTask = registerCreateContainerTask(findTask, mapOf(), ContainerEnvironment()) + createTask.configure { task -> task.withPortMappings(portMapping) - task.hostConfig.network.set(networkId) - - task.dependsOn(pullTask, networkTask) } + registerStartContainerTask(createTask) } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/SolrPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/SolrPreparer.kt index 64e65b7..66b2bf6 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/SolrPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/SolrPreparer.kt @@ -17,7 +17,7 @@ package com.intershop.gradle.icm.docker.utils.solrcloud import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration import com.intershop.gradle.icm.docker.utils.IPFinder @@ -32,77 +32,61 @@ class SolrPreparer( ) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extName: String = "Solr" + const val EXT_NAME: String = "Solr" const val CONTAINER_PORT = 8983 const val GROUP_NAME = "icm container solrcloud" } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.solr override fun getUseHostUserConfigProperty(): String = Configuration.SOLR_USE_HOST_USER + override fun getTaskGroupExt(): String = "solrcloud" init { initBaseTasks() - - pullTask.configure { - it.group = GROUP_NAME - } - stopTask.configure { - it.group = GROUP_NAME - it.dependsOn(zkPreparer.stopTask) - } - removeTask.configure { - it.group = "icm container solrcloud" - it.dependsOn(zkPreparer.removeTask) + val portMapping = dockerExtension.developmentConfig.getPortMapping( + "SOLR", + Configuration.SOLR_CLOUD_HOST_PORT, + Configuration.SOLR_CLOUD_HOST_PORT_VALUE, + CONTAINER_PORT, + true) + val env = ContainerEnvironment().addAll( + "SOLR_PORT" to portMapping.containerPort.toString(), + "ZK_HOST" to zkPreparer.getRenderedHostPort(), + "SOLR_HOST" to "${IPFinder.getSystemIP().first}", + "SOLR_OPTS" to "-Dsolr.disableConfigSetsCreateAuthChecks=true" + ) + val dataDir: File? = getLocalDataDir() + val volumes = if (dataDir != null) { + mapOf(dataDir.absolutePath to "/var/solr") + } else { + mapOf() } - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.group = GROUP_NAME - task.description = "Start Solr component of SolrCloud" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - val portMapping = dockerExtension.developmentConfig.getPortMapping( - "SOLR", - Configuration.SOLR_CLOUD_HOST_PORT, - Configuration.SOLR_CLOUD_HOST_PORT_VALUE, - CONTAINER_PORT, - true) + val createTask = registerCreateContainerTask(findTask, volumes, env) + createTask.configure { task -> task.withPortMappings(portMapping) + } - task.envVars.set( - mutableMapOf( - "SOLR_PORT" to portMapping.containerPort.toString(), - "ZK_HOST" to zkPreparer.renderedHostPort, - "SOLR_HOST" to "${IPFinder.getSystemIP().first}", - "SOLR_OPTS" to "-Dsolr.disableConfigSetsCreateAuthChecks=true" - ) - ) - - val volumeMap = mutableMapOf() - - // add data path if configured - val dataPath = dockerExtension.developmentConfig.getConfigProperty(Configuration.SOLR_DATA_FOLDER_PATH,"") - val dataPahtFP = if (dataPath.isNotEmpty()) File(dataPath) else null - - if(dataPahtFP != null) { - volumeMap[dataPahtFP.absolutePath] = "/var/solr" - volumeMap.forEach { path, _ -> File(path).mkdirs() } - task.hostConfig.binds.set(volumeMap) + registerStartContainerTask(createTask).configure { task -> + task.doLast { + task.logger.quiet( + "The Solr server can be connected with {}:{}", + getContainerName(), + portMapping.containerPort + ) } + task.dependsOn(zkPreparer.startTask) + } - task.hostConfig.network.set(networkId) - task.logger.quiet( - "The Solr server can be connected with {}:{}", - task.containerName.get(), - portMapping.containerPort - ) + } - task.dependsOn(pullTask, networkTask, zkPreparer.startTask) + private fun getLocalDataDir(): File? { + val dataPath = devConfig.getConfigProperty(Configuration.SOLR_DATA_FOLDER_PATH, "") + if (dataPath.isBlank()) { + return null } - + return File(dataPath) } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/ZKPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/ZKPreparer.kt index 6d4cd28..e066b25 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/ZKPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/solrcloud/ZKPreparer.kt @@ -17,11 +17,10 @@ package com.intershop.gradle.icm.docker.utils.solrcloud import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration import com.intershop.gradle.icm.docker.utils.PortMapping -import com.intershop.gradle.icm.docker.utils.solrcloud.SolrPreparer.Companion.GROUP_NAME import org.gradle.api.Project import org.gradle.api.provider.Provider @@ -31,83 +30,68 @@ class ZKPreparer( ) : AbstractTaskPreparer(project, networkTask) { companion object { - const val extName: String = "ZK" + const val EXT_NAME: String = "ZK" const val CONTAINER_PORT = 2181 const val CONTAINER_METRICS_PORT = 7000 const val CONTAINER_PORTMAPPING = "CONTAINER" } - override fun getExtensionName(): String = extName + override fun getExtensionName(): String = EXT_NAME override fun getImage(): Provider = dockerExtension.images.zookeeper override fun getUseHostUserConfigProperty(): String = Configuration.ZOOKEEPER_USE_HOST_USER + override fun getTaskGroupExt(): String = "solrcloud" init { initBaseTasks() - pullTask.configure { - it.group = GROUP_NAME - } - stopTask.configure { - it.group = GROUP_NAME - } - removeTask.configure { - it.group = GROUP_NAME - } - - val metricsPortMapping = dockerExtension.developmentConfig.getPortMapping( + val metricsPortMapping = devConfig.getPortMapping( "METRICS", Configuration.ZOOKEEPER_METRICS_HOST_PORT, Configuration.ZOOKEEPER_METRICS_HOST_PORT_VALUE, CONTAINER_METRICS_PORT, ) + val portMapping = getPortMapping() - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.group = "icm container solrcloud" - task.description = "Start Zookeeper component of SolrCloud" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - task.withPortMappings(portMapping, metricsPortMapping) + val env = ContainerEnvironment().addAll( + "ZOO_MY_ID" to "1", + "ZOO_PORT" to portMapping.containerPort.toString(), + "ZOO_SERVERS" to "server.1=${getZKServers()}", + "ZOO_4LW_COMMANDS_WHITELIST" to "mntr, conf, ruok", + "ZOO_CFG_EXTRA" to """ + metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider + metricsProvider.httpPort=${metricsPortMapping.containerPort} + metricsProvider.exportJvmInfo=true + """.trimIndent() + ) - val zooServers = "${getContainerName()}:2888:3888;${portMapping.containerPort}" - task.envVars.set( - mutableMapOf( - "ZOO_MY_ID" to "1", - "ZOO_PORT" to portMapping.containerPort.toString(), - "ZOO_SERVERS" to "server.1=$zooServers", - "ZOO_4LW_COMMANDS_WHITELIST" to "mntr, conf, ruok", - "ZOO_CFG_EXTRA" to - "metricsProvider.className=org.apache.zookeeper.metrics.prometheus." + - "PrometheusMetricsProvider metricsProvider.httpPort=" + - "${metricsPortMapping.containerPort} " + - "metricsProvider.exportJvmInfo=true" - ) - ) + val createTask = registerCreateContainerTask(findTask, mapOf(), env) + createTask.configure { task -> + task.withPortMappings(portMapping) + } - task.hostConfig.network.set(networkId) - task.logger.quiet( - "The ZK for SolrCloud can be connected with {}:{}", - task.containerName.get(), - portMapping.containerPort - ) - task.dependsOn(pullTask, networkTask) + registerStartContainerTask(createTask).configure { task -> + task.doLast { + project.logger.quiet( + "The ZK for SolrCloud can be connected with {}:{}", + getContainerName(), + portMapping.containerPort + ) + } } } - private val portMapping: PortMapping by lazy { - dockerExtension.developmentConfig.getPortMapping( - CONTAINER_PORTMAPPING, - Configuration.ZOOKEEPER_HOST_PORT, - Configuration.ZOOKEEPER_HOST_PORT_VALUE, - CONTAINER_PORT, - true + private fun getZKServers(): String = "${getContainerName()}:2888:3888;${getPortMapping().containerPort}" + private fun getPortMapping(): PortMapping = + devConfig.getPortMapping( + CONTAINER_PORTMAPPING, + Configuration.ZOOKEEPER_HOST_PORT, + Configuration.ZOOKEEPER_HOST_PORT_VALUE, + CONTAINER_PORT, + true ) - } - val renderedHostPort : String by lazy { - "${getContainerName()}:${portMapping.containerPort}" - } + + fun getRenderedHostPort(): String = "${getContainerName()}:${getPortMapping().containerPort}" + } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/TaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/TaskPreparer.kt index 7518391..2740968 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/TaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/TaskPreparer.kt @@ -20,12 +20,12 @@ import com.intershop.gradle.icm.docker.extension.IntershopDockerExtension import com.intershop.gradle.icm.docker.tasks.CreateVolumes import com.intershop.gradle.icm.docker.tasks.RemoveVolumes import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.network.TaskPreparer as NetworkPreparer import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.getByType import java.io.File +import com.intershop.gradle.icm.docker.utils.network.TaskPreparer as NetworkPreparer class TaskPreparer(val project: Project, private val networkTasks: NetworkPreparer) { @@ -72,7 +72,7 @@ class TaskPreparer(val project: Project, private val networkTasks: NetworkPrepar } waaTasks.startTask.configure { - it.dependsOn(createVolumes, waTasks.startTask) + it.dependsOn(createVolumes) } project.tasks.register("start${TASK_EXT_SERVER}") { task -> diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WAATaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WAATaskPreparer.kt index 109df01..4195812 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WAATaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WAATaskPreparer.kt @@ -17,10 +17,10 @@ package com.intershop.gradle.icm.docker.utils.webserver import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer +import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration -import com.intershop.gradle.icm.docker.utils.appsrv.ServerTaskPreparer +import com.intershop.gradle.icm.docker.utils.appsrv.ASTaskPreparer import org.gradle.api.Project import org.gradle.api.provider.Provider @@ -30,62 +30,42 @@ class WAATaskPreparer(project: Project, companion object { const val extName: String = "WAA" - const val GROUP_NAME: String = "icm container webserver" } override fun getExtensionName(): String = extName override fun getImage(): Provider = dockerExtension.images.webadapteragent override fun getUseHostUserConfigProperty(): String = Configuration.WAA_USE_HOST_USER + override fun getTaskGroupExt(): String = "webserver" init{ initBaseTasks() - pullTask.configure { - it.group = GROUP_NAME - } - stopTask.configure { - it.group = GROUP_NAME - } - removeTask.configure { - it.group = GROUP_NAME - } - - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.group = "icm container webserver" - task.description = "Start ICM WebAdapterAgent" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - with(dockerExtension.developmentConfig) { - val portMapping = asPortConfiguration.managementConnector.get() + val env = with(dockerExtension.developmentConfig) { + val portMapping = asPortConfiguration.managementConnector.get() - val host: String - val port: Int - if (appserverAsContainer) { - // started as container - host = "${dockerExtension.containerPrefix}-${ServerTaskPreparer.extName.lowercase()}" - port = portMapping.containerPort - } else { + val host: String + val port: Int + if (appserverAsContainer) { + // started as container + host = "${dockerExtension.containerPrefix}-${ASTaskPreparer.extName.lowercase()}" + port = portMapping.containerPort + } else { - // started externally - host = getConfigProperty( - Configuration.LOCAL_CONNECTOR_HOST, - Configuration.LOCAL_CONNECTOR_HOST_VALUE - ) - port = portMapping.hostPort - } - - task.envVars.put( - "ICM_ICMSERVLETURLS", - "cs.url.0=http://${host}:${port}/servlet/ConfigurationServlet" + // started externally + host = getConfigProperty( + Configuration.LOCAL_CONNECTOR_HOST, + Configuration.LOCAL_CONNECTOR_HOST_VALUE ) + port = portMapping.hostPort } - task.hostConfig.binds.set( volumes ) - task.hostConfig.network.set(networkId) - task.dependsOn(pullTask, networkTask) + ContainerEnvironment().add( + "ICM_ICMSERVLETURLS", + "cs.url.0=http://${host}:${port}/servlet/ConfigurationServlet" + ) } + val createTask = registerCreateContainerTask(findTask, volumes, env) + registerStartContainerTask(createTask) + } } diff --git a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WATaskPreparer.kt b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WATaskPreparer.kt index 63a622f..0826486 100644 --- a/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WATaskPreparer.kt +++ b/src/main/kotlin/com/intershop/gradle/icm/docker/utils/webserver/WATaskPreparer.kt @@ -18,7 +18,6 @@ package com.intershop.gradle.icm.docker.utils.webserver import com.intershop.gradle.icm.docker.tasks.PrepareNetwork -import com.intershop.gradle.icm.docker.tasks.StartExtraContainer import com.intershop.gradle.icm.docker.tasks.utils.ContainerEnvironment import com.intershop.gradle.icm.docker.utils.AbstractTaskPreparer import com.intershop.gradle.icm.docker.utils.Configuration @@ -27,8 +26,7 @@ import com.intershop.gradle.icm.docker.utils.Configuration.WS_READINESS_PROBE_IN import com.intershop.gradle.icm.docker.utils.Configuration.WS_READINESS_PROBE_INTERVAL_VALUE import com.intershop.gradle.icm.docker.utils.Configuration.WS_READINESS_PROBE_TIMEOUT import com.intershop.gradle.icm.docker.utils.Configuration.WS_READINESS_PROBE_TIMEOUT_VALUE -import com.intershop.gradle.icm.docker.utils.appsrv.ServerTaskPreparer -import com.intershop.gradle.icm.docker.utils.webserver.WAATaskPreparer.Companion.GROUP_NAME +import com.intershop.gradle.icm.docker.utils.appsrv.ASTaskPreparer import org.gradle.api.Project import org.gradle.api.provider.Provider @@ -45,22 +43,11 @@ class WATaskPreparer( override fun getExtensionName(): String = extName override fun getImage(): Provider = dockerExtension.images.webadapter override fun getUseHostUserConfigProperty(): String = WA_USE_HOST_USER - - val httpContainerPort: Int + override fun getTaskGroupExt(): String = "webserver" init { initBaseTasks() - pullTask.configure { - it.group = GROUP_NAME - } - stopTask.configure { - it.group = GROUP_NAME - } - removeTask.configure { - it.group = GROUP_NAME - } - val httpPortMapping = dockerExtension.developmentConfig.getPortMapping( "http", Configuration.WS_HTTP_PORT, @@ -76,65 +63,56 @@ class WATaskPreparer( Configuration.WS_CONTAINER_HTTPS_PORT_VALUE, true ) - httpContainerPort = httpPortMapping.containerPort - - project.tasks.register("start${getExtensionName()}", StartExtraContainer::class.java) { task -> - configureContainerTask(task) - task.group = "icm container webserver" - task.description = "Start ICM WebServer with WebAdapter" - - task.targetImageId(project.provider { pullTask.get().image.get() }) - task.image.set(pullTask.get().image) - - with(dockerExtension.developmentConfig) { - task.withPortMappings(httpPortMapping, httpsPortMapping) - - val env = ContainerEnvironment() - val serverCertName = getConfigProperty(Configuration.WS_SERVER_CERT, "") - if (serverCertName.isNotBlank()) { - env.add("ICM_SERVERCERT", serverCertName) - } + val env = with(dockerExtension.developmentConfig) { + val env = ContainerEnvironment() - val privateKeyName = getConfigProperty(Configuration.WS_SERVER_PRIVAT, "") - if (privateKeyName.isNotBlank()) { - env.add("ICM_SERVERPRIVATEKEY", privateKeyName) - } + val serverCertName = getConfigProperty(Configuration.WS_SERVER_CERT, "") + if (serverCertName.isNotBlank()) { + env.add("ICM_SERVERCERT", serverCertName) + } - val usehttp2 = getConfigProperty(Configuration.WS_SERVER_HTTP2, "false") - if (usehttp2 == "true") { - env.add("USEHTTP2", "true") - } + val privateKeyName = getConfigProperty(Configuration.WS_SERVER_PRIVAT, "") + if (privateKeyName.isNotBlank()) { + env.add("ICM_SERVERPRIVATEKEY", privateKeyName) + } + val usehttp2 = getConfigProperty(Configuration.WS_SERVER_HTTP2, "false") + if (usehttp2 == "true") { + env.add("USEHTTP2", "true") + } - val servletUrlProvider = project.provider { - val portMapping = asPortConfiguration.managementConnector.get() - - val host: String - val port: Int - if (appserverAsContainer) { - // started as container - host = "${dockerExtension.containerPrefix}-${ServerTaskPreparer.extName.lowercase()}" - port = portMapping.containerPort - } else { - - // started externally - host = getConfigProperty( - Configuration.LOCAL_CONNECTOR_HOST, - Configuration.LOCAL_CONNECTOR_HOST_VALUE - ) - port = portMapping.hostPort - } - return@provider "cs.url.0=http://$host:$port/servlet/ConfigurationServlet" + val servletUrlProvider = project.provider { + val portMapping = asPortConfiguration.managementConnector.get() + + val host: String + val port: Int + if (appserverAsContainer) { + // started as container + host = "${dockerExtension.containerPrefix}-${ASTaskPreparer.extName.lowercase()}" + port = portMapping.containerPort + } else { + + // started externally + host = getConfigProperty( + Configuration.LOCAL_CONNECTOR_HOST, + Configuration.LOCAL_CONNECTOR_HOST_VALUE + ) + port = portMapping.hostPort } + return@provider "cs.url.0=http://$host:$port/servlet/ConfigurationServlet" + } - env.add("ICM_ICMSERVLETURLS", servletUrlProvider) + env.add("ICM_ICMSERVLETURLS", servletUrlProvider) + return@with env + } - task.withEnvironment(env) - } - task.hostConfig.network.set(networkId) - task.hostConfig.binds.set(volumes) + val createTask = registerCreateContainerTask(findTask, volumes, env) + createTask.configure { task -> + task.withPortMappings(httpPortMapping, httpsPortMapping) + } + registerStartContainerTask(createTask).configure { task -> // add socketProbes to http and https ports with(dockerExtension.developmentConfig) { task.withSocketProbe( @@ -148,7 +126,6 @@ class WATaskPreparer( getDurationProperty(WS_READINESS_PROBE_TIMEOUT, WS_READINESS_PROBE_TIMEOUT_VALUE) ) } - task.dependsOn(pullTask, networkTask) } } } diff --git a/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerPluginIntegegrationSpec.groovy b/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerPluginIntegegrationSpec.groovy index 51e860b..bfe6acb 100644 --- a/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerPluginIntegegrationSpec.groovy +++ b/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerPluginIntegegrationSpec.groovy @@ -18,11 +18,14 @@ package com.intershop.gradle.icm.docker import com.intershop.gradle.icm.docker.util.TestRepo import com.intershop.gradle.test.AbstractIntegrationGroovySpec -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + import static org.gradle.testkit.runner.TaskOutcome.SKIPPED +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { + final ICMGRADLEVERSION = "6.0.1" + private def prepareBuildConfig(File testProjectDir, File settingsFile, File buildFile) { TestRepo repo = new TestRepo(new File(testProjectDir, "/repo")) String repoConf = repo.getRepoConfig() @@ -40,7 +43,7 @@ class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { buildFile << """ plugins { id 'java' - id 'com.intershop.gradle.icm.base' version '4.3.0' + id 'com.intershop.gradle.icm.base' version '$ICMGRADLEVERSION' id 'com.intershop.gradle.icm.docker' } @@ -201,7 +204,7 @@ class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { buildFile << """ plugins { id 'java' - id 'com.intershop.gradle.icm.project' version '4.3.0' + id 'com.intershop.gradle.icm.project' version '$ICMGRADLEVERSION' id 'com.intershop.gradle.icm.docker.customization' id 'com.intershop.gradle.icm.docker.solrcloud' } @@ -396,7 +399,7 @@ class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { buildFile << """ plugins { id 'java' - id 'com.intershop.gradle.icm.project' version '4.3.0' + id 'com.intershop.gradle.icm.project' version '$ICMGRADLEVERSION' id 'com.intershop.gradle.icm.docker.customization' } @@ -544,7 +547,7 @@ class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { buildFile << """ plugins { id 'java' - id 'com.intershop.gradle.icm.project' version '4.3.0' + id 'com.intershop.gradle.icm.project' version '$ICMGRADLEVERSION' id 'com.intershop.gradle.icm.docker.customization' id 'com.intershop.gradle.icm.docker.solrcloud' } @@ -723,21 +726,21 @@ class ICMDockerPluginIntegegrationSpec extends AbstractIntegrationGroovySpec { when: def result2 = getPreparedGradleRunner() - .withArguments("startContainer", "-s") + .withArguments("startWaitingAs", "-s") .withGradleVersion(gradleVersion) .build() then: - result2.task(":startContainer").outcome == SUCCESS + result2.task(":startWaitingAs").outcome == SUCCESS when: def result3 = getPreparedGradleRunner() - .withArguments("removeContainer", "-s") + .withArguments("removeWaitingAs", "-s") .withGradleVersion(gradleVersion) .build() then: - result3.task(":removeContainer").outcome == SUCCESS + result3.task(":removeWaitingAs").outcome == SUCCESS where: gradleVersion << supportedGradleVersions diff --git a/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerTaskIntegrationSpec.groovy b/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerTaskIntegrationSpec.groovy index 0169a4e..a2ed3be 100644 --- a/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerTaskIntegrationSpec.groovy +++ b/src/test/groovy/com/intershop/gradle/icm/docker/ICMDockerTaskIntegrationSpec.groovy @@ -23,7 +23,7 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class ICMDockerTaskIntegrationSpec extends AbstractIntegrationGroovySpec { - final ICMGRADLEVERSION = "5.6.0" + final ICMGRADLEVERSION = "6.0.1" def 'test create volumes task'() { settingsFile << """ diff --git a/src/test/groovy/com/intershop/gradle/icm/docker/TaskICMGenSpec.groovy b/src/test/groovy/com/intershop/gradle/icm/docker/TaskICMGenSpec.groovy index d84657d..5ce1503 100644 --- a/src/test/groovy/com/intershop/gradle/icm/docker/TaskICMGenSpec.groovy +++ b/src/test/groovy/com/intershop/gradle/icm/docker/TaskICMGenSpec.groovy @@ -28,7 +28,7 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class TaskICMGenSpec extends AbstractIntegrationGroovySpec { - final ICMGRADLEVERSION = "5.6.0" + final ICMGRADLEVERSION = "6.0.1" String buildfileContent = """ @@ -71,90 +71,6 @@ class TaskICMGenSpec extends AbstractIntegrationGroovySpec { gradleVersion << supportedGradleVersions } - def 'oracle file creation (container)'() { - settingsFile << settingsfileContent - buildFile << buildfileContent - - when: - def result1 = getPreparedGradleRunner() - .withArguments("generateICMProps", "--db=oracle-cont", "-s") - .withGradleVersion(gradleVersion) - .build() - File file = new File(testProjectDir, "build/icmproperties/icm.properties") - - then: - result1.task(":generateICMProps").outcome == SUCCESS - file.exists() - file.text.contains("oracle base configuration") - file.text.contains("jdbc:oracle:thin:@rootproject-oracle:1521:XE") - - where: - gradleVersion << supportedGradleVersions - } - - def 'oracle file creation (external)'() { - settingsFile << settingsfileContent - buildFile << buildfileContent - - when: - def result1 = getPreparedGradleRunner() - .withArguments("generateICMProps", "--db=oracle", "-s") - .withGradleVersion(gradleVersion) - .build() - File file = new File(testProjectDir, "build/icmproperties/icm.properties") - - then: - result1.task(":generateICMProps").outcome == SUCCESS - file.exists() - file.text.contains("oracle base configuration") - file.text.contains("") - - where: - gradleVersion << supportedGradleVersions - } - - def 'oracle file creation (container + icmas)'() { - settingsFile << settingsfileContent - buildFile << buildfileContent - - when: - def result1 = getPreparedGradleRunner() - .withArguments("generateICMProps", "--db=oracle-cont", "--icmas", "-s") - .withGradleVersion(gradleVersion) - .build() - File file = new File(testProjectDir, "build/icmproperties/icm.properties") - - then: - result1.task(":generateICMProps").outcome == SUCCESS - file.exists() - file.text.contains("oracle base configuration") - file.text.contains("intershop.jdbc.url = jdbc:oracle:thin:@localhost:1521:XE") - - where: - gradleVersion << supportedGradleVersions - } - - def 'oracle file creation (external + icmas)'() { - settingsFile << settingsfileContent - buildFile << buildfileContent - - when: - def result1 = getPreparedGradleRunner() - .withArguments("generateICMProps", "--db=oracle", "--icmas", "-s") - .withGradleVersion(gradleVersion) - .build() - File file = new File(testProjectDir, "build/icmproperties/icm.properties") - - then: - result1.task(":generateICMProps").outcome == SUCCESS - file.exists() - file.text.contains("oracle base configuration") - file.text.contains("") - - where: - gradleVersion << supportedGradleVersions - } - def 'mssql file creation (container)'() { settingsFile << settingsfileContent buildFile << buildfileContent