>From Ian Maxon <[email protected]>:

Ian Maxon has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20432?usp=email )


Change subject: [ASTERIXDB-3654][TEST]Use Azurite in testcontainers
......................................................................

[ASTERIXDB-3654][TEST]Use Azurite in testcontainers

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Use Azurite in testcontainers instead of installing and
  invoking it via npm through frontend-npm-plugin

- Use the normal storage credential path instead of the
  anonymous auth test path for CloudStorageAzTest

Ext-ref: MB-68803
Change-Id: Iad1a6f9331fd844f3e3c04b8f56e811e4227f83e
---
M asterixdb/asterix-app/pom.xml
M 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageAzTest.java
M asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.conf
A asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.ftl
M asterixdb/pom.xml
5 files changed, 179 insertions(+), 75 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/32/20432/1

diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index f1bbb37..a6d95de 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -293,29 +293,6 @@
             </configuration>
           </execution>
           <execution>
-            <id>azurite</id>
-            <phase>${azurite.stage}</phase>
-            <goals>
-              <goal>exec</goal>
-            </goals>
-            <configuration>
-              <!--suppress UnresolvedMavenProperty -->
-              
<executable>${project.build.directory}/npm/node_modules/.bin/azurite-blob</executable>
-              <workingDirectory>${project.build.directory}</workingDirectory>
-              <environmentVariables>
-                <PATH>${project.build.directory}/npm/node</PATH>
-              </environmentVariables>
-              <arguments>
-                <argument>--blobPort</argument>
-                <argument>15055</argument>
-                <argument>--location</argument>
-                <argument>${project.build.directory}/azurite</argument>
-              </arguments>
-              <async>true</async>
-              
<outputFile>${project.build.directory}/azurite/logs/azurite.log</outputFile>
-            </configuration>
-          </execution>
-          <execution>
             <id>fake-gcs-server</id>
             <phase>${gcs.stage}</phase>
             <goals>
@@ -697,43 +674,6 @@
         <failIfNoTests>false</failIfNoTests>
       </properties>
     </profile>
-    <profile>
-        <id>azurite-tests</id>
-        <build>
-            <plugins>
-                <plugin>
-                    <groupId>com.github.eirslett</groupId>
-                    <artifactId>frontend-maven-plugin</artifactId>
-                    <version>1.13.4</version>
-                    <configuration>
-                        <nodeVersion>v14.15.4</nodeVersion>
-                        <npmVersion>6.14.11</npmVersion>
-                        <workingDirectory>target/npm</workingDirectory>
-                        <installDirectory>target/npm</installDirectory>
-                    </configuration>
-                    <executions>
-                        <execution>
-                            <id>install node and yarn</id>
-                            <goals>
-                                <goal>install-node-and-npm</goal>
-                            </goals>
-                            <phase>${azurite.npm.install.stage}</phase>
-                        </execution>
-                        <execution>
-                            <id>azurite blob</id>
-                            <phase>${azurite.install.stage}</phase>
-                            <goals>
-                                <goal>npm</goal>
-                            </goals>
-                            <configuration>
-                                <arguments>install [email protected]</arguments>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-            </plugins>
-        </build>
-    </profile>
   </profiles>
   <dependencies>
     <dependency>
@@ -1062,6 +1002,11 @@
     </dependency>
     <dependency>
       <groupId>org.testcontainers</groupId>
+      <artifactId>azure</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.testcontainers</groupId>
       <artifactId>postgresql</artifactId>
       <scope>test</scope>
     </dependency>
@@ -1201,5 +1146,17 @@
       <version>2.3.31</version>
       <scope>test</scope>
    </dependency>
+   <dependency>
+     <groupId>org.bouncycastle</groupId>
+     <artifactId>bcprov-jdk18on</artifactId>
+     <version>1.78.1</version>
+     <scope>test</scope>
+   </dependency>
+   <dependency>
+     <groupId>org.bouncycastle</groupId>
+     <artifactId>bcpkix-jdk18on</artifactId>
+     <version>1.78.1</version>
+     <scope>test</scope>
+   </dependency>
   </dependencies>
 </project>
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageAzTest.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageAzTest.java
index d3f766e..2df75fc 100644
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageAzTest.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageAzTest.java
@@ -19,10 +19,22 @@
 package org.apache.asterix.test.cloud_storage;

 import static 
org.apache.asterix.api.common.LocalCloudUtil.CLOUD_STORAGE_BUCKET;
+import static 
org.apache.asterix.api.common.LocalCloudUtilAdobeMock.fillConfigTemplate;
 import static 
org.apache.asterix.test.cloud_storage.CloudStorageGCSTest.S3_ONLY;

+import java.io.File;
+import java.io.FileOutputStream;
+import java.math.BigInteger;
+import java.net.URI;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -36,6 +48,11 @@
 import org.apache.asterix.testframework.xml.TestCase;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.junit.AfterClass;
 import org.junit.Assume;
 import org.junit.BeforeClass;
@@ -45,10 +62,17 @@
 import org.junit.runners.MethodSorters;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
+import org.testcontainers.azure.AzuriteContainer;
+import org.testcontainers.utility.MountableFile;

+import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
 import com.azure.storage.blob.BlobServiceClient;
 import com.azure.storage.blob.BlobServiceClientBuilder;
-import com.azure.storage.common.StorageSharedKeyCredential;
+
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import reactor.netty.http.client.HttpClient;

 /**
  * Run tests in cloud deployment environment
@@ -62,40 +86,78 @@
     private final TestCaseContext tcCtx;
     private static final String SUITE_TESTS = "testsuite_cloud_storage.xml";
     private static final String ONLY_TESTS = 
"testsuite_cloud_storage_only.xml";
-    private static final String CONFIG_FILE_NAME = 
"src/test/resources/cc-cloud-storage-azblob.conf";
+    private static final String CONFIG_FILE = 
"target/cc-cloud-storage-azblob.conf";
+    private static final String CONFIG_FILE_TEMPLATE = 
"src/test/resources/cc-cloud-storage-azblob.ftl";
     private static final String DELTA_RESULT_PATH = "results_cloud";
     private static final String EXCLUDED_TESTS = "MP";

+    private static AzuriteContainer azBlob;
+
     public CloudStorageAzTest(TestCaseContext tcCtx) {
         this.tcCtx = tcCtx;
     }

+    private static void generateSelfSignedTLS() throws Exception {
+        java.security.Security.addProvider(new 
org.bouncycastle.jce.provider.BouncyCastleProvider());
+        KeyPairGenerator keyPairGenerator = 
KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(2048);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        PublicKey publicKey = keyPair.getPublic();
+        PrivateKey privateKey = keyPair.getPrivate();
+        long now = System.currentTimeMillis();
+        Date startDate = new Date(now);
+        X500Name dnName = new X500Name("CN=asterixdb azure test");
+        BigInteger certSerialNumber = new BigInteger(Long.toString(now));
+        Date endDate = new Date(now + 24 * 60 * 60 * 1000L); // 1 day validity
+        SubjectPublicKeyInfo subjectPublicKeyInfo = 
SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
+        X509v3CertificateBuilder certificateBuilder = new 
X509v3CertificateBuilder(dnName, certSerialNumber, startDate,
+                endDate, dnName, subjectPublicKeyInfo);
+        JcaContentSignerBuilder contentSignerBuilder = new 
JcaContentSignerBuilder("SHA256WithRSA");
+        X509Certificate selfSignedCertificate = new 
JcaX509CertificateConverter().setProvider("BC")
+                
.getCertificate(certificateBuilder.build(contentSignerBuilder.build(privateKey)));
+        KeyStore keyStore = KeyStore.getInstance("PKCS12");
+        keyStore.load(null, null);
+        keyStore.setKeyEntry("mytestcert", privateKey, 
"password".toCharArray(),
+                new java.security.cert.Certificate[] { selfSignedCertificate 
});
+        try (FileOutputStream fos = new FileOutputStream("target" + 
File.separator + "azure_test.pfx")) {
+            keyStore.store(fos, "password".toCharArray());
+        }
+    }
+
     @BeforeClass
     public static void setUp() throws Exception {
-        String endpointString = "http://127.0.0.1:15055/devstoreaccount1/"; + 
CLOUD_STORAGE_BUCKET;
-        final String accKey =
-                
"Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
-        final String accName = "devstoreaccount1";
-
-        BlobServiceClient blobServiceClient = new 
BlobServiceClientBuilder().endpoint(endpointString)
-                .credential(new StorageSharedKeyCredential(accName, 
accKey)).buildClient();
+        LocalCloudUtilAdobeMock.startS3CloudEnvironment(true, true);
+        generateSelfSignedTLS();
+        MountableFile azureCert = 
MountableFile.forHostPath("target/azure_test.pfx");
+        azBlob = new 
AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.35.0").withSsl(azureCert,
 "password");
+        azBlob.start();
+        SslContext insecureSslContext =
+                
SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
+        BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
+                .connectionString(azBlob.getConnectionString())
+                .httpClient(new NettyAsyncHttpClientBuilder(
+                        HttpClient.create().secure(sslSpec -> 
sslSpec.sslContext(insecureSslContext).build())).build())
+                .buildClient();
+        URI blobStore = URI.create(blobServiceClient.getAccountUrl());
+        String endpoint = blobStore.getScheme() + "://" + 
blobStore.getAuthority();
+        fillConfigTemplate(endpoint, CONFIG_FILE_TEMPLATE, CONFIG_FILE);

         cleanup(blobServiceClient);
         initialize(blobServiceClient);

-        //storage.close(); WHAT IS THIS FOR IN GCS
-
         TestExecutor testExecutor = new TestExecutor(DELTA_RESULT_PATH);
         testExecutor.executorId = "cloud";
         testExecutor.stripSubstring = "//DB:";
-        LangExecutionUtil.setUp(CONFIG_FILE_NAME, testExecutor);
-        System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, 
CONFIG_FILE_NAME);
+        LangExecutionUtil.setUp(CONFIG_FILE, testExecutor);
+        System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, CONFIG_FILE);
     }

     @AfterClass
     public static void tearDown() throws Exception {
         LangExecutionUtil.tearDown();
         LocalCloudUtilAdobeMock.shutdownSilently();
+        azBlob.close();
+        azBlob.stop();
     }

     @Parameters(name = "CloudStorageAzBlobTest {index}: {0}")
diff --git 
a/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.conf 
b/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.conf
index 409b99b..ad87368 100644
--- a/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.conf
+++ b/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.conf
@@ -69,6 +69,7 @@
 cloud.storage.scheme=azblob
 cloud.storage.bucket=cloud-storage-container
 cloud.storage.region=us-east-2
-cloud.storage.endpoint=http://127.0.0.1:15055
-cloud.storage.anonymous.auth=true
+cloud.storage.endpoint=https://localhost:39667
+cloud.storage.anonymous.auth=false
+cloud.storage.disable.ssl.verify=true
 cloud.storage.cache.policy=lazy
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.ftl 
b/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.ftl
new file mode 100644
index 0000000..91d87cd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/cc-cloud-storage-azblob.ftl
@@ -0,0 +1,74 @@
+; Licensed to the Apache Software Foundation (ASF) under one
+; or more contributor license agreements.  See the NOTICE file
+; distributed with this work for additional information
+; regarding copyright ownership.  The ASF licenses this file
+; to you 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.
+
+[nc/asterix_nc1]
+txn.log.dir=target/tmp/asterix_nc1/txnlog
+core.dump.dir=target/tmp/asterix_nc1/coredump
+iodevices=target/tmp/asterix_nc1/iodevice1
+iodevices=../asterix-server/target/tmp/asterix_nc1/iodevice2
+nc.api.port=19004
+#jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
+
+[nc/asterix_nc2]
+ncservice.port=9091
+txn.log.dir=target/tmp/asterix_nc2/txnlog
+core.dump.dir=target/tmp/asterix_nc2/coredump
+iodevices=target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+nc.api.port=19005
+#jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007
+
+[nc]
+credential.file=src/test/resources/security/passwd
+python.cmd.autolocate=true
+python.env=FOO=BAR=BAZ,BAR=BAZ
+address=127.0.0.1
+command=asterixnc
+app.class=org.apache.asterix.hyracks.bootstrap.NCApplication
+jvm.args=-Xmx4096m 
-Dnode.Resolver="org.apache.asterix.external.util.IdentitiyResolverFactory"
+storage.buffercache.size=128MB
+storage.memorycomponent.globalbudget=512MB
+storage.max.columns.in.zeroth.segment=800
+
+[cc]
+address = 127.0.0.1
+app.class=org.apache.asterix.hyracks.bootstrap.CCApplication
+heartbeat.period=2000
+heartbeat.max.misses=25
+credential.file=src/test/resources/security/passwd
+
+[common]
+log.dir = logs/
+log.level = INFO
+compiler.framesize=32KB
+compiler.sortmemory=320KB
+compiler.groupmemory=160KB
+compiler.joinmemory=256KB
+compiler.textsearchmemory=160KB
+compiler.windowmemory=192KB
+compiler.ordered.fields=false
+compiler.internal.sanitycheck=true
+messaging.frame.size=4096
+messaging.frame.count=512
+cloud.deployment=true
+storage.buffercache.pagesize=32KB
+storage.partitioning=static
+cloud.storage.scheme=azblob
+cloud.storage.bucket=cloud-storage-container
+cloud.storage.region=us-east-2
+cloud.storage.endpoint=${cloudUrl}/devstoreaccount1
+cloud.storage.disable.ssl.verify=true
+cloud.storage.cache.policy=lazy
\ No newline at end of file
diff --git a/asterixdb/pom.xml b/asterixdb/pom.xml
index 74f4271..d6b9faf 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -650,6 +650,11 @@
               ${coverageArgLine}
               ${extraSurefireArgLine}
             </argLine>
+            <environmentVariables>
+              <!-->Public/dummy test credentials for Azurite tests<!-->
+              <AZURE_STORAGE_ACCOUNT>devstoreaccount1</AZURE_STORAGE_ACCOUNT>
+              
<AZURE_STORAGE_KEY>Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==</AZURE_STORAGE_KEY>
+            </environmentVariables>
             <includes>
               <include>${test.includes}</include>
             </includes>
@@ -1697,6 +1702,11 @@
         <version>42.2.24</version>
       </dependency>
       <dependency>
+        <groupId>org.testcontainers</groupId>
+        <artifactId>azure</artifactId>
+        <version>1.21.3</version>
+      </dependency>
+      <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpmime</artifactId>
         <version>4.5.14</version>

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20432?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: phoenix
Gerrit-Change-Id: Iad1a6f9331fd844f3e3c04b8f56e811e4227f83e
Gerrit-Change-Number: 20432
Gerrit-PatchSet: 1
Gerrit-Owner: Ian Maxon <[email protected]>

Reply via email to