diff --git a/lib/ansible/module_utils/k8s/__init__.py b/lib/ansible/module_utils/k8s/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/ansible/module_utils/k8s/common.py b/lib/ansible/module_utils/k8s/common.py
new file mode 100644
index 00000000000..bb8ee012104
--- /dev/null
+++ b/lib/ansible/module_utils/k8s/common.py
@@ -0,0 +1,368 @@
+#
+#  Copyright 2018 Red Hat | Ansible
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+import re
+import copy
+
+from ansible.module_utils.six import iteritems
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible.module_utils.k8s.helper import\
+    AnsibleMixin,\
+    HAS_STRING_UTILS,\
+    COMMON_ARG_SPEC,\
+    AUTH_ARG_SPEC,\
+    OPENSHIFT_ARG_SPEC
+
+try:
+    from openshift.helper.kubernetes import KubernetesObjectHelper
+    from openshift.helper.openshift import OpenShiftObjectHelper
+    from openshift.helper.exceptions import KubernetesException
+    HAS_K8S_MODULE_HELPER = True
+except ImportError as exc:
+    class KubernetesObjectHelper(object):
+        pass
+
+    class OpenShiftObjectHelper(object):
+        pass
+
+    HAS_K8S_MODULE_HELPER = False
+
+try:
+    import yaml
+    HAS_YAML = True
+except ImportError:
+    HAS_YAML = False
+
+
+class KubernetesAnsibleModuleHelper(AnsibleMixin, KubernetesObjectHelper):
+    pass
+
+
+class KubernetesAnsibleModule(AnsibleModule):
+
+    def __init__(self):
+
+        if not HAS_K8S_MODULE_HELPER:
+            raise Exception(
+                "This module requires the OpenShift Python client. Try `pip install openshift`"
+            )
+
+        if not HAS_YAML:
+            raise Exception(
+                "This module requires PyYAML. Try `pip install PyYAML`"
+            )
+
+        if not HAS_STRING_UTILS:
+            raise Exception(
+                "This module requires Python string utils. Try `pip install python-string-utils`"
+            )
+
+        mutually_exclusive = [
+            ('resource_definition', 'src'),
+        ]
+
+        AnsibleModule.__init__(self,
+                               argument_spec=self._argspec,
+                               supports_check_mode=True,
+                               mutually_exclusive=mutually_exclusive)
+
+        self.kind = self.params.pop('kind')
+        self.api_version = self.params.pop('api_version')
+        self.resource_definition = self.params.pop('resource_definition')
+        self.src = self.params.pop('src')
+        if self.src:
+            self.resource_definition = self.load_resource_definition(self.src)
+
+        if self.resource_definition:
+            self.api_version = self.resource_definition.get('apiVersion')
+            self.kind = self.resource_definition.get('kind')
+
+        self.api_version = self.api_version.lower()
+        self.kind = self._to_snake(self.kind)
+
+        if not self.api_version:
+            self.fail_json(
+                msg=("Error: no api_version specified. Use the api_version parameter, or provide it as part of a ",
+                     "resource_definition.")
+            )
+        if not self.kind:
+            self.fail_json(
+                msg="Error: no kind specified. Use the kind parameter, or provide it as part of a resource_definition"
+            )
+
+        self.helper = self._get_helper(self.api_version, self.kind)
+
+    @property
+    def _argspec(self):
+        argspec = copy.deepcopy(COMMON_ARG_SPEC)
+        argspec.update(copy.deepcopy(AUTH_ARG_SPEC))
+        return argspec
+
+    def _get_helper(self, api_version, kind):
+        try:
+            helper = KubernetesAnsibleModuleHelper(api_version=api_version, kind=kind, debug=False)
+            helper.get_model(api_version, kind)
+            return helper
+        except KubernetesException as exc:
+            self.fail_json(msg="Error initializing module helper {0}".format(exc.message))
+
+    def execute_module(self):
+        if self.resource_definition:
+            resource_params = self.resource_to_parameters(self.resource_definition)
+            self.params.update(resource_params)
+
+        self._authenticate()
+
+        state = self.params.pop('state', None)
+        force = self.params.pop('force', False)
+        name = self.params.get('name')
+        namespace = self.params.get('namespace')
+        existing = None
+
+        self._remove_aliases()
+
+        return_attributes = dict(changed=False, result=dict())
+
+        if self._diff:
+            return_attributes['request'] = self.helper.request_body_from_params(self.params)
+
+        if self.helper.base_model_name_snake.endswith('list'):
+            k8s_obj = self._read(name, namespace)
+            return_attributes['result'] = k8s_obj.to_dict()
+            self.exit_json(**return_attributes)
+
+        try:
+            existing = self.helper.get_object(name, namespace)
+        except KubernetesException as exc:
+            self.fail_json(msg='Failed to retrieve requested object: {0}'.format(exc.message),
+                           error=exc.value.get('status'))
+
+        if state == 'absent':
+            if not existing:
+                # The object already does not exist
+                self.exit_json(**return_attributes)
+            else:
+                # Delete the object
+                if not self.check_mode:
+                    try:
+                        self.helper.delete_object(name, namespace)
+                    except KubernetesException as exc:
+                        self.fail_json(msg="Failed to delete object: {0}".format(exc.message),
+                                       error=exc.value.get('status'))
+                return_attributes['changed'] = True
+                self.exit_json(**return_attributes)
+        else:
+            if not existing:
+                k8s_obj = self._create(namespace)
+                return_attributes['result'] = k8s_obj.to_dict()
+                return_attributes['changed'] = True
+                self.exit_json(**return_attributes)
+
+            if existing and force:
+                k8s_obj = None
+                request_body = self.helper.request_body_from_params(self.params)
+                if not self.check_mode:
+                    try:
+                        k8s_obj = self.helper.replace_object(name, namespace, body=request_body)
+                    except KubernetesException as exc:
+                        self.fail_json(msg="Failed to replace object: {0}".format(exc.message),
+                                       error=exc.value.get('status'))
+                return_attributes['result'] = k8s_obj.to_dict()
+                return_attributes['changed'] = True
+                self.exit_json(**return_attributes)
+
+            # Check if existing object should be patched
+            k8s_obj = copy.deepcopy(existing)
+            try:
+                self.helper.object_from_params(self.params, obj=k8s_obj)
+            except KubernetesException as exc:
+                self.fail_json(msg="Failed to patch object: {0}".format(exc.message))
+            match, diff = self.helper.objects_match(existing, k8s_obj)
+            if match:
+                return_attributes['result'] = existing.to_dict()
+                self.exit_json(**return_attributes)
+            elif self._diff:
+                return_attributes['differences'] = diff
+            # Differences exist between the existing obj and requested params
+            if not self.check_mode:
+                try:
+                    k8s_obj = self.helper.patch_object(name, namespace, k8s_obj)
+                except KubernetesException as exc:
+                    self.fail_json(msg="Failed to patch object: {0}".format(exc.message))
+            return_attributes['result'] = k8s_obj.to_dict()
+            return_attributes['changed'] = True
+            self.exit_json(**return_attributes)
+
+    def _authenticate(self):
+        try:
+            auth_options = {}
+            auth_args = ('host', 'api_key', 'kubeconfig', 'context', 'username', 'password',
+                         'cert_file', 'key_file', 'ssl_ca_cert', 'verify_ssl')
+            for key, value in iteritems(self.params):
+                if key in auth_args and value is not None:
+                    auth_options[key] = value
+            self.helper.set_client_config(**auth_options)
+        except KubernetesException as e:
+            self.fail_json(msg='Error loading config', error=str(e))
+
+    def _remove_aliases(self):
+        """
+        The helper doesn't know what to do with aliased keys
+        """
+        for k, v in iteritems(self._argspec):
+            if 'aliases' in v:
+                for alias in v['aliases']:
+                    if alias in self.params:
+                        self.params.pop(alias)
+
+    def _create(self, namespace):
+        request_body = None
+        k8s_obj = None
+        try:
+            request_body = self.helper.request_body_from_params(self.params)
+        except KubernetesException as exc:
+            self.fail_json(msg="Failed to create object: {0}".format(exc.message))
+        if not self.check_mode:
+            try:
+                k8s_obj = self.helper.create_object(namespace, body=request_body)
+            except KubernetesException as exc:
+                self.fail_json(msg="Failed to create object: {0}".format(exc.message),
+                               error=exc.value.get('status'))
+        return k8s_obj
+
+    def _read(self, name, namespace):
+        k8s_obj = None
+        try:
+            k8s_obj = self.helper.get_object(name, namespace)
+        except KubernetesException as exc:
+            self.fail_json(msg='Failed to retrieve requested object',
+                           error=exc.value.get('status'))
+        return k8s_obj
+
+    def load_resource_definition(self, src):
+        """ Load the requested src path """
+        result = None
+        path = os.path.normpath(src)
+        if not os.path.exists(path):
+            self.fail_json(msg="Error accessing {0}. Does the file exist?".format(path))
+        try:
+            result = yaml.safe_load(open(path, 'r'))
+        except (IOError, yaml.YAMLError) as exc:
+            self.fail_json(msg="Error loading resource_definition: {0}".format(exc))
+        return result
+
+    def resource_to_parameters(self, resource):
+        """ Converts a resource definition to module parameters """
+        parameters = {}
+        for key, value in iteritems(resource):
+            if key in ('apiVersion', 'kind', 'status'):
+                continue
+            elif key == 'metadata' and isinstance(value, dict):
+                for meta_key, meta_value in iteritems(value):
+                    if meta_key in ('name', 'namespace', 'labels', 'annotations'):
+                        parameters[meta_key] = meta_value
+            elif key in self.helper.argspec and value is not None:
+                parameters[key] = value
+            elif isinstance(value, dict):
+                self._add_parameter(value, [key], parameters)
+        return parameters
+
+    def _add_parameter(self, request, path, parameters):
+        for key, value in iteritems(request):
+            if path:
+                param_name = '_'.join(path + [self._to_snake(key)])
+            else:
+                param_name = self.helper.attribute_to_snake(key)
+            if param_name in self.helper.argspec and value is not None:
+                parameters[param_name] = value
+            elif isinstance(value, dict):
+                continue_path = copy.copy(path) if path else []
+                continue_path.append(self.helper.attribute_to_snake(key))
+                self._add_parameter(value, continue_path, parameters)
+            else:
+                self.fail_json(
+                    msg=("Error parsing resource definition. Encountered {0}, which does not map to a parameter "
+                         "expected by the OpenShift Python module.".format(param_name))
+                )
+
+    @staticmethod
+    def _to_snake(name):
+        """
+        Convert a string from camel to snake
+        :param name: string to convert
+        :return: string
+        """
+        if not name:
+            return name
+
+        def replace(m):
+            m = m.group(0)
+            return m[0] + '_' + m[1:]
+
+        p = r'[a-z][A-Z]|' \
+            r'[A-Z]{2}[a-z]'
+        result = re.sub(p, replace, name)
+        return result.lower()
+
+
+class OpenShiftAnsibleModuleHelper(AnsibleMixin, OpenShiftObjectHelper):
+    pass
+
+
+class OpenShiftAnsibleModule(KubernetesAnsibleModule):
+    def __init__(self):
+        super(OpenShiftAnsibleModule, self).__init__()
+
+    @property
+    def _argspec(self):
+        args = super(OpenShiftAnsibleModule, self)._argspec
+        args.update(copy.deepcopy(OPENSHIFT_ARG_SPEC))
+        return args
+
+    def _get_helper(self, api_version, kind):
+        try:
+            helper = OpenShiftAnsibleModuleHelper(api_version=api_version, kind=kind, debug=False)
+            helper.get_model(api_version, kind)
+            return helper
+        except KubernetesException as exc:
+            self.exit_json(msg="Error initializing module helper {}".format(exc.message))
+
+    def _create(self, namespace):
+        if self.kind.lower() == 'project':
+            return self._create_project()
+        return super(OpenShiftAnsibleModule, self)._create(namespace)
+
+    def _create_project(self):
+        new_obj = None
+        k8s_obj = None
+        try:
+            new_obj = self.helper.object_from_params(self.params)
+        except KubernetesException as exc:
+            self.fail_json(msg="Failed to create object: {}".format(exc.message))
+        try:
+            k8s_obj = self.helper.create_project(metadata=new_obj.metadata,
+                                                 display_name=self.params.get('display_name'),
+                                                 description=self.params.get('description'))
+        except KubernetesException as exc:
+            self.fail_json(msg='Failed to retrieve requested object',
+                           error=exc.value.get('status'))
+        return k8s_obj
diff --git a/lib/ansible/module_utils/k8s_common.py b/lib/ansible/module_utils/k8s/helper.py
similarity index 70%
rename from lib/ansible/module_utils/k8s_common.py
rename to lib/ansible/module_utils/k8s/helper.py
index 900238fa732..f8f6098dda6 100644
--- a/lib/ansible/module_utils/k8s_common.py
+++ b/lib/ansible/module_utils/k8s/helper.py
@@ -1,5 +1,5 @@
 #
-#  Copyright 2017 Red Hat | Ansible
+#  Copyright 2018 Red Hat | Ansible
 #
 # This file is part of Ansible
 #
@@ -16,34 +16,20 @@
 # You should have received a copy of the GNU General Public License
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 
-from __future__ import absolute_import, division, print_function
-
-import os
-import re
-import copy
 import base64
+import copy
 
+from ansible.module_utils.six import iteritems, string_types
 from keyword import kwlist
 
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.basic import AnsibleModule
-
 try:
     from openshift.helper import PRIMITIVES
-    from openshift.helper.kubernetes import KubernetesObjectHelper
     from openshift.helper.exceptions import KubernetesException
     HAS_K8S_MODULE_HELPER = True
 except ImportError as exc:
-    class KubernetesObjectHelper(object):
-        pass
     HAS_K8S_MODULE_HELPER = False
 
-try:
-    import yaml
-    HAS_YAML = True
-except ImportError:
-    HAS_YAML = False
-
+# TODO Remove string_utils dependency
 try:
     import string_utils
     HAS_STRING_UTILS = True
@@ -55,7 +41,7 @@ ARG_ATTRIBUTES_BLACKLIST = ('property_path',)
 PYTHON_KEYWORD_MAPPING = dict(zip(['_{0}'.format(item) for item in kwlist], kwlist))
 PYTHON_KEYWORD_MAPPING.update(dict([reversed(item) for item in iteritems(PYTHON_KEYWORD_MAPPING)]))
 
-ARG_SPEC = {
+COMMON_ARG_SPEC = {
     'state': {
         'default': 'present',
         'choices': ['present', 'absent'],
@@ -74,12 +60,13 @@ ARG_SPEC = {
     'kind': {},
     'name': {},
     'namespace': {},
-    'description': {},
-    'display_name': {},
     'api_version': {
         'default': 'v1',
         'aliases': ['api', 'version'],
     },
+}
+
+AUTH_ARG_SPEC = {
     'kubeconfig': {
         'type': 'path',
     },
@@ -106,6 +93,11 @@ ARG_SPEC = {
     },
 }
 
+OPENSHIFT_ARG_SPEC = {
+    'description': {},
+    'display_name': {},
+}
+
 
 class AnsibleMixin(object):
     _argspec_cache = None
@@ -118,8 +110,9 @@ class AnsibleMixin(object):
         """
         if self._argspec_cache:
             return self._argspec_cache
-
-        argument_spec = copy.deepcopy(ARG_SPEC)
+        argument_spec = copy.deepcopy(COMMON_ARG_SPEC)
+        argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
+        argument_spec.update(copy.deepcopy(OPENSHIFT_ARG_SPEC))
         argument_spec.update(self.__transform_properties(self.properties))
         self._argspec_cache = argument_spec
         return self._argspec_cache
@@ -638,275 +631,3 @@ class AnsibleMixin(object):
                     if len(choices) > 0:
                         args[arg_prefix + prop]['choices'] = choices
         return args
-
-
-class KubernetesAnsibleModuleHelper(AnsibleMixin, KubernetesObjectHelper):
-    pass
-
-
-class KubernetesAnsibleModule(AnsibleModule):
-
-    def __init__(self):
-
-        if not HAS_K8S_MODULE_HELPER:
-            raise Exception(
-                "This module requires the OpenShift Python client. Try `pip install openshift`"
-            )
-
-        if not HAS_YAML:
-            raise Exception(
-                "This module requires PyYAML. Try `pip install PyYAML`"
-            )
-
-        if not HAS_STRING_UTILS:
-            raise Exception(
-                "This module requires Python string utils. Try `pip install python-string-utils`"
-            )
-
-        mutually_exclusive = [
-            ('resource_definition', 'src'),
-        ]
-
-        AnsibleModule.__init__(self,
-                               argument_spec=self._argspec,
-                               supports_check_mode=True,
-                               mutually_exclusive=mutually_exclusive)
-
-        self.kind = self.params.pop('kind')
-        self.api_version = self.params.pop('api_version')
-        self.resource_definition = self.params.pop('resource_definition')
-        self.src = self.params.pop('src')
-        if self.src:
-            self.resource_definition = self.load_resource_definition(self.src)
-
-        if self.resource_definition:
-            self.api_version = self.resource_definition.get('apiVersion')
-            self.kind = self.resource_definition.get('kind')
-
-        self.api_version = self.api_version.lower()
-        self.kind = self._to_snake(self.kind)
-
-        if not self.api_version:
-            self.fail_json(
-                msg=("Error: no api_version specified. Use the api_version parameter, or provide it as part of a ",
-                     "resource_definition.")
-            )
-        if not self.kind:
-            self.fail_json(
-                msg="Error: no kind specified. Use the kind parameter, or provide it as part of a resource_definition"
-            )
-
-        self.helper = self._get_helper(self.api_version, self.kind)
-
-    @property
-    def _argspec(self):
-        argspec = copy.deepcopy(ARG_SPEC)
-        argspec.pop('display_name')
-        argspec.pop('description')
-        return argspec
-
-    def _get_helper(self, api_version, kind):
-        try:
-            helper = KubernetesAnsibleModuleHelper(api_version=api_version, kind=kind, debug=False)
-            helper.get_model(api_version, kind)
-            return helper
-        except KubernetesException as exc:
-            self.fail_json(msg="Error initializing module helper {0}".format(exc.message))
-
-    def execute_module(self):
-        if self.resource_definition:
-            resource_params = self.resource_to_parameters(self.resource_definition)
-            self.params.update(resource_params)
-
-        self._authenticate()
-
-        state = self.params.pop('state', None)
-        force = self.params.pop('force', False)
-        name = self.params.get('name')
-        namespace = self.params.get('namespace')
-        existing = None
-
-        self._remove_aliases()
-
-        return_attributes = dict(changed=False, result=dict())
-
-        if self._diff:
-            return_attributes['request'] = self.helper.request_body_from_params(self.params)
-
-        if self.helper.base_model_name_snake.endswith('list'):
-            k8s_obj = self._read(name, namespace)
-            return_attributes['result'] = k8s_obj.to_dict()
-            self.exit_json(**return_attributes)
-
-        try:
-            existing = self.helper.get_object(name, namespace)
-        except KubernetesException as exc:
-            self.fail_json(msg='Failed to retrieve requested object: {0}'.format(exc.message),
-                           error=exc.value.get('status'))
-
-        if state == 'absent':
-            if not existing:
-                # The object already does not exist
-                self.exit_json(**return_attributes)
-            else:
-                # Delete the object
-                if not self.check_mode:
-                    try:
-                        self.helper.delete_object(name, namespace)
-                    except KubernetesException as exc:
-                        self.fail_json(msg="Failed to delete object: {0}".format(exc.message),
-                                       error=exc.value.get('status'))
-                return_attributes['changed'] = True
-                self.exit_json(**return_attributes)
-        else:
-            if not existing:
-                k8s_obj = self._create(namespace)
-                return_attributes['result'] = k8s_obj.to_dict()
-                return_attributes['changed'] = True
-                self.exit_json(**return_attributes)
-
-            if existing and force:
-                k8s_obj = None
-                request_body = self.helper.request_body_from_params(self.params)
-                if not self.check_mode:
-                    try:
-                        k8s_obj = self.helper.replace_object(name, namespace, body=request_body)
-                    except KubernetesException as exc:
-                        self.fail_json(msg="Failed to replace object: {0}".format(exc.message),
-                                       error=exc.value.get('status'))
-                return_attributes['result'] = k8s_obj.to_dict()
-                return_attributes['changed'] = True
-                self.exit_json(**return_attributes)
-
-            # Check if existing object should be patched
-            k8s_obj = copy.deepcopy(existing)
-            try:
-                self.helper.object_from_params(self.params, obj=k8s_obj)
-            except KubernetesException as exc:
-                self.fail_json(msg="Failed to patch object: {0}".format(exc.message))
-            match, diff = self.helper.objects_match(existing, k8s_obj)
-            if match:
-                return_attributes['result'] = existing.to_dict()
-                self.exit_json(**return_attributes)
-            elif self._diff:
-                return_attributes['differences'] = diff
-            # Differences exist between the existing obj and requested params
-            if not self.check_mode:
-                try:
-                    k8s_obj = self.helper.patch_object(name, namespace, k8s_obj)
-                except KubernetesException as exc:
-                    self.fail_json(msg="Failed to patch object: {0}".format(exc.message))
-            return_attributes['result'] = k8s_obj.to_dict()
-            return_attributes['changed'] = True
-            self.exit_json(**return_attributes)
-
-    def _authenticate(self):
-        try:
-            auth_options = {}
-            auth_args = ('host', 'api_key', 'kubeconfig', 'context', 'username', 'password',
-                         'cert_file', 'key_file', 'ssl_ca_cert', 'verify_ssl')
-            for key, value in iteritems(self.params):
-                if key in auth_args and value is not None:
-                    auth_options[key] = value
-            self.helper.set_client_config(**auth_options)
-        except KubernetesException as e:
-            self.fail_json(msg='Error loading config', error=str(e))
-
-    def _remove_aliases(self):
-        """
-        The helper doesn't know what to do with aliased keys
-        """
-        for k, v in iteritems(self._argspec):
-            if 'aliases' in v:
-                for alias in v['aliases']:
-                    if alias in self.params:
-                        self.params.pop(alias)
-
-    def _create(self, namespace):
-        request_body = None
-        k8s_obj = None
-        try:
-            request_body = self.helper.request_body_from_params(self.params)
-        except KubernetesException as exc:
-            self.fail_json(msg="Failed to create object: {0}".format(exc.message))
-        if not self.check_mode:
-            try:
-                k8s_obj = self.helper.create_object(namespace, body=request_body)
-            except KubernetesException as exc:
-                self.fail_json(msg="Failed to create object: {0}".format(exc.message),
-                               error=exc.value.get('status'))
-        return k8s_obj
-
-    def _read(self, name, namespace):
-        k8s_obj = None
-        try:
-            k8s_obj = self.helper.get_object(name, namespace)
-        except KubernetesException as exc:
-            self.fail_json(msg='Failed to retrieve requested object',
-                           error=exc.value.get('status'))
-        return k8s_obj
-
-    def load_resource_definition(self, src):
-        """ Load the requested src path """
-        result = None
-        path = os.path.normpath(src)
-        if not os.path.exists(path):
-            self.fail_json(msg="Error accessing {0}. Does the file exist?".format(path))
-        try:
-            result = yaml.safe_load(open(path, 'r'))
-        except (IOError, yaml.YAMLError) as exc:
-            self.fail_json(msg="Error loading resource_definition: {0}".format(exc))
-        return result
-
-    def resource_to_parameters(self, resource):
-        """ Converts a resource definition to module parameters """
-        parameters = {}
-        for key, value in iteritems(resource):
-            if key in ('apiVersion', 'kind', 'status'):
-                continue
-            elif key == 'metadata' and isinstance(value, dict):
-                for meta_key, meta_value in iteritems(value):
-                    if meta_key in ('name', 'namespace', 'labels', 'annotations'):
-                        parameters[meta_key] = meta_value
-            elif key in self.helper.argspec and value is not None:
-                parameters[key] = value
-            elif isinstance(value, dict):
-                self._add_parameter(value, [key], parameters)
-        return parameters
-
-    def _add_parameter(self, request, path, parameters):
-        for key, value in iteritems(request):
-            if path:
-                param_name = '_'.join(path + [self._to_snake(key)])
-            else:
-                param_name = self.helper.attribute_to_snake(key)
-            if param_name in self.helper.argspec and value is not None:
-                parameters[param_name] = value
-            elif isinstance(value, dict):
-                continue_path = copy.copy(path) if path else []
-                continue_path.append(self.helper.attribute_to_snake(key))
-                self._add_parameter(value, continue_path, parameters)
-            else:
-                self.fail_json(
-                    msg=("Error parsing resource definition. Encountered {0}, which does not map to a parameter "
-                         "expected by the OpenShift Python module.".format(param_name))
-                )
-
-    @staticmethod
-    def _to_snake(name):
-        """
-        Convert a string from camel to snake
-        :param name: string to convert
-        :return: string
-        """
-        if not name:
-            return name
-
-        def replace(m):
-            m = m.group(0)
-            return m[0] + '_' + m[1:]
-
-        p = r'[a-z][A-Z]|' \
-            r'[A-Z]{2}[a-z]'
-        result = re.sub(p, replace, name)
-        return result.lower()
diff --git a/lib/ansible/module_utils/openshift_common.py b/lib/ansible/module_utils/openshift_common.py
deleted file mode 100644
index 6cccd8b40e5..00000000000
--- a/lib/ansible/module_utils/openshift_common.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-#  Copyright 2018 Red Hat | Ansible
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
-
-import copy
-
-from ansible.module_utils.k8s_common import KubernetesAnsibleModule, AnsibleMixin, ARG_SPEC
-
-try:
-    from openshift.helper.openshift import OpenShiftObjectHelper
-    from openshift.helper.exceptions import KubernetesException
-    HAS_OPENSHIFT_HELPER = True
-except ImportError as exc:
-    class OpenShiftObjectHelper(object):
-        pass
-    HAS_OPENSHIFT_HELPER = False
-
-
-class OpenShiftAnsibleModuleHelper(AnsibleMixin, OpenShiftObjectHelper):
-    pass
-
-
-class OpenShiftAnsibleModule(KubernetesAnsibleModule):
-    def __init__(self):
-
-        if not HAS_OPENSHIFT_HELPER:
-            raise Exception(
-                "This module requires the OpenShift Python client. Try `pip install openshift`"
-            )
-
-        super(OpenShiftAnsibleModule, self).__init__()
-
-    @property
-    def _argspec(self):
-        return copy.deepcopy(ARG_SPEC)
-
-    def _get_helper(self, api_version, kind):
-        try:
-            helper = OpenShiftAnsibleModuleHelper(api_version=api_version, kind=kind, debug=False)
-            helper.get_model(api_version, kind)
-            return helper
-        except KubernetesException as exc:
-            self.exit_json(msg="Error initializing module helper {}".format(exc.message))
-
-    def _create(self, namespace):
-        if self.kind.lower() == 'project':
-            return self._create_project()
-        return super(OpenShiftAnsibleModule, self)._create(namespace)
-
-    def _create_project(self):
-        new_obj = None
-        k8s_obj = None
-        try:
-            new_obj = self.helper.object_from_params(self.params)
-        except KubernetesException as exc:
-            self.fail_json(msg="Failed to create object: {}".format(exc.message))
-        try:
-            k8s_obj = self.helper.create_project(metadata=new_obj.metadata,
-                                                 display_name=self.params.get('display_name'),
-                                                 description=self.params.get('description'))
-        except KubernetesException as exc:
-            self.fail_json(msg='Failed to retrieve requested object',
-                           error=exc.value.get('status'))
-        return k8s_obj
diff --git a/lib/ansible/modules/clustering/k8s/k8s_raw.py b/lib/ansible/modules/clustering/k8s/k8s_raw.py
index d64d9fc1bef..38954511010 100644
--- a/lib/ansible/modules/clustering/k8s/k8s_raw.py
+++ b/lib/ansible/modules/clustering/k8s/k8s_raw.py
@@ -136,7 +136,7 @@ diff:
   type: list
 '''
 
-from ansible.module_utils.k8s_common import KubernetesAnsibleModule
+from ansible.module_utils.k8s.common import KubernetesAnsibleModule
 
 
 def main():
diff --git a/lib/ansible/modules/clustering/openshift/openshift_raw.py b/lib/ansible/modules/clustering/openshift/openshift_raw.py
index 20cbdfbbdc5..9a8c2955a24 100644
--- a/lib/ansible/modules/clustering/openshift/openshift_raw.py
+++ b/lib/ansible/modules/clustering/openshift/openshift_raw.py
@@ -176,7 +176,7 @@ diff:
   type: list
 '''
 
-from ansible.module_utils.openshift_common import OpenShiftAnsibleModule
+from ansible.module_utils.k8s.common import OpenShiftAnsibleModule
 
 
 def main():