JAMES-2525 implements Keystone v3 ObjectStorageBlobsDAOBuilder

Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/be1702dd
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/be1702dd
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/be1702dd

Branch: refs/heads/master
Commit: be1702ddc7d0be43bfbe833cd660d6cb172254ef
Parents: 1c47e2f
Author: Jean Helou <j...@codamens.fr>
Authored: Fri Aug 31 18:09:54 2018 +0200
Committer: Benoit Tellier <btell...@linagora.com>
Committed: Fri Oct 5 18:11:43 2018 +0700

----------------------------------------------------------------------
 server/blob/blob-objectstorage/pom.xml          |   6 +
 .../objectstorage/ObjectStorageBlobsDAO.java    |   5 +
 .../swift/SwiftKeystone3ObjectStorage.java      | 244 +++++++++++++++++++
 .../objectstorage/DockerSwiftExtension.java     |   6 +-
 .../ObjectStorageBlobsDAOContract.java          |  12 +-
 ...ystone2ObjectStorageBlobsDAOBuilderTest.java |  18 +-
 ...ystone3ObjectStorageBlobsDAOBuilderTest.java | 128 ++++++++++
 ...Keystone3ObjectStorageConfigurationTest.java | 161 ++++++++++++
 ...empAuthObjectStorageBlobsDAOBuilderTest.java |  23 +-
 9 files changed, 572 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/pom.xml
----------------------------------------------------------------------
diff --git a/server/blob/blob-objectstorage/pom.xml 
b/server/blob/blob-objectstorage/pom.xml
index 8e4eb44..3b895b5 100644
--- a/server/blob/blob-objectstorage/pom.xml
+++ b/server/blob/blob-objectstorage/pom.xml
@@ -96,10 +96,16 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.testcontainers</groupId>
             <artifactId>testcontainers</artifactId>
             <scope>test</scope>
         </dependency>
+
     </dependencies>
     
 </project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
index 478bb67..176e5a4 100644
--- 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
+++ 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAO.java
@@ -29,6 +29,7 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.ObjectStoreException;
 import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
+import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
 import org.jclouds.blobstore.domain.Blob;
 import org.jclouds.blobstore.options.CopyOptions;
@@ -62,6 +63,10 @@ public class ObjectStorageBlobsDAO implements BlobStore {
         return SwiftKeystone2ObjectStorage.daoBuilder(testConfig);
     }
 
+    public static ObjectStorageBlobsDAOBuilder 
builder(SwiftKeystone3ObjectStorage.Configuration testConfig) {
+        return SwiftKeystone3ObjectStorage.daoBuilder(testConfig);
+    }
+
     @Override
     public CompletableFuture<BlobId> save(byte[] data) {
         return save(new ByteArrayInputStream(data));

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorage.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorage.java
 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorage.java
new file mode 100644
index 0000000..e544735
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorage.java
@@ -0,0 +1,244 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.objectstorage.swift;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.function.Supplier;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.apache.james.util.OptionalUtils;
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.swift.v1.blobstore.RegionScopedBlobStoreContext;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+public class SwiftKeystone3ObjectStorage {
+    private static final Iterable<Module> JCLOUDS_MODULES =
+        ImmutableSet.of(new SLF4JLoggingModule());
+
+    public static ObjectStorageBlobsDAOBuilder daoBuilder(Configuration 
testConfig) {
+        return new ObjectStorageBlobsDAOBuilder(new 
BlobStoreBuilder(testConfig));
+    }
+
+    public static Configuration.Builder configBuilder() {
+        return new Configuration.Builder();
+    }
+
+    public static class BlobStoreBuilder implements Supplier<BlobStore> {
+        private final Configuration testConfig;
+
+        private BlobStoreBuilder(Configuration testConfig) {
+            this.testConfig = testConfig;
+        }
+
+        @Override
+        public BlobStore get() {
+            RegionScopedBlobStoreContext blobStoreContext = contextBuilder()
+                .endpoint(testConfig.getEndpoint().toString())
+                .credentials(testConfig.getIdentity().asString(), 
testConfig.getCredentials().value())
+                .overrides(testConfig.getOverrides())
+                .modules(JCLOUDS_MODULES)
+                .buildView(RegionScopedBlobStoreContext.class);
+
+            return testConfig.getRegion()
+                .map(Region::value)
+                .map(blobStoreContext::getBlobStore)
+                .orElseGet(blobStoreContext::getBlobStore);
+        }
+
+        private ContextBuilder contextBuilder() {
+            return ContextBuilder.newBuilder("openstack-swift");
+        }
+    }
+
+    public static final class Configuration {
+        public static class Builder {
+            private URI endpoint;
+            private UserName userName;
+            private DomainName domainName;
+            private Credentials credentials;
+            private Optional<Region> region;
+            private Optional<Project> project;
+            private Optional<DomainId> domainId;
+
+            private Builder() {
+                region = Optional.empty();
+                project = Optional.empty();
+                domainId = Optional.empty();
+            }
+
+            public Builder endpoint(URI endpoint) {
+                this.endpoint = endpoint;
+                return this;
+            }
+
+            public Builder identity(IdentityV3 identity) {
+                this.domainName = identity.getDomainName();
+                this.userName = identity.getUserName();
+                return this;
+            }
+
+            public Builder credentials(Credentials credentials) {
+                this.credentials = credentials;
+                return this;
+            }
+
+            public Builder region(Region region) {
+                this.region = Optional.of(region);
+                return this;
+            }
+
+            public Builder domainId(DomainId domainId) {
+                this.domainId = Optional.of(domainId);
+                return this;
+            }
+
+            public Builder project(Project project) {
+                this.project = Optional.of(project);
+                return this;
+            }
+
+            public Configuration build() {
+                Preconditions.checkState(endpoint != null);
+                Preconditions.checkState(domainName != null);
+                Preconditions.checkState(userName != null);
+                Preconditions.checkState(credentials != null);
+                IdentityV3 identity = IdentityV3.of(domainName, userName);
+                return new Configuration(endpoint, identity, credentials, 
region, project, domainId);
+            }
+        }
+
+        private final URI endpoint;
+        private final IdentityV3 identity;
+        private final Optional<Region> region;
+        private final Credentials credentials;
+        private final Optional<Project> project;
+        private final Optional<DomainId> domainId;
+
+        private Configuration(URI endpoint,
+                              IdentityV3 identity,
+                              Credentials credentials,
+                              Optional<Region> region,
+                              Optional<Project> project,
+                              Optional<DomainId> domainId) {
+            this.endpoint = endpoint;
+            this.identity = identity;
+            this.region = region;
+            this.credentials = credentials;
+            this.project = project;
+            this.domainId = domainId;
+        }
+
+        public URI getEndpoint() {
+            return endpoint;
+        }
+
+        public IdentityV3 getIdentity() {
+            return identity;
+        }
+
+        public Credentials getCredentials() {
+            return credentials;
+        }
+
+        public Properties getOverrides() {
+            Properties properties = new Properties();
+            properties.setProperty(KeystoneProperties.KEYSTONE_VERSION, "3");
+            OptionalUtils.or(
+                project.map(project -> setScope(project)),
+                domainId.map(domain -> setScope(domain))
+            ).ifPresent(scopeProps ->
+                properties.putAll(scopeProps)
+            );
+            return properties;
+        }
+
+        private Properties setScope(DomainId domainId) {
+            Properties properties = new Properties();
+            properties.setProperty(KeystoneProperties.SCOPE, 
domainId.asString());
+            return properties;
+        }
+
+        private Properties setScope(Project project) {
+            Properties properties = new Properties();
+            properties.setProperty(KeystoneProperties.SCOPE, 
project.name().asString());
+            project.domainName()
+                .map(domain -> Pair.of(KeystoneProperties.PROJECT_DOMAIN_NAME, 
domain));
+            OptionalUtils.or(
+                project.domainName()
+                    .map(domain -> 
Pair.of(KeystoneProperties.PROJECT_DOMAIN_NAME, domain.value())),
+                project.domainId()
+                    .map(domain -> 
Pair.of(KeystoneProperties.PROJECT_DOMAIN_ID, domain.value()))
+            ).ifPresent(pair ->
+                properties.setProperty(pair.getKey(), pair.getValue())
+            );
+
+            return properties;
+        }
+
+        public Optional<Region> getRegion() {
+            return region;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Configuration that = (Configuration) o;
+            return Objects.equal(endpoint, that.endpoint) &&
+                Objects.equal(identity, that.identity) &&
+                Objects.equal(region, that.region) &&
+                Objects.equal(credentials, that.credentials) &&
+                Objects.equal(project, that.project) &&
+                Objects.equal(domainId, that.domainId);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(endpoint, identity, region, credentials, 
project, domainId);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("endpoint", endpoint)
+                .add("identity", identity)
+                .add("region", region)
+                .add("credentials", credentials)
+                .add("project", project)
+                .add("domainId", domainId)
+                .toString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/DockerSwiftExtension.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/DockerSwiftExtension.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/DockerSwiftExtension.java
index 48b2d3a..b30bd44 100644
--- 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/DockerSwiftExtension.java
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/DockerSwiftExtension.java
@@ -81,8 +81,10 @@ public class DockerSwiftExtension implements 
ParameterResolver, BeforeAllCallbac
         }
         URI keystoneV2Endpoint =
             URI.create("http://"; + containerIpAddress + ":" + keystonePort + 
"/v2.0");
-        URI keystoneV3Endpoint = URI.create("http://"; + containerIpAddress + 
":" + keystonePort + "/v3");
-        URI swiftEndpoint = URI.create("http://"; + containerIpAddress + ":" + 
swiftPort + "/auth/v1.0");
+        URI keystoneV3Endpoint =
+            URI.create("http://"; + containerIpAddress + ":" + keystonePort + 
"/v3");
+        URI swiftEndpoint =
+            URI.create("http://"; + containerIpAddress + ":" + swiftPort + 
"/auth/v1.0");
         dockerSwift = new DockerSwift(keystoneV2Endpoint, keystoneV3Endpoint, 
swiftEndpoint);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOContract.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOContract.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOContract.java
index 07da03b..a6cb4b4 100644
--- 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOContract.java
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOContract.java
@@ -25,25 +25,23 @@ import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
 
 import org.apache.james.blob.api.BlobId;
 import org.jclouds.blobstore.BlobStore;
 import org.jclouds.domain.Location;
-import org.junit.jupiter.api.Test;
 
 public interface ObjectStorageBlobsDAOContract {
 
-    ObjectStorageBlobsDAOBuilder builder();
-
     Location DEFAULT_LOCATION = null;
 
     ContainerName containerName();
 
-    @Test
-    default void builtBlobsDAOCanStoreAndRetrieve() throws Exception {
-        ObjectStorageBlobsDAOBuilder builder = builder();
-
+    default void 
assertBlobsDAOCanStoreAndRetrieve(ObjectStorageBlobsDAOBuilder builder)
+        throws InterruptedException, ExecutionException, TimeoutException {
         BlobStore blobStore = builder.getSupplier().get();
         blobStore.createContainerInLocation(DEFAULT_LOCATION, 
containerName().value());
         ObjectStorageBlobsDAO dao = builder.build();

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone2ObjectStorageBlobsDAOBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone2ObjectStorageBlobsDAOBuilderTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone2ObjectStorageBlobsDAOBuilderTest.java
index 8821d31..36e01fe 100644
--- 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone2ObjectStorageBlobsDAOBuilderTest.java
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone2ObjectStorageBlobsDAOBuilderTest.java
@@ -58,14 +58,6 @@ class SwiftKeystone2ObjectStorageBlobsDAOBuilderTest 
implements ObjectStorageBlo
     }
 
     @Override
-    public ObjectStorageBlobsDAOBuilder builder() {
-        return ObjectStorageBlobsDAO
-            .builder(testConfig)
-            .container(containerName)
-            .blobIdFactory(new HashBlobId.Factory());
-    }
-
-    @Override
     public ContainerName containerName() {
         return containerName;
     }
@@ -87,4 +79,14 @@ class SwiftKeystone2ObjectStorageBlobsDAOBuilderTest 
implements ObjectStorageBlo
 
         
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
     }
+
+    @Test
+    public void builtBlobsDAOCanStoreAndRetrieve() throws Exception {
+        ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
+            .builder(testConfig)
+            .container(containerName)
+            .blobIdFactory(new HashBlobId.Factory());
+
+        assertBlobsDAOCanStoreAndRetrieve(builder);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageBlobsDAOBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageBlobsDAOBuilderTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageBlobsDAOBuilderTest.java
new file mode 100644
index 0000000..db5edd3
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageBlobsDAOBuilderTest.java
@@ -0,0 +1,128 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.objectstorage.swift;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.james.blob.api.HashBlobId;
+import org.apache.james.blob.objectstorage.ContainerName;
+import org.apache.james.blob.objectstorage.DockerSwift;
+import org.apache.james.blob.objectstorage.DockerSwiftExtension;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAO;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOContract;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@ExtendWith(DockerSwiftExtension.class)
+class SwiftKeystone3ObjectStorageBlobsDAOBuilderTest implements 
ObjectStorageBlobsDAOContract {
+
+    private static final DomainName DOMAIN_NAME = DomainName.of("Default");
+    private static final DomainId DOMAIN_ID = DomainId.of("default");
+    private static final ProjectName PROJECT_NAME = ProjectName.of("test");
+    private static final UserName DEMO_USER_NAME = UserName.of("demo");
+    private static final Credentials DEMO_PASSWORD = Credentials.of("demo");
+    private static final IdentityV3 DEMO_IDENTITY = IdentityV3.of(DOMAIN_NAME, 
DEMO_USER_NAME);
+
+    private static final String PROJECT_CONFIG_KEY = "PROJECT_CONFIG_KEY";
+    private static final SwiftKeystone3ObjectStorage.Configuration.Builder 
PROJECT_CONFIG =
+         SwiftKeystone3ObjectStorage.configBuilder()
+            .identity(DEMO_IDENTITY)
+            .credentials(DEMO_PASSWORD)
+            .project(Project.of(PROJECT_NAME));
+
+    private static final String PROJECT_DOMAIN_NAME_KEY = 
"PROJECT_DOMAIN_NAME_KEY";
+    private static final SwiftKeystone3ObjectStorage.Configuration.Builder 
PROJECT_DOMAIN_NAME_SCOPE =
+        SwiftKeystone3ObjectStorage.configBuilder()
+            .identity(DEMO_IDENTITY)
+            .credentials(DEMO_PASSWORD)
+            .project(Project.of(PROJECT_NAME, DOMAIN_NAME));
+
+    private static final String PROJECT_DOMAIN_ID_KEY = 
"PROJECT_DOMAIN_ID_KEY";
+    private static final SwiftKeystone3ObjectStorage.Configuration.Builder 
PROJECT_DOMAIN_ID_SCOPE =
+        SwiftKeystone3ObjectStorage.configBuilder()
+            .identity(DEMO_IDENTITY)
+            .credentials(DEMO_PASSWORD)
+            .project(Project.of(PROJECT_NAME, DOMAIN_ID));
+
+    private ContainerName containerName;
+
+    private SwiftKeystone3ObjectStorage.Configuration testConfig;
+    private DockerSwift dockerSwift;
+    private Map<String, SwiftKeystone3ObjectStorage.Configuration.Builder> 
configBuilders;
+
+    @BeforeEach
+    void setUp(DockerSwift dockerSwift) throws Exception {
+        this.dockerSwift = dockerSwift;
+        containerName = ContainerName.of(UUID.randomUUID().toString());
+        testConfig = PROJECT_CONFIG
+            .endpoint(dockerSwift.keystoneV3Endpoint())
+            .build();
+        configBuilders = new HashMap<>();
+        // There should be 2 more modes: unscoped and domain-scoped
+        // but the docker image doesn't support them...
+        configBuilders.put(PROJECT_CONFIG_KEY, PROJECT_CONFIG);
+        configBuilders.put(PROJECT_DOMAIN_ID_KEY, PROJECT_DOMAIN_ID_SCOPE);
+        configBuilders.put(PROJECT_DOMAIN_NAME_KEY, PROJECT_DOMAIN_NAME_SCOPE);
+    }
+
+    @Override
+    public ContainerName containerName() {
+        return containerName;
+    }
+
+    @Test
+    void containerNameIsMandatoryToBuildBlobsDAO() throws Exception {
+        ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
+            .builder(testConfig)
+            .blobIdFactory(new HashBlobId.Factory());
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void blobIdFactoryIsMandatoryToBuildBlobsDAO() throws Exception {
+        ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
+            .builder(testConfig)
+            .container(containerName);
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {PROJECT_CONFIG_KEY, PROJECT_DOMAIN_ID_KEY, 
PROJECT_DOMAIN_NAME_KEY})
+    public void builtBlobsDAOCanStoreAndRetrieve(String key) throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration config =
+            
configBuilders.get(key).endpoint(dockerSwift.keystoneV3Endpoint()).build();
+        ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
+            .builder(config)
+            .container(containerName)
+            .blobIdFactory(new HashBlobId.Factory());
+
+        assertBlobsDAOCanStoreAndRetrieve(builder);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageConfigurationTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageConfigurationTest.java
new file mode 100644
index 0000000..90530ae
--- /dev/null
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftKeystone3ObjectStorageConfigurationTest.java
@@ -0,0 +1,161 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+package org.apache.james.blob.objectstorage.swift;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.net.URI;
+
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class SwiftKeystone3ObjectStorageConfigurationTest {
+
+    private static final ProjectName PROJECT_NAME = ProjectName.of("project");
+    private static URI ENDPOINT = URI.create("http://example.com";);
+    private static Credentials CREDENTIALS = Credentials.of("fake");
+    private static final DomainName DOMAIN_NAME = DomainName.of("fake");
+    private static final DomainId DOMAIN_ID = DomainId.of("fake");
+    private static IdentityV3 SWIFT_IDENTITY =
+        IdentityV3.of(DOMAIN_NAME, UserName.of("fake"));
+
+    @Test
+    void enpointIsMandatoryToBuildConfiguration() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .identity(SWIFT_IDENTITY)
+            .credentials(CREDENTIALS);
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void identityIsMandatoryToBuildConfiguration() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .credentials(CREDENTIALS);
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void credentialsIsMandatoryToBuildConfiguration() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY);
+
+        
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void configurationIsBuiltWhenAllMandatoryParamsAreProvided() throws 
Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY)
+            .credentials(CREDENTIALS);
+
+        SwiftKeystone3ObjectStorage.Configuration build = builder.build();
+
+        assertThat(build.getEndpoint()).isEqualTo(ENDPOINT);
+        assertThat(build.getIdentity()).isEqualTo(SWIFT_IDENTITY);
+        assertThat(build.getCredentials()).isEqualTo(CREDENTIALS);
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.KEYSTONE_VERSION)).isEqualTo("3");
+    }
+
+    @Test
+    void authCanBeProjectScoped() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY)
+            .project(Project.of(PROJECT_NAME))
+            .credentials(CREDENTIALS);
+
+        SwiftKeystone3ObjectStorage.Configuration build = builder.build();
+
+        assertThat(build.getEndpoint()).isEqualTo(ENDPOINT);
+        assertThat(build.getIdentity()).isEqualTo(SWIFT_IDENTITY);
+        assertThat(build.getCredentials()).isEqualTo(CREDENTIALS);
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.SCOPE)).isEqualTo(PROJECT_NAME.asString());
+    }
+
+    @Test
+    void authCanBeProjectAndDomainNameScoped() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY)
+            .project(Project.of(PROJECT_NAME, DOMAIN_NAME))
+            .credentials(CREDENTIALS);
+
+        SwiftKeystone3ObjectStorage.Configuration build = builder.build();
+
+        assertThat(build.getEndpoint()).isEqualTo(ENDPOINT);
+        assertThat(build.getIdentity()).isEqualTo(SWIFT_IDENTITY);
+        assertThat(build.getCredentials()).isEqualTo(CREDENTIALS);
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.SCOPE)).isEqualTo(PROJECT_NAME.asString());
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.PROJECT_DOMAIN_NAME)).isEqualTo(DOMAIN_NAME.value());
+    }
+
+    @Test
+    void authCanBeProjectAndDomainIdScoped() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY)
+            .project(Project.of(PROJECT_NAME, DOMAIN_ID))
+            .credentials(CREDENTIALS);
+
+        SwiftKeystone3ObjectStorage.Configuration build = builder.build();
+
+        assertThat(build.getEndpoint()).isEqualTo(ENDPOINT);
+        assertThat(build.getIdentity()).isEqualTo(SWIFT_IDENTITY);
+        assertThat(build.getCredentials()).isEqualTo(CREDENTIALS);
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.SCOPE)).isEqualTo(PROJECT_NAME.asString());
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.PROJECT_DOMAIN_ID)).isEqualTo(DOMAIN_ID.value());
+    }
+
+    @Test
+    void authCanBeDomainIdScoped() throws Exception {
+        SwiftKeystone3ObjectStorage.Configuration.Builder builder =
+            SwiftKeystone3ObjectStorage.configBuilder()
+            .endpoint(ENDPOINT)
+            .identity(SWIFT_IDENTITY)
+            .domainId(DOMAIN_ID)
+            .credentials(CREDENTIALS);
+
+        SwiftKeystone3ObjectStorage.Configuration build = builder.build();
+
+        assertThat(build.getEndpoint()).isEqualTo(ENDPOINT);
+        assertThat(build.getIdentity()).isEqualTo(SWIFT_IDENTITY);
+        assertThat(build.getCredentials()).isEqualTo(CREDENTIALS);
+        
assertThat(build.getOverrides().getProperty(KeystoneProperties.SCOPE)).isEqualTo(DOMAIN_ID.asString());
+    }
+
+    @Test
+    void configurationShouldEnforceBeanContract() {
+        
EqualsVerifier.forClass(SwiftKeystone3ObjectStorage.Configuration.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/be1702dd/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftTempAuthObjectStorageBlobsDAOBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftTempAuthObjectStorageBlobsDAOBuilderTest.java
 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftTempAuthObjectStorageBlobsDAOBuilderTest.java
index c44c1ad..7095624 100644
--- 
a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftTempAuthObjectStorageBlobsDAOBuilderTest.java
+++ 
b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/swift/SwiftTempAuthObjectStorageBlobsDAOBuilderTest.java
@@ -19,18 +19,11 @@
 
 package org.apache.james.blob.objectstorage.swift;
 
-import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
 import java.net.URI;
-import java.nio.charset.StandardCharsets;
 import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
 
-import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.objectstorage.ContainerName;
 import org.apache.james.blob.objectstorage.DockerSwift;
@@ -66,6 +59,11 @@ class SwiftTempAuthObjectStorageBlobsDAOBuilderTest 
implements ObjectStorageBlob
             .build();
     }
 
+    @Override
+    public ContainerName containerName() {
+        return containerName;
+    }
+
     @Test
     void containerNameIsMandatoryToBuildBlobsDAO() throws Exception {
         ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
@@ -84,16 +82,13 @@ class SwiftTempAuthObjectStorageBlobsDAOBuilderTest 
implements ObjectStorageBlob
         
assertThatThrownBy(builder::build).isInstanceOf(IllegalStateException.class);
     }
 
-    @Override
-    public ObjectStorageBlobsDAOBuilder builder() {
-        return ObjectStorageBlobsDAO
+    @Test
+    public void builtBlobsDAOCanStoreAndRetrieve() throws Exception {
+        ObjectStorageBlobsDAOBuilder builder = ObjectStorageBlobsDAO
             .builder(testConfig)
             .container(containerName)
             .blobIdFactory(new HashBlobId.Factory());
-    }
 
-    @Override
-    public ContainerName containerName() {
-        return containerName;
+        assertBlobsDAOCanStoreAndRetrieve(builder);
     }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to