You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by al...@apache.org on 2021/03/18 21:36:48 UTC

[camel-quarkus] branch master updated: openstack: added keystone tests #1943

This is an automated email from the ASF dual-hosted git repository.

aldettinger pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/master by this push:
     new 5cfe78c  openstack: added keystone tests #1943
5cfe78c is described below

commit 5cfe78c9c080e0dbbece19b6c61cf6b52fc9f9c6
Author: aldettinger <al...@gmail.com>
AuthorDate: Wed Mar 17 10:30:54 2021 +0100

    openstack: added keystone tests #1943
---
 .../it/OpenstackKeystoneDomainResource.java        | 122 +++++++++++++++
 .../it/OpenstackKeystoneGroupResource.java         | 169 +++++++++++++++++++++
 .../it/OpenstackKeystoneProjectResource.java       | 143 +++++++++++++++++
 .../it/OpenstackKeystoneRegionResource.java        | 133 ++++++++++++++++
 .../it/OpenstackKeystoneUserResource.java          | 126 +++++++++++++++
 .../openstack/it/OpenstackKeystoneDomainTest.java  |  53 +++++++
 .../openstack/it/OpenstackKeystoneGroupTest.java   |  68 +++++++++
 .../openstack/it/OpenstackKeystoneProjectTest.java |  53 +++++++
 .../openstack/it/OpenstackKeystoneRegionTest.java  |  58 +++++++
 .../openstack/it/OpenstackKeystoneUserTest.java    |  53 +++++++
 .../keystone/domains/domains_create_response.json  |  18 +++
 .../mappings/keystone/domains/domains_delete.json  |  20 +++
 .../keystone/domains/domains_get_byId.json         |  19 +++
 .../keystone/domains/domains_update_response.json  |  18 +++
 .../keystone/domains/domains_with_options.json     |  18 +++
 .../mappings/keystone/groups/groups_add_user.json  |  20 +++
 .../keystone/groups/groups_check_user.json         |  20 +++
 .../keystone/groups/groups_create_response.json    |  18 +++
 .../mappings/keystone/groups/groups_delete.json    |  20 +++
 .../mappings/keystone/groups/groups_get_byId.json  |  18 +++
 .../mappings/keystone/groups/groups_list.json      |  22 +++
 .../keystone/groups/groups_remove_user.json        |  20 +++
 .../keystone/groups/groups_update_response.json    |  18 +++
 .../projects/projects_create_response.json         |  18 +++
 .../keystone/projects/projects_delete.json         |  20 +++
 .../keystone/projects/projects_get_byId.json       |  18 +++
 .../projects/projects_update_response.json         |  18 +++
 .../keystone/projects/projects_with_options.json   |  18 +++
 .../keystone/regions/regions_create_response.json  |  18 +++
 .../mappings/keystone/regions/regions_delete.json  |  20 +++
 .../keystone/regions/regions_get_byId.json         |  18 +++
 .../keystone/regions/regions_get_nonExistent.json  |  22 +++
 .../mappings/keystone/regions/regions_list.json    |  22 +++
 .../keystone/regions/regions_update_response.json  |  18 +++
 .../mappings/keystone/users/create_user.json       |  18 +++
 .../mappings/keystone/users/update_user.json       |  18 +++
 .../mappings/keystone/users/user_delete.json       |  20 +++
 .../mappings/keystone/users/user_get_byId.json     |  18 +++
 .../resources/mappings/keystone/users/users.json   |  22 +++
 39 files changed, 1533 insertions(+)

diff --git a/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainResource.java b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainResource.java
new file mode 100644
index 0000000..9930518
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainResource.java
@@ -0,0 +1,122 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openstack.common.OpenstackConstants;
+import org.apache.camel.component.openstack.keystone.KeystoneConstants;
+import org.jboss.logging.Logger;
+import org.openstack4j.api.Builders;
+import org.openstack4j.model.identity.v3.Domain;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Path("/openstack/keystone/domains/")
+@ApplicationScoped
+public class OpenstackKeystoneDomainResource {
+
+    private static final Logger LOG = Logger.getLogger(OpenstackKeystoneDomainResource.class);
+
+    private static final String URI_FORMAT = "openstack-keystone://{{camel.openstack.test.host-url}}?username=user&password=secret&project=project&operation=%s&subsystem="
+            + KeystoneConstants.DOMAINS;
+
+    private static final String DOMAIN_NAME = "Domain_CRUD";
+    private static final String DOMAIN_ID = "98c110ae41c249189c9d5c25d8377b65";
+    private static final String DOMAIN_DESCRIPTION = "Domain used for CRUD tests";
+    private static final String DOMAIN_DESCRIPTION_UPDATED = "An updated domain used for CRUD tests";
+
+    @Inject
+    ProducerTemplate template;
+
+    @Path("/createShouldSucceed")
+    @POST
+    public void createShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneDomainResource.createShouldSucceed()");
+
+        Domain in = Builders.domain().name(DOMAIN_NAME).description(DOMAIN_DESCRIPTION).enabled(true).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.CREATE);
+        Domain out = template.requestBody(uri, in, Domain.class);
+
+        assertNotNull(out);
+        assertEquals(DOMAIN_NAME, out.getName());
+        assertEquals(DOMAIN_ID, out.getId());
+        assertEquals(DOMAIN_DESCRIPTION, out.getDescription());
+    }
+
+    @Path("/getShouldSucceed")
+    @POST
+    public void getShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneDomainResource.getShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        Domain out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, DOMAIN_ID, Domain.class);
+
+        assertNotNull(out);
+        assertEquals(DOMAIN_NAME, out.getName());
+        assertEquals(DOMAIN_ID, out.getId());
+        assertEquals(DOMAIN_DESCRIPTION, out.getDescription());
+        assertFalse(out.isEnabled());
+    }
+
+    @Path("/getAllShouldSucceed")
+    @POST
+    public void getAllShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneDomainResource.getAllShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET_ALL);
+        Domain[] domains = template.requestBody(uri, null, Domain[].class);
+
+        assertEquals(1, domains.length);
+        assertEquals("default", domains[0].getId());
+        assertNotNull(domains[0].getOptions());
+        assertTrue(domains[0].getOptions().isEmpty());
+    }
+
+    @Path("/updateShouldSucceed")
+    @POST
+    public void updateShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneDomainResource.updateShouldSucceed()");
+
+        Domain in = Builders.domain().name(DOMAIN_NAME).description(DOMAIN_DESCRIPTION_UPDATED).id(DOMAIN_ID).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.UPDATE);
+        Domain out = template.requestBody(uri, in, Domain.class);
+
+        assertNotNull(out);
+        assertEquals(DOMAIN_NAME, out.getName());
+        assertEquals(DOMAIN_ID, out.getId());
+        assertEquals(DOMAIN_DESCRIPTION_UPDATED, out.getDescription());
+    }
+
+    @Path("/deleteShouldSucceed")
+    @POST
+    public void deleteShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneDomainResource.deleteShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.DELETE);
+        template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, DOMAIN_ID);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupResource.java b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupResource.java
new file mode 100644
index 0000000..afc198d
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupResource.java
@@ -0,0 +1,169 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openstack.common.OpenstackConstants;
+import org.apache.camel.component.openstack.keystone.KeystoneConstants;
+import org.jboss.logging.Logger;
+import org.openstack4j.api.Builders;
+import org.openstack4j.model.identity.v3.Group;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Path("/openstack/keystone/groups/")
+@ApplicationScoped
+public class OpenstackKeystoneGroupResource {
+
+    private static final Logger LOG = Logger.getLogger(OpenstackKeystoneGroupResource.class);
+
+    private static final String URI_FORMAT = "openstack-keystone://{{camel.openstack.test.host-url}}?username=user&password=secret&project=project&operation=%s&subsystem="
+            + KeystoneConstants.GROUPS;
+
+    private static final String GROUP_NAME = "GROUP_CRUD";
+    private static final String GROUP_ID = "c0d675eac29945ad9dfd08aa1bb75751";
+    private static final String GROUP_DOMAIN_ID = "default";
+    private static final String GROUP_DESCRIPTION = "Group used for CRUD tests";
+    private static final String GROUP_DESCRIPTION_UPDATED = "An updated group used for CRUD tests";
+
+    @Inject
+    ProducerTemplate template;
+
+    @Path("/createShouldSucceed")
+    @POST
+    public void createShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.createShouldSucceed()");
+
+        Group in = Builders.group().name(GROUP_NAME).description(GROUP_DESCRIPTION).domainId(GROUP_DOMAIN_ID).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.CREATE);
+        Group out = template.requestBody(uri, in, Group.class);
+
+        assertNotNull(out);
+        assertEquals(GROUP_NAME, out.getName());
+        assertEquals(GROUP_DOMAIN_ID, out.getDomainId());
+        assertEquals(GROUP_DESCRIPTION, out.getDescription());
+    }
+
+    @Path("/getShouldSucceed")
+    @POST
+    public void getShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.getShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        Group out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, GROUP_ID, Group.class);
+
+        assertNotNull(out);
+        assertEquals(GROUP_NAME, out.getName());
+        assertEquals(GROUP_ID, out.getId());
+        assertEquals(GROUP_DOMAIN_ID, out.getDomainId());
+        assertEquals(GROUP_DESCRIPTION, out.getDescription());
+    }
+
+    @Path("/getAllShouldSucceed")
+    @POST
+    public void getAllShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.getAllShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET_ALL);
+        Group[] groups = template.requestBody(uri, null, Group[].class);
+
+        assertEquals(5, groups.length);
+
+        assertEquals("7261c982051c4080a69a52117a861d64", groups[0].getId());
+        assertEquals("default", groups[1].getDomainId());
+        assertEquals("Group for CRUD tests", groups[2].getDescription());
+        assertEquals("role_crud_group", groups[3].getName());
+        assertNotNull(groups[4].getLinks());
+        assertTrue(groups[4].getLinks().containsKey("self"));
+    }
+
+    @Path("/updateShouldSucceed")
+    @POST
+    public void updateShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.updateShouldSucceed()");
+
+        Group in = Builders.group().id(GROUP_ID).description(GROUP_DESCRIPTION_UPDATED).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.UPDATE);
+        Group out = template.requestBody(uri, in, Group.class);
+
+        assertNotNull(out);
+        assertEquals(GROUP_NAME, out.getName());
+        assertEquals(GROUP_ID, out.getId());
+        assertEquals(GROUP_DESCRIPTION_UPDATED, out.getDescription());
+    }
+
+    @Path("/deleteShouldSucceed")
+    @POST
+    public void deleteShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.deleteShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.DELETE);
+        template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, GROUP_ID);
+    }
+
+    @Path("/addUserToGroupShouldSucceed")
+    @POST
+    public void addUserToGroupShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.addUserToGroupShouldSucceed()");
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(KeystoneConstants.USER_ID, "d599b83141fc47bc9c25e89267aa27c4");
+        headers.put(KeystoneConstants.GROUP_ID, "851398fccda34f208e1839ebbc1251d1");
+
+        String uri = String.format(URI_FORMAT, KeystoneConstants.ADD_USER_TO_GROUP);
+        template.requestBodyAndHeaders(uri, null, headers, Group.class);
+    }
+
+    @Path("/checkUserGroupShouldSucceed")
+    @POST
+    public void checkUserGroupShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.checkUserGroupShouldSucceed()");
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(KeystoneConstants.USER_ID, "d599b83141fc47bc9c25e89267aa27c4");
+        headers.put(KeystoneConstants.GROUP_ID, "851398fccda34f208e1839ebbc1251d1");
+
+        String uri = String.format(URI_FORMAT, KeystoneConstants.CHECK_GROUP_USER);
+        boolean userInGroup = template.requestBodyAndHeaders(uri, null, headers, Boolean.class);
+        assertTrue(userInGroup);
+    }
+
+    @Path("/removeUserFromGroupShouldSucceed")
+    @POST
+    public void removeUserFromGroupShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneGroupResource.removeUserFromGroupShouldSucceed()");
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(KeystoneConstants.USER_ID, "d599b83141fc47bc9c25e89267aa27c4");
+        headers.put(KeystoneConstants.GROUP_ID, "851398fccda34f208e1839ebbc1251d1");
+
+        String uri = String.format(URI_FORMAT, KeystoneConstants.REMOVE_USER_FROM_GROUP);
+        template.requestBodyAndHeaders(uri, null, headers);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectResource.java b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectResource.java
new file mode 100644
index 0000000..88578f7
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectResource.java
@@ -0,0 +1,143 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openstack.common.OpenstackConstants;
+import org.apache.camel.component.openstack.keystone.KeystoneConstants;
+import org.jboss.logging.Logger;
+import org.openstack4j.api.Builders;
+import org.openstack4j.model.identity.v3.Project;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Path("/openstack/keystone/projects/")
+@ApplicationScoped
+public class OpenstackKeystoneProjectResource {
+
+    private static final Logger LOG = Logger.getLogger(OpenstackKeystoneProjectResource.class);
+
+    private static final String URI_FORMAT = "openstack-keystone://{{camel.openstack.test.host-url}}?username=user&password=secret&project=project&operation=%s&subsystem="
+            + KeystoneConstants.PROJECTS;
+
+    private static final String PROJECT_NAME = "ProjectX";
+    private static final String PROJECT_ID = "3337151a1c38496c8bffcb280b19c346";
+    private static final String PROJECT_DOMAIN_ID = "7a71863c2d1d4444b3e6c2cd36955e1e";
+    private static final String PROJECT_DESCRIPTION = "Project used for CRUD tests";
+    private static final String PROJECT_DESCRIPTION_UPDATED = "An updated project used for CRUD tests";
+    private static final String PROJECT_EXTRA_KEY_1 = "extra_key1";
+    private static final String PROJECT_EXTRA_VALUE_1 = "value1";
+    private static final String PROJECT_EXTRA_KEY_2 = "extra_key2";
+    private static final String PROJECT_EXTRA_VALUE_2 = "value2";
+    private static final List<String> TAGS = Arrays.asList("one", "two", "three");
+
+    @Inject
+    ProducerTemplate template;
+
+    @Path("/createShouldSucceed")
+    @POST
+    public void createShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneProjectResource.createShouldSucceed()");
+
+        Project in = Builders.project().name(PROJECT_NAME).description(PROJECT_DESCRIPTION).domainId(PROJECT_DOMAIN_ID)
+                .setExtra(PROJECT_EXTRA_KEY_1, PROJECT_EXTRA_VALUE_1).enabled(true).setTags(TAGS).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.CREATE);
+        Project out = template.requestBody(uri, in, Project.class);
+
+        assertNotNull(out);
+        assertEquals(PROJECT_NAME, out.getName());
+        assertEquals(PROJECT_ID, out.getId());
+        assertEquals(PROJECT_DOMAIN_ID, out.getDomainId());
+        assertEquals(PROJECT_DESCRIPTION, out.getDescription());
+        assertEquals(PROJECT_EXTRA_VALUE_1, out.getExtra(PROJECT_EXTRA_KEY_1));
+        assertEquals(TAGS, out.getTags());
+    }
+
+    @Path("/getShouldSucceed")
+    @POST
+    public void getShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneProjectResource.getShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        Project out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, PROJECT_ID, Project.class);
+
+        assertNotNull(out);
+        assertEquals(PROJECT_NAME, out.getName());
+        assertEquals(PROJECT_ID, out.getId());
+        assertEquals(PROJECT_DOMAIN_ID, out.getDomainId());
+        assertEquals(PROJECT_DESCRIPTION, out.getDescription());
+    }
+
+    @Path("/getAllShouldSucceed")
+    @POST
+    public void getAllShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneProjectResource.getAllShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET_ALL);
+        Project[] projects = template.requestBody(uri, null, Project[].class);
+
+        assertEquals(3, projects.length);
+        assertEquals("10b40033bbef48f89fe838fef62398f0", projects[0].getId());
+        assertEquals("600905d353a84b20b644d2fe55a21e8a", projects[1].getId());
+        assertEquals("8519dba9f4594f0f87071c87784a8d2c", projects[2].getId());
+        assertNotNull(projects[2].getOptions());
+        assertTrue(projects[2].getOptions().isEmpty());
+        assertNotNull(projects[2].getTags());
+        assertTrue(projects[2].getTags().isEmpty());
+    }
+
+    @Path("/updateShouldSucceed")
+    @POST
+    public void updateShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneProjectResource.updateShouldSucceed()");
+
+        Project in = Builders.project().id(PROJECT_ID).description(PROJECT_DESCRIPTION_UPDATED)
+                .setExtra(PROJECT_EXTRA_KEY_2, PROJECT_EXTRA_VALUE_2).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.UPDATE);
+        Project out = template.requestBody(uri, in, Project.class);
+
+        assertNotNull(out);
+        assertEquals(PROJECT_ID, out.getId());
+        assertEquals(PROJECT_NAME, out.getName());
+        assertEquals(PROJECT_DOMAIN_ID, out.getDomainId());
+        assertEquals(PROJECT_DESCRIPTION_UPDATED, out.getDescription());
+        assertEquals(PROJECT_EXTRA_VALUE_1, out.getExtra(PROJECT_EXTRA_KEY_1));
+        assertEquals(PROJECT_EXTRA_VALUE_2, out.getExtra(PROJECT_EXTRA_KEY_2));
+    }
+
+    @Path("/deleteShouldSucceed")
+    @POST
+    public void deleteShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneProjectResource.deleteShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.DELETE);
+        template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, PROJECT_ID);
+    }
+
+}
diff --git a/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionResource.java b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionResource.java
new file mode 100644
index 0000000..a849122
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionResource.java
@@ -0,0 +1,133 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openstack.common.OpenstackConstants;
+import org.apache.camel.component.openstack.keystone.KeystoneConstants;
+import org.jboss.logging.Logger;
+import org.openstack4j.api.Builders;
+import org.openstack4j.model.identity.v3.Region;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+@Path("/openstack/keystone/regions/")
+@ApplicationScoped
+public class OpenstackKeystoneRegionResource {
+
+    private static final Logger LOG = Logger.getLogger(OpenstackKeystoneRegionResource.class);
+
+    private static final String URI_FORMAT = "openstack-keystone://{{camel.openstack.test.host-url}}?username=user&password=secret&project=project&operation=%s&subsystem="
+            + KeystoneConstants.REGIONS;
+
+    private static final String REGION_ID = "Region_CRUD";
+    private static final String REGION_PARENTREGIONID = "RegionOne";
+    private static final String REGION_DESCRIPTION = "No description provided.";
+    private static final String REGION_DESCRIPTION_UPDATED = "A updated region used for CRUD tests.";
+
+    @Inject
+    ProducerTemplate template;
+
+    @Path("/createShouldSucceed")
+    @POST
+    public void createShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.createShouldSucceed()");
+
+        Region in = Builders.region().id(REGION_ID).description(REGION_DESCRIPTION)
+                .parentRegionId(REGION_PARENTREGIONID).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.CREATE);
+        Region out = template.requestBody(uri, in, Region.class);
+
+        assertNotNull(out);
+        assertEquals(REGION_ID, out.getId());
+        assertEquals(REGION_DESCRIPTION, out.getDescription());
+        assertEquals(REGION_PARENTREGIONID, out.getParentRegionId());
+    }
+
+    @Path("/getShouldSucceed")
+    @POST
+    public void getShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.getShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        Region out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, REGION_ID, Region.class);
+
+        assertNotNull(out);
+        assertEquals(REGION_ID, out.getId());
+        assertEquals(REGION_DESCRIPTION, out.getDescription());
+        assertEquals(REGION_PARENTREGIONID, out.getParentRegionId());
+    }
+
+    @Path("/getAllShouldSucceed")
+    @POST
+    public void getAllShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.getAllShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET_ALL);
+        Region[] regions = template.requestBody(uri, null, Region[].class);
+
+        assertEquals(2, regions.length);
+        assertEquals(REGION_PARENTREGIONID, regions[0].getId());
+        assertEquals(null, regions[0].getParentRegionId());
+        assertEquals(REGION_ID, regions[1].getId());
+        assertEquals(REGION_PARENTREGIONID, regions[1].getParentRegionId());
+    }
+
+    @Path("/updateShouldSucceed")
+    @POST
+    public void updateShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.updateShouldSucceed()");
+
+        Region in = Builders.region().id(REGION_ID).description(REGION_DESCRIPTION_UPDATED).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.UPDATE);
+        Region out = template.requestBody(uri, in, Region.class);
+
+        assertNotNull(out);
+        assertEquals(REGION_ID, out.getId());
+        assertEquals(REGION_DESCRIPTION_UPDATED, out.getDescription());
+        assertEquals(REGION_PARENTREGIONID, out.getParentRegionId());
+    }
+
+    @Path("/deleteShouldSucceed")
+    @POST
+    public void deleteShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.deleteShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.DELETE);
+        template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, REGION_ID);
+    }
+
+    @Path("/getUnknownShouldReturnNull")
+    @POST
+    public void getUnknownRegionShouldReturnNull() {
+        LOG.debug("Calling OpenstackKeystoneRegionResource.getUnknownShouldReturnNull()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        Region out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, "nonExistentRegionId", Region.class);
+
+        assertNull(out);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserResource.java b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserResource.java
new file mode 100644
index 0000000..e9ac403
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/main/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserResource.java
@@ -0,0 +1,126 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.openstack.common.OpenstackConstants;
+import org.apache.camel.component.openstack.keystone.KeystoneConstants;
+import org.jboss.logging.Logger;
+import org.openstack4j.api.Builders;
+import org.openstack4j.model.identity.v3.User;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Path("/openstack/keystone/users/")
+@ApplicationScoped
+public class OpenstackKeystoneUserResource {
+
+    private static final Logger LOG = Logger.getLogger(OpenstackKeystoneUserResource.class);
+
+    private static final String URI_FORMAT = "openstack-keystone://{{camel.openstack.test.host-url}}?username=user&password=secret&project=project&operation=%s&subsystem="
+            + KeystoneConstants.USERS;
+
+    private static final String USER_NAME = "foobar";
+    private static final String USER_DOMAIN_ID = "default";
+    private static final String USER_EMAIL = "foobar@example.org";
+    private static final String USER_EMAIL_UPDATED = "updatedFoobar@example.org";
+    private static final String USER_ID = "29d5aaaa6d3b471e9c101ae470e649a6";
+
+    @Inject
+    ProducerTemplate template;
+
+    @Path("/createShouldSucceed")
+    @POST
+    public void createShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneUserResource.createShouldSucceed()");
+
+        User in = Builders.user().name(USER_NAME).domainId(USER_DOMAIN_ID).email(USER_EMAIL).enabled(true).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.CREATE);
+        User out = template.requestBody(uri, in, User.class);
+
+        assertNotNull(out);
+        assertEquals(USER_NAME, out.getName());
+        assertEquals(USER_DOMAIN_ID, out.getDomainId());
+        assertEquals(USER_EMAIL, out.getEmail());
+        assertTrue(out.isEnabled());
+        assertEquals(USER_ID, out.getId());
+    }
+
+    @Path("/getShouldSucceed")
+    @POST
+    public void getShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneUserResource.getShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET);
+        User out = template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, USER_ID, User.class);
+
+        assertNotNull(out);
+        assertEquals(USER_NAME, out.getName());
+        assertEquals(USER_DOMAIN_ID, out.getDomainId());
+        assertTrue(out.isEnabled());
+        assertEquals(USER_ID, out.getId());
+    }
+
+    @Path("/getAllShouldSucceed")
+    @POST
+    public void getAllShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneUserResource.getAllShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.GET_ALL);
+        User[] users = template.requestBody(uri, null, User[].class);
+
+        assertNotNull(users);
+        assertEquals(6, users.length);
+        assertEquals("glance", users[0].getName());
+        assertEquals("default", users[1].getDomainId());
+        assertNull(users[2].getEmail());
+        assertEquals("7afec08993c24bb09df141e513738030", users[3].getId());
+    }
+
+    @Path("/updateShouldSucceed")
+    @POST
+    public void updateShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneUserResource.updateShouldSucceed()");
+
+        User in = Builders.user().id(USER_ID).email(USER_EMAIL_UPDATED).build();
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.UPDATE);
+        User out = template.requestBody(uri, in, User.class);
+
+        assertNotNull(out);
+        assertEquals(USER_ID, out.getId());
+        assertEquals(USER_EMAIL_UPDATED, out.getEmail());
+    }
+
+    @Path("/deleteShouldSucceed")
+    @POST
+    public void deleteShouldSucceed() {
+        LOG.debug("Calling OpenstackKeystoneUserResource.deleteShouldSucceed()");
+
+        String uri = String.format(URI_FORMAT, OpenstackConstants.DELETE);
+        template.requestBodyAndHeader(uri, null, OpenstackConstants.ID, USER_ID);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainTest.java b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainTest.java
new file mode 100644
index 0000000..1a492bc
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneDomainTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.post;
+
+@QuarkusTest
+@QuarkusTestResource(OpenStackTestResource.class)
+class OpenstackKeystoneDomainTest {
+
+    @Test
+    public void createShouldSucceed() {
+        post("/openstack/keystone/domains/createShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getShouldSucceed() {
+        post("/openstack/keystone/domains/getShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getAllShouldSucceed() {
+        post("/openstack/keystone/domains/getAllShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void updateShouldSucceed() {
+        post("/openstack/keystone/domains/updateShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void deleteShouldSucceed() {
+        post("/openstack/keystone/domains/deleteShouldSucceed").then().statusCode(204);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupTest.java b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupTest.java
new file mode 100644
index 0000000..7ce3984
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneGroupTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.post;
+
+@QuarkusTest
+@QuarkusTestResource(OpenStackTestResource.class)
+class OpenstackKeystoneGroupTest {
+
+    @Test
+    public void createShouldSucceed() {
+        post("/openstack/keystone/groups/createShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getShouldSucceed() {
+        post("/openstack/keystone/groups/getShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getAllShouldSucceed() {
+        post("/openstack/keystone/groups/getAllShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void updateShouldSucceed() {
+        post("/openstack/keystone/groups/updateShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void deleteShouldSucceed() {
+        post("/openstack/keystone/groups/deleteShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void addUserToGroupShouldSucceed() {
+        post("/openstack/keystone/groups/addUserToGroupShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void checkUserGroupShouldSucceed() {
+        post("/openstack/keystone/groups/checkUserGroupShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void removeUserFromGroupShouldSucceed() {
+        post("/openstack/keystone/groups/removeUserFromGroupShouldSucceed").then().statusCode(204);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectTest.java b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectTest.java
new file mode 100644
index 0000000..0f81efc
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneProjectTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.post;
+
+@QuarkusTest
+@QuarkusTestResource(OpenStackTestResource.class)
+class OpenstackKeystoneProjectTest {
+
+    @Test
+    public void createShouldSucceed() {
+        post("/openstack/keystone/projects/createShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getShouldSucceed() {
+        post("/openstack/keystone/projects/getShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getAllShouldSucceed() {
+        post("/openstack/keystone/projects/getAllShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void updateShouldSucceed() {
+        post("/openstack/keystone/projects/updateShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void deleteShouldSucceed() {
+        post("/openstack/keystone/projects/deleteShouldSucceed").then().statusCode(204);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionTest.java b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionTest.java
new file mode 100644
index 0000000..d744c0e
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneRegionTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.post;
+
+@QuarkusTest
+@QuarkusTestResource(OpenStackTestResource.class)
+class OpenstackKeystoneRegionTest {
+
+    @Test
+    public void createShouldSucceed() {
+        post("/openstack/keystone/regions/createShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getShouldSucceed() {
+        post("/openstack/keystone/regions/getShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getAllShouldSucceed() {
+        post("/openstack/keystone/regions/getAllShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void updateShouldSucceed() {
+        post("/openstack/keystone/regions/updateShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void deleteShouldSucceed() {
+        post("/openstack/keystone/regions/deleteShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getUnknownShouldReturnNull() {
+        post("/openstack/keystone/regions/getUnknownShouldReturnNull").then().statusCode(204);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserTest.java b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserTest.java
new file mode 100644
index 0000000..7249dc2
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/java/org/apache/camel/quarkus/component/openstack/it/OpenstackKeystoneUserTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.camel.quarkus.component.openstack.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.post;
+
+@QuarkusTest
+@QuarkusTestResource(OpenStackTestResource.class)
+class OpenstackKeystoneUserTest {
+
+    @Test
+    public void createShouldSucceed() {
+        post("/openstack/keystone/users/createShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getShouldSucceed() {
+        post("/openstack/keystone/users/getShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void getAllShouldSucceed() {
+        post("/openstack/keystone/users/getAllShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void updateShouldSucceed() {
+        post("/openstack/keystone/users/updateShouldSucceed").then().statusCode(204);
+    }
+
+    @Test
+    public void deleteShouldSucceed() {
+        post("/openstack/keystone/users/deleteShouldSucceed").then().statusCode(204);
+    }
+}
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_create_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_create_response.json
new file mode 100644
index 0000000..7e3c1cc
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_create_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "4adf6297-55fa-472b-8e08-b9060f6440b2",
+  "name" : "domains_create_response.json",
+  "request" : {
+    "url" : "/v3/domains",
+    "method" : "POST"
+  },
+  "response" : {
+    "status" : 201,
+    "body" : "{\"domain\":{\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/domains\/98c110ae41c249189c9d5c25d8377b65\"},\"enabled\":true,\"description\":\"Domain used for CRUD tests\",\"name\":\"Domain_CRUD\",\"id\":\"98c110ae41c249189c9d5c25d8377b65\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    }
+  },
+  "uuid" : "4adf6297-55fa-472b-8e08-b9060f6440b2",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_delete.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_delete.json
new file mode 100644
index 0000000..17d0d84
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_delete.json
@@ -0,0 +1,20 @@
+{
+  "id" : "92c0d2c0-e157-44b6-ba35-5b0c40b415d9",
+  "name" : "domains_delete.json",
+  "request" : {
+    "url" : "/v3/domains/98c110ae41c249189c9d5c25d8377b65",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "status" : 204,
+    "headers" : {
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-aaaf3dea-0c0f-40ef-827b-141be2756eec"
+    }
+  },
+  "uuid" : "92c0d2c0-e157-44b6-ba35-5b0c40b415d9",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_get_byId.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_get_byId.json
new file mode 100644
index 0000000..a2e6e96
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_get_byId.json
@@ -0,0 +1,19 @@
+{
+  "id" : "2cddaa4b-0547-446b-ba0a-e03a1aaa47c5",
+  "name" : "domains_get_byId.json",
+  "request" : {
+    "url" : "/v3/domains/98c110ae41c249189c9d5c25d8377b65",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"domain\":{\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/domains\/98c110ae41c249189c9d5c25d8377b65\"},\"enabled\":false,\"description\":\"Domain used for CRUD tests\",\"name\":\"Domain_CRUD\",\"id\":\"98c110ae41c249189c9d5c25d8377b65\"}}",
+    "headers" : {
+      "Content-Type" : "application/json",
+       "x-openstack-request-id": "req-3fd97a17-e56c-49b0-9246-c721afce0055"
+    },
+    "status" : 200
+  },
+  "uuid" : "2cddaa4b-0547-446b-ba0a-e03a1aaa47c5",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_update_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_update_response.json
new file mode 100644
index 0000000..588b176
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_update_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "b09c0fc6-26bd-4152-877d-4a2c61478759",
+  "name" : "domains_update_response.json",
+  "request" : {
+    "url" : "/v3/domains/98c110ae41c249189c9d5c25d8377b65",
+    "method" : "PATCH"
+  },
+  "response" : {
+    "body": "{\"domain\":{\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/domains\/98c110ae41c249189c9d5c25d8377b65\"},\"enabled\":true,\"description\":\"An updated domain used for CRUD tests\",\"name\":\"Domain_CRUD\",\"id\":\"98c110ae41c249189c9d5c25d8377b65\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "b09c0fc6-26bd-4152-877d-4a2c61478759",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_with_options.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_with_options.json
new file mode 100644
index 0000000..63bfe84
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/domains/domains_with_options.json
@@ -0,0 +1,18 @@
+{
+  "id" : "38c152b0-ebd7-48e9-b3a9-5866f0f5ef86",
+  "name" : "domains_with_options.json",
+  "request" : {
+    "url" : "/v3/domains",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"domains\":[{\"description\":\"The default domain\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/domains\/default\"},\"tags\":[],\"enabled\":true,\"options\":{},\"id\":\"default\",\"name\":\"Default\"}],\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/domains?limit=500\",\"previous\":null,\"next\":null}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "38c152b0-ebd7-48e9-b3a9-5866f0f5ef86",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_add_user.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_add_user.json
new file mode 100644
index 0000000..1686c1a
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_add_user.json
@@ -0,0 +1,20 @@
+{
+  "id" : "5322bec6-a2fd-4152-98d2-810e4b1167c0",
+  "name" : "groups_add_user.json",
+  "request" : {
+    "url" : "/v3/groups/851398fccda34f208e1839ebbc1251d1/users/d599b83141fc47bc9c25e89267aa27c4",
+    "method" : "PUT"
+  },
+  "response" : {
+    "headers" : {
+      "Date": "Wed, 17 Feb 2016 18:17:43 GMT",
+      "Server": "Apache/2.4.7 (Ubuntu)",
+      "Vary": "X-Auth-Token",
+      "x-openstack-request-id": "req-d1524fa5-4265-4ae8-bad9-d705b9766835"
+    },
+    "status" : 204
+  },
+  "uuid" : "5322bec6-a2fd-4152-98d2-810e4b1167c0",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_check_user.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_check_user.json
new file mode 100644
index 0000000..da57ea6
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_check_user.json
@@ -0,0 +1,20 @@
+{
+  "id" : "9c26c4ce-90b9-44da-9ebe-d2c1218764f6",
+  "name" : "groups_check_user.json",
+  "request" : {
+    "url" : "/v3/groups/851398fccda34f208e1839ebbc1251d1/users/d599b83141fc47bc9c25e89267aa27c4",
+    "method" : "HEAD"
+  },
+  "response" : {
+    "headers" : {
+      "Date": "Wed, 17 Feb 2016 18:17:43 GMT",
+      "Server": "Apache/2.4.7 (Ubuntu)",
+      "Vary": "X-Auth-Token",
+      "x-openstack-request-id": "req-76920b81-66dd-4b88-92d6-2ef9168b9397"
+    },
+    "status" : 204
+  },
+  "uuid" : "9c26c4ce-90b9-44da-9ebe-d2c1218764f6",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_create_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_create_response.json
new file mode 100644
index 0000000..297ae75
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_create_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "1a86d6a5-736a-4eba-b1ab-a39625f92385",
+  "name" : "groups_create_response.json",
+  "request" : {
+    "url" : "/v3/groups",
+    "method" : "POST"
+  },
+  "response" : {
+    "body" : "{\"group\":{\"domain_id\":\"default\",\"description\":\"Group used for CRUD tests\",\"id\":\"c0d675eac29945ad9dfd08aa1bb75751\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/groups\/c0d675eac29945ad9dfd08aa1bb75751\"},\"name\":\"GROUP_CRUD\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 201
+  },
+  "uuid" : "1a86d6a5-736a-4eba-b1ab-a39625f92385",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_delete.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_delete.json
new file mode 100644
index 0000000..e0ed763
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_delete.json
@@ -0,0 +1,20 @@
+{
+  "id" : "ea1f6a98-86b1-44e0-aecc-9c3b2e15cc9d",
+  "name" : "regions_delete.json",
+  "request" : {
+    "url" : "/v3/groups/c0d675eac29945ad9dfd08aa1bb75751",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "status" : 204,
+    "headers" : {
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-bf13fc70-8a3d-41ff-881a-880bc8a59f4d"
+    }
+  },
+  "uuid" : "ea1f6a98-86b1-44e0-aecc-9c3b2e15cc9d",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_get_byId.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_get_byId.json
new file mode 100644
index 0000000..8599b2d
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_get_byId.json
@@ -0,0 +1,18 @@
+{
+  "id" : "4e5d9c78-a7c2-41d4-ae93-bfeb3991c272",
+  "name" : "groups_get_byId.json",
+  "request" : {
+    "url" : "/v3/groups/c0d675eac29945ad9dfd08aa1bb75751",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"group\":{\"domain_id\":\"default\",\"description\":\"Group used for CRUD tests\",\"id\":\"c0d675eac29945ad9dfd08aa1bb75751\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/groups\/c0d675eac29945ad9dfd08aa1bb75751\"},\"name\":\"GROUP_CRUD\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "4e5d9c78-a7c2-41d4-ae93-bfeb3991c272",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_list.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_list.json
new file mode 100644
index 0000000..d4c0df8
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_list.json
@@ -0,0 +1,22 @@
+{
+  "id" : "123de0b3-ea3f-4eb9-a7f0-aaaaaced130e",
+  "name" : "groups_list.json",
+  "request" : {
+    "url" : "/v3/groups",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/groups\",\"previous\":null,\"next\":null},\"groups\":[{\"domain_id\":\"default\",\"description\":\"openstack admin group\",\"id\":\"7261c982051c4080a69a52117a861d64\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/groups\/7261c982051c4080a69a52117a861d64\"},\"name\":\"admins\"},{\"domain_id\":\"default\",\"description\":\"non-admin group\",\"id\":\"8030dabf0cb843509602f0b3fa49adc2\",\"link [...]
+    "headers" : {
+        "Content-Type": "application/json",
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-afc2a71a-c0da-4d4b-8be9-93669eac9ece"
+    },
+    "status" : 200
+  },
+  "uuid" : "123de0b3-ea3f-4eb9-a7f0-aaaaaced130e",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_remove_user.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_remove_user.json
new file mode 100644
index 0000000..e29a6ae
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_remove_user.json
@@ -0,0 +1,20 @@
+{
+  "id" : "62c32d80-aa7c-44c4-8eca-d6514f7cd53d",
+  "name" : "groups_remove_user.json",
+  "request" : {
+    "url" : "/v3/groups/851398fccda34f208e1839ebbc1251d1/users/d599b83141fc47bc9c25e89267aa27c4",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "headers" : {
+      "Date": "Wed, 17 Feb 2016 18:17:43 GMT",
+      "Server": "Apache/2.4.7 (Ubuntu)",
+      "Vary": "X-Auth-Token",
+      "x-openstack-request-id": "req-ba2c6bde-a6da-40ba-9ac2-1980b623344b"
+    },
+    "status" : 204
+  },
+  "uuid" : "62c32d80-aa7c-44c4-8eca-d6514f7cd53d",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_update_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_update_response.json
new file mode 100644
index 0000000..2e85031
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/groups/groups_update_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "7943ac36-c063-4849-a621-7fd7ddd6b072",
+  "name" : "groups_update_response.json",
+  "request" : {
+    "url" : "/v3/groups/c0d675eac29945ad9dfd08aa1bb75751",
+    "method" : "PATCH"
+  },
+  "response" : {
+    "body": "{\"group\":{\"domain_id\":\"default\",\"description\":\"An updated group used for CRUD tests\",\"id\":\"c0d675eac29945ad9dfd08aa1bb75751\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/groups\/c0d675eac29945ad9dfd08aa1bb75751\"},\"name\":\"GROUP_CRUD\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "7943ac36-c063-4849-a621-7fd7ddd6b072",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_create_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_create_response.json
new file mode 100644
index 0000000..4d4588a
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_create_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "a41972c3-5f86-4d0e-837b-e3bfdb62062b",
+  "name" : "projects_create_response.json",
+  "request" : {
+    "url" : "/v3/projects",
+    "method" : "POST"
+  },
+  "response" : {
+    "body" : "{\"project\":{\"is_domain\":false,\"description\":\"Project used for CRUD tests\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/projects\/3337151a1c38496c8bffcb280b19c346\"},\"enabled\":true,\"id\":\"3337151a1c38496c8bffcb280b19c346\",\"parent_id\":null,\"domain_id\":\"7a71863c2d1d4444b3e6c2cd36955e1e\",\"name\":\"ProjectX\",\"extra_key1\":\"value1\",\"tags\":[\"one\",\"two\",\"three\"]}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 201
+  },
+  "uuid" : "a41972c3-5f86-4d0e-837b-e3bfdb62062b",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_delete.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_delete.json
new file mode 100644
index 0000000..e199189
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_delete.json
@@ -0,0 +1,20 @@
+{
+  "id" : "e2e8dab4-68d1-4fe8-bd73-78a7b5e5374b",
+  "name" : "projects_delete.json",
+  "request" : {
+    "url" : "/v3/projects/3337151a1c38496c8bffcb280b19c346",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "status" : 204,
+    "headers" : {
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-d428e41d-104e-4d70-ba47-0878e914b200"
+    }
+  },
+  "uuid" : "e2e8dab4-68d1-4fe8-bd73-78a7b5e5374b",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_get_byId.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_get_byId.json
new file mode 100644
index 0000000..0bad1c1
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_get_byId.json
@@ -0,0 +1,18 @@
+{
+  "id" : "d2953b7a-f008-4ca6-8490-0c77297afd3a",
+  "name" : "projects_get_byId.json",
+  "request" : {
+    "url" : "/v3/projects/3337151a1c38496c8bffcb280b19c346",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"project\":{\"is_domain\":false,\"description\":\"Project used for CRUD tests\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/projects\/3337151a1c38496c8bffcb280b19c346\"},\"enabled\":true,\"id\":\"3337151a1c38496c8bffcb280b19c346\",\"parent_id\":null,\"domain_id\":\"7a71863c2d1d4444b3e6c2cd36955e1e\",\"name\":\"ProjectX\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "d2953b7a-f008-4ca6-8490-0c77297afd3a",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_update_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_update_response.json
new file mode 100644
index 0000000..6ec474e
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_update_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "81e5db2e-3043-401b-9cfb-61371d12822f",
+  "name" : "projects_update_response.json",
+  "request" : {
+    "url" : "/v3/projects/3337151a1c38496c8bffcb280b19c346",
+    "method" : "PATCH"
+  },
+  "response" : {
+    "body": "{\"project\":{\"is_domain\":false,\"description\":\"An updated project used for CRUD tests\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/projects\/3337151a1c38496c8bffcb280b19c346\"},\"enabled\":true,\"id\":\"3337151a1c38496c8bffcb280b19c346\",\"parent_id\":null,\"domain_id\":\"7a71863c2d1d4444b3e6c2cd36955e1e\",\"name\":\"ProjectX\",\"extra_key1\":\"value1\",\"extra_key2\":\"value2\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "81e5db2e-3043-401b-9cfb-61371d12822f",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_with_options.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_with_options.json
new file mode 100644
index 0000000..01bf1ee
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/projects/projects_with_options.json
@@ -0,0 +1,18 @@
+{
+  "id" : "50d2b5ce-59a2-4073-9372-337f81d13ee5",
+  "name" : "projects_with_options.json",
+  "request" : {
+    "url" : "/v3/projects",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/projects\",\"previous\":null,\"next\":null},\"projects\":[{\"is_domain\":false,\"description\":\"Tenant for the openstack services\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/projects\/10b40033bbef48f89fe838fef62398f0\"},\"tags\":[],\"enabled\":true,\"id\":\"10b40033bbef48f89fe838fef62398f0\",\"parent_id\":\"default\",\"options\":{},\"domain_id\":\"default\",\"name\":\"services\"},{\"is_domain\":false,\"descriptio [...]
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "50d2b5ce-59a2-4073-9372-337f81d13ee5",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_create_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_create_response.json
new file mode 100644
index 0000000..8d60ed5
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_create_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "22265785-c287-4a4c-9d90-8481ad57c1eb",
+  "name" : "regions_create_response.json",
+  "request" : {
+    "url" : "/v3/regions",
+    "method" : "POST"
+  },
+  "response" : {
+    "body" : "{\"region\":{\"id\":\"Region_CRUD\",\"description\":\"No description provided.\",\"parent_region_id\":\"RegionOne\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 201
+  },
+  "uuid" : "22265785-c287-4a4c-9d90-8481ad57c1eb",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_delete.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_delete.json
new file mode 100644
index 0000000..f95907b
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_delete.json
@@ -0,0 +1,20 @@
+{
+  "id" : "c76fbdcd-3528-49fa-9062-260043f62b12",
+  "name" : "regions_delete.json",
+  "request" : {
+    "url" : "/v3/regions/Region_CRUD",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "status" : 204,
+    "headers" : {
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-d428e41d-104e-4d70-ba47-0878e914b200"
+    }
+  },
+  "uuid" : "c76fbdcd-3528-49fa-9062-260043f62b12",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_byId.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_byId.json
new file mode 100644
index 0000000..b529de4
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_byId.json
@@ -0,0 +1,18 @@
+{
+  "id" : "2ae1f597-9421-424e-a98d-02b1ad3db3ae",
+  "name" : "regions_get_byId.json",
+  "request" : {
+    "url" : "/v3/regions/Region_CRUD",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"region\":{\"parent_region_id\":\"RegionOne\",\"id\":\"Region_CRUD\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/regions\/Region_CRUD\"},\"description\":\"No description provided.\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "2ae1f597-9421-424e-a98d-02b1ad3db3ae",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_nonExistent.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_nonExistent.json
new file mode 100644
index 0000000..56996fe
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_get_nonExistent.json
@@ -0,0 +1,22 @@
+{
+  "id" : "f8df5e9e-d4bc-480c-8ee3-0227fa41daee",
+  "name" : "regions_get_nonExistent.json",
+  "request" : {
+    "url" : "/v3/regions/nonExistentRegionId",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"error\":{\"message\":\"Could not find region: nonExistentRegionIda\",\"code\":404,\"title\":\"Not Found\"}}",
+    "headers" : {
+        "Content-Type": "application/json",
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-9699ed7f-05d3-4e0c-86e9-09f2744f7362"
+    },
+    "status" : 404
+  },
+  "uuid" : "f8df5e9e-d4bc-480c-8ee3-0227fa41daee",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_list.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_list.json
new file mode 100644
index 0000000..ab2b0e7
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_list.json
@@ -0,0 +1,22 @@
+{
+  "id" : "ded84235-4119-4322-a3eb-610db51d9c5d",
+  "name" : "regions_list.json",
+  "request" : {
+    "url" : "/v3/regions",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"regions\":[{\"parent_region_id\":null,\"id\":\"RegionOne\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/regions\/RegionOne\"},\"description\":\"\"},{\"parent_region_id\":\"RegionOne\",\"id\":\"Region_CRUD\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/regions\/Region_CRUD\"},\"description\":\"A region used for CRUD tests.\"}],\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/regions\",\"previous\":null,\"next\":null}}",
+    "headers" : {
+        "Content-Type": "application/json",
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-3bda5b96-7a40-4125-a82c-0362e08af1e9"
+    },
+    "status" : 200
+  },
+  "uuid" : "ded84235-4119-4322-a3eb-610db51d9c5d",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_update_response.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_update_response.json
new file mode 100644
index 0000000..544fed6
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/regions/regions_update_response.json
@@ -0,0 +1,18 @@
+{
+  "id" : "c966b263-358f-4ec3-aa05-3f39a370de80",
+  "name" : "regions_update_response.json",
+  "request" : {
+    "url" : "/v3/regions/Region_CRUD",
+    "method" : "PATCH"
+  },
+  "response" : {
+    "body": "{\"region\":{\"parent_region_id\":\"RegionOne\",\"id\":\"Region_CRUD\",\"links\":{\"self\":\"http:\/\/127.0.0.1:5000\/v3\/regions\/Region_CRUD\"},\"description\":\"A updated region used for CRUD tests.\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "c966b263-358f-4ec3-aa05-3f39a370de80",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/create_user.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/create_user.json
new file mode 100644
index 0000000..cb2ce72
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/create_user.json
@@ -0,0 +1,18 @@
+{
+  "id" : "c9f071d2-2a46-43bd-bdad-0644df510d5c",
+  "name" : "create_user.json",
+  "request" : {
+    "url" : "/v3/users",
+    "method" : "POST"
+  },
+  "response" : {
+    "body" : "{\"user\":{\"name\":\"foobar\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:35357\/v3\/users\/29d5aaaa6d3b471e9c101ae470e649a6\"},\"domain_id\":\"default\",\"enabled\":true,\"email\":\"foobar@example.org\",\"description\":\"a new user\",\"default_project_id\":\"123ac695d4db400a9001b91bb3b8aa46\",\"id\":\"29d5aaaa6d3b471e9c101ae470e649a6\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 201
+  },
+  "uuid" : "c9f071d2-2a46-43bd-bdad-0644df510d5c",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/update_user.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/update_user.json
new file mode 100644
index 0000000..297e313
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/update_user.json
@@ -0,0 +1,18 @@
+{
+  "id" : "7c43c266-253a-489e-bef5-5c4c882b153c",
+  "name" : "update_user.json",
+  "request" : {
+    "url" : "/v3/users/29d5aaaa6d3b471e9c101ae470e649a6",
+    "method" : "PATCH"
+  },
+  "response" : {
+    "body": "{\"user\":{\"name\":\"foobar\",\"links\":{\"self\":\"http:\/\/devstack.openstack,stack:5000\/v3\/users\/29d5aaaa6d3b471e9c101ae470e649a6\"},\"extra\":{\"email\":\"updatedFoobar@example.org\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/users\/29d5aaaa6d3b471e9c101ae470e649a6\"}},\"domain_id\":\"default\",\"enabled\":true,\"id\":\"29d5aaaa6d3b471e9c101ae470e649a6\",\"email\":\"updatedFoobar@example.org\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "7c43c266-253a-489e-bef5-5c4c882b153c",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_delete.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_delete.json
new file mode 100644
index 0000000..0905a94
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_delete.json
@@ -0,0 +1,20 @@
+{
+  "id" : "36204957-321b-4a69-8a14-fb8efa016de3",
+  "name" : "user_delete.json",
+  "request" : {
+    "url" : "/v3/users/29d5aaaa6d3b471e9c101ae470e649a6",
+    "method" : "DELETE"
+  },
+  "response" : {
+    "status" : 204,
+    "headers" : {
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-d428e41d-104e-4d70-ba47-0878e914b200"
+    }
+  },
+  "uuid" : "36204957-321b-4a69-8a14-fb8efa016de3",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_get_byId.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_get_byId.json
new file mode 100644
index 0000000..2f6579c
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/user_get_byId.json
@@ -0,0 +1,18 @@
+{
+  "id" : "6c90b04b-9872-445c-ac34-e02bfffa03a9",
+  "name" : "user_get_byId.json",
+  "request" : {
+    "url" : "/v3/users/29d5aaaa6d3b471e9c101ae470e649a6",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"user\":{\"domain_id\":\"default\",\"name\":\"foobar\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:5000\/v3\/users\/29d5aaaa6d3b471e9c101ae470e649a6\"},\"id\":\"29d5aaaa6d3b471e9c101ae470e649a6\",\"enabled\":true,\"email\":null,\"default_project_id\":\"123ac695d4db400a9001b91bb3b8aa46\"}}",
+    "headers" : {
+      "Content-Type" : "application/json; charset=UTF-8"
+    },
+    "status" : 200
+  },
+  "uuid" : "6c90b04b-9872-445c-ac34-e02bfffa03a9",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/users.json b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/users.json
new file mode 100644
index 0000000..26a6d72
--- /dev/null
+++ b/extensions-jvm/openstack/integration-test/src/test/resources/mappings/keystone/users/users.json
@@ -0,0 +1,22 @@
+{
+  "id" : "c3b1cc4a-3200-4f28-a1db-d68a157110c9",
+  "name" : "users.json",
+  "request" : {
+    "url" : "/v3/users",
+    "method" : "GET"
+  },
+  "response" : {
+    "body" : "{\"users\":[{\"name\":\"glance\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:35357\/v3\/users\/07cfb841cddd46819e3dcd5df238ae04\"},\"domain_id\":\"default\",\"enabled\":true,\"email\":null,\"id\":\"07cfb841cddd46819e3dcd5df238ae04\"},{\"name\":\"demo\",\"links\":{\"self\":\"http:\/\/devstack.openstack.stack:35357\/v3\/users\/11ba3db90590446fb6d7e0efe6c1f46a\"},\"domain_id\":\"default\",\"enabled\":true,\"email\":\"demo@example.com\",\"id\":\"11ba3db90590446fb6d7 [...]
+    "headers" : {
+        "Content-Type": "application/json",
+        "Date": "Wed, 16 Mar 2016 15:01:58 GMT",
+        "Server": "Apache/2.4.7 (Ubuntu)",
+        "Vary": "X-Auth-Token",
+        "x-openstack-request-id": "req-3bda5b96-7a40-4125-a82c-0362e08af1e9"
+    },
+    "status" : 200
+  },
+  "uuid" : "c3b1cc4a-3200-4f28-a1db-d68a157110c9",
+  "persistent" : true,
+  "insertionIndex" : 1
+}
\ No newline at end of file