|
1 | 1 | /*
|
2 |
| - * Copyright 2020-2021 the original author or authors. |
| 2 | + * Copyright 2022 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
15 | 15 | */
|
16 | 16 | package org.springframework.batch.core.test.repository;
|
17 | 17 |
|
| 18 | +import java.time.Duration; |
| 19 | +import java.time.temporal.ChronoUnit; |
| 20 | +import java.util.Arrays; |
| 21 | +import java.util.HashMap; |
| 22 | +import java.util.HashSet; |
| 23 | +import java.util.Map; |
| 24 | +import java.util.Set; |
| 25 | + |
18 | 26 | import javax.sql.DataSource;
|
19 | 27 |
|
| 28 | +import com.github.dockerjava.api.model.Ulimit; |
20 | 29 | import org.junit.Assert;
|
21 | 30 | import org.junit.Before;
|
22 | 31 | import org.junit.ClassRule;
|
| 32 | +import org.junit.Ignore; |
23 | 33 | import org.junit.Test;
|
24 | 34 | import org.junit.runner.RunWith;
|
25 | 35 | import org.springframework.batch.core.ExitStatus;
|
|
38 | 48 | import org.springframework.core.io.ClassPathResource;
|
39 | 49 | import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
40 | 50 | import org.springframework.test.context.ContextConfiguration;
|
| 51 | +import org.springframework.test.context.junit.jupiter.EnabledIf; |
41 | 52 | import org.springframework.test.context.junit4.SpringRunner;
|
| 53 | + |
| 54 | +import org.testcontainers.containers.JdbcDatabaseContainer; |
| 55 | +import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; |
42 | 56 | import org.testcontainers.utility.DockerImageName;
|
43 | 57 |
|
44 | 58 | import com.sap.db.jdbcext.HanaDataSource;
|
| 59 | +import org.testcontainers.utility.LicenseAcceptance; |
45 | 60 |
|
46 | 61 | /**
|
| 62 | + * The official Docker image for SAP HANA is not publicly available. SAP HANA support is tested manually. |
| 63 | + * See https://hub.docker.com/_/sap-hana-express-edition/plans/f2dc436a-d851-4c22-a2ba-9de07db7a9ac |
| 64 | + * FTR, from the previous link: "This installation does not support Docker for Windows or Docker for Mac." |
| 65 | + * |
47 | 66 | * @author Jonathan Bregler
|
| 67 | + * @author Mahmoud Ben Hassine |
48 | 68 | */
|
49 | 69 | @RunWith(SpringRunner.class)
|
50 | 70 | @ContextConfiguration
|
| 71 | +@Ignore("Official Docker image for SAP HANA not publicly available and works only on Linux") |
51 | 72 | public class HANAJobRepositoryIntegrationTests {
|
52 | 73 |
|
53 |
| - private static final DockerImageName HANA_IMAGE = DockerImageName.parse( "store/saplabs/hanaexpress:2.00.054.00.20210603.1" ); |
| 74 | + private static final DockerImageName HANA_IMAGE = DockerImageName.parse( "store/saplabs/hanaexpress:2.00.057.00.20211207.1" ); |
54 | 75 |
|
55 | 76 | @ClassRule
|
56 | 77 | public static HANAContainer<?> hana = new HANAContainer<>( HANA_IMAGE ).acceptLicense();
|
@@ -103,4 +124,103 @@ public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
|
103 | 124 | }
|
104 | 125 |
|
105 | 126 | }
|
| 127 | + |
| 128 | + /** |
| 129 | + * @author Jonathan Bregler |
| 130 | + */ |
| 131 | + public static class HANAContainer<SELF extends HANAContainer<SELF>> extends JdbcDatabaseContainer<SELF> { |
| 132 | + |
| 133 | + private static final Integer PORT = 39041; |
| 134 | + |
| 135 | + private static final String SYSTEM_USER = "SYSTEM"; |
| 136 | + private static final String SYSTEM_USER_PASSWORD = "HXEHana1"; |
| 137 | + |
| 138 | + public HANAContainer(DockerImageName image) { |
| 139 | + |
| 140 | + super( image ); |
| 141 | + |
| 142 | + addExposedPorts( 39013, 39017, 39041, 39042, 39043, 39044, 39045, 1128, 1129, 59013, 59014 ); |
| 143 | + |
| 144 | + // create ulimits |
| 145 | + Ulimit[] ulimits = new Ulimit[]{ new Ulimit( "nofile", 1048576L, 1048576L ) }; |
| 146 | + |
| 147 | + // create sysctls Map. |
| 148 | + Map<String, String> sysctls = new HashMap<String, String>(); |
| 149 | + |
| 150 | + sysctls.put( "kernel.shmmax", "1073741824" ); |
| 151 | + sysctls.put( "net.ipv4.ip_local_port_range", "40000 60999" ); |
| 152 | + |
| 153 | + // Apply mounts, ulimits and sysctls. |
| 154 | + this.withCreateContainerCmdModifier( it -> it.getHostConfig().withUlimits( ulimits ).withSysctls( sysctls ) ); |
| 155 | + |
| 156 | + // Arguments for Image. |
| 157 | + this.withCommand( "--master-password " + SYSTEM_USER_PASSWORD + " --agree-to-sap-license" ); |
| 158 | + |
| 159 | + // Determine if container is ready. |
| 160 | + this.waitStrategy = new LogMessageWaitStrategy().withRegEx( ".*Startup finished!*\\s" ).withTimes( 1 ) |
| 161 | + .withStartupTimeout( Duration.of( 600, ChronoUnit.SECONDS ) ); |
| 162 | + } |
| 163 | + |
| 164 | + @Override |
| 165 | + protected void configure() { |
| 166 | + /* |
| 167 | + * Enforce that the license is accepted - do not remove. License available at: |
| 168 | + * https://www.sap.com/docs/download/cmp/2016/06/sap-hana-express-dev-agmt-and-exhibit.pdf |
| 169 | + */ |
| 170 | + |
| 171 | + // If license was not accepted programmatically, check if it was accepted via |
| 172 | + // resource file |
| 173 | + if ( !getEnvMap().containsKey( "AGREE_TO_SAP_LICENSE" ) ) { |
| 174 | + LicenseAcceptance.assertLicenseAccepted( this.getDockerImageName() ); |
| 175 | + acceptLicense(); |
| 176 | + } |
| 177 | + } |
| 178 | + |
| 179 | + /** |
| 180 | + * Accepts the license for the SAP HANA Express container by setting the AGREE_TO_SAP_LICENSE=Y Calling this method |
| 181 | + * will automatically accept the license at: |
| 182 | + * https://www.sap.com/docs/download/cmp/2016/06/sap-hana-express-dev-agmt-and-exhibit.pdf |
| 183 | + * |
| 184 | + * @return The container itself with an environment variable accepting the SAP HANA Express license |
| 185 | + */ |
| 186 | + public SELF acceptLicense() { |
| 187 | + addEnv( "AGREE_TO_SAP_LICENSE", "Y" ); |
| 188 | + return self(); |
| 189 | + } |
| 190 | + |
| 191 | + @Override |
| 192 | + public Set<Integer> getLivenessCheckPortNumbers() { |
| 193 | + return new HashSet<>( Arrays.asList( new Integer[]{ getMappedPort( PORT ) } ) ); |
| 194 | + } |
| 195 | + |
| 196 | + @Override |
| 197 | + protected void waitUntilContainerStarted() { |
| 198 | + getWaitStrategy().waitUntilReady( this ); |
| 199 | + } |
| 200 | + |
| 201 | + @Override |
| 202 | + public String getDriverClassName() { |
| 203 | + return "com.sap.db.jdbc.Driver"; |
| 204 | + } |
| 205 | + |
| 206 | + @Override |
| 207 | + public String getUsername() { |
| 208 | + return SYSTEM_USER; |
| 209 | + } |
| 210 | + |
| 211 | + @Override |
| 212 | + public String getPassword() { |
| 213 | + return SYSTEM_USER_PASSWORD; |
| 214 | + } |
| 215 | + |
| 216 | + @Override |
| 217 | + public String getTestQueryString() { |
| 218 | + return "SELECT 1 FROM SYS.DUMMY"; |
| 219 | + } |
| 220 | + |
| 221 | + @Override |
| 222 | + public String getJdbcUrl() { |
| 223 | + return "jdbc:sap://" + getContainerIpAddress() + ":" + getMappedPort( PORT ) + "/"; |
| 224 | + } |
| 225 | + } |
106 | 226 | }
|
0 commit comments