diff --git a/library/k8s_v1_horizontal_pod_autoscaler.py b/library/k8s_v1_horizontal_pod_autoscaler.py
index cce6a211..f8be0623 100644
--- a/library/k8s_v1_horizontal_pod_autoscaler.py
+++ b/library/k8s_v1_horizontal_pod_autoscaler.py
@@ -147,6 +147,15 @@ requirements:
'''
EXAMPLES = '''
+- name: Create replica set
+ k8s_v1_horizontal_pod_autoscaler.yml:
+ name: test-scaler
+ namespace: test
+ state: present
+ scale_target_ref_kind: ReplicaSet
+ scale_target_ref_name: test
+ min_replicas: 2
+ max_replicas: 5
'''
RETURN = '''
diff --git a/library/k8s_v1beta1_replica_set.py b/library/k8s_v1beta1_replica_set.py
index 2424295d..fa9c95d5 100644
--- a/library/k8s_v1beta1_replica_set.py
+++ b/library/k8s_v1beta1_replica_set.py
@@ -336,6 +336,17 @@ requirements:
'''
EXAMPLES = '''
+- name: Create replica set
+ k8s_v1beta1_replica_set.yml:
+ name: myreplicaset
+ namespace: test
+ state: present
+ replicas: 3
+ spec_template_metadata_labels:
+ name: myreplicaset
+ containers:
+ - name: myreplicaset
+ image: openshift/origin-ruby-sample:v1.0
'''
RETURN = '''
diff --git a/library/k8s_v1beta1_stateful_set.py b/library/k8s_v1beta1_stateful_set.py
index 8a83258a..9cf0c2bc 100644
--- a/library/k8s_v1beta1_stateful_set.py
+++ b/library/k8s_v1beta1_stateful_set.py
@@ -349,6 +349,22 @@ requirements:
'''
EXAMPLES = '''
+- name: Create stateful set
+ k8s_v1beta1_stateful_set.yml:
+ name: test
+ labels:
+ name: test
+ namespace: test
+ state: present
+ service_name: test
+ replicas: 3
+ spec_template_metadata_labels:
+ name: test
+ spec_template_metadata_name: test
+ termination_grace_period_seconds: 10
+ containers:
+ - name: test
+ image: openshift/origin-ruby-sample:v1.0
'''
RETURN = '''
diff --git a/module_utils/README.md b/module_utils/README.md
deleted file mode 100644
index e8c0d21f..00000000
--- a/module_utils/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-### module_utils
-
-If you're running Ansible 2.3, custom module_utils is supported.
-
-The K8s and OpenShift common modules will land in Ansible 2.4, so for now we're including the latest here, just to make life a little easier for those not running Ansible from source. As indicated above, you will need to have Ansible 2.3 installed for this to work.
-
-If your install of Ansible fails to find the common modules, then the easiest solution may be to run Ansible from source. If you need assistance, please view the [Running From Source guide](http://docs.ansible.com/ansible/intro_installation.html#running-from-source).
diff --git a/module_utils/k8s_common.py b/module_utils/k8s_common.py
deleted file mode 100644
index e8199f53..00000000
--- a/module_utils/k8s_common.py
+++ /dev/null
@@ -1,297 +0,0 @@
-#
-# Copyright 2017 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 .
-
-import copy
-import json
-import os
-
-from ansible.module_utils.basic import AnsibleModule
-
-try:
- from openshift.helper.ansible import KubernetesAnsibleModuleHelper, ARG_ATTRIBUTES_BLACKLIST
- from openshift.helper.exceptions import KubernetesException
- HAS_K8S_MODULE_HELPER = True
-except ImportError as exc:
- HAS_K8S_MODULE_HELPER = False
-
-try:
- import yaml
- HAS_YAML = True
-except ImportError:
- HAS_YAML = False
-
-
-class KubernetesAnsibleException(Exception):
- pass
-
-
-class KubernetesAnsibleModule(AnsibleModule):
- @staticmethod
- def get_helper(api_version, kind):
- return KubernetesAnsibleModuleHelper(api_version, kind)
-
- def __init__(self, kind, api_version):
- self.api_version = api_version
- self.kind = kind
- self.argspec_cache = None
-
- if not HAS_K8S_MODULE_HELPER:
- raise KubernetesAnsibleException(
- "This module requires the OpenShift Python client. Try `pip install openshift`"
- )
-
- if not HAS_YAML:
- raise KubernetesAnsibleException(
- "This module requires PyYAML. Try `pip install PyYAML`"
- )
-
- try:
- self.helper = self.get_helper(api_version, kind)
- except Exception as exc:
- raise KubernetesAnsibleException(
- "Error initializing AnsibleModuleHelper: {}".format(exc)
- )
-
- mutually_exclusive = (
- ('resource_definition', 'src'),
- )
-
- AnsibleModule.__init__(self,
- argument_spec=self.argspec,
- supports_check_mode=True,
- mutually_exclusive=mutually_exclusive)
-
- @property
- def argspec(self):
- """
- Build the module argument spec from the helper.argspec, removing any extra attributes not needed by
- Ansible.
-
- :return: dict: a valid Ansible argument spec
- """
- if not self.argspec_cache:
- spec = {}
- for arg_name, arg_properties in self.helper.argspec.items():
- spec[arg_name] = {}
- for option, option_value in arg_properties.items():
- if option not in ARG_ATTRIBUTES_BLACKLIST:
- if option == 'choices':
- if isinstance(option_value, dict):
- spec[arg_name]['choices'] = [value for key, value in option_value.items()]
- else:
- spec[arg_name]['choices'] = option_value
- else:
- spec[arg_name][option] = option_value
-
- self.argspec_cache = spec
- return self.argspec_cache
-
- def execute_module(self):
- """
- Performs basic CRUD operations on the model object. Ends by calling
- AnsibleModule.fail_json(), if an error is encountered, otherwise
- AnsibleModule.exit_json() with a dict containing:
- changed: boolean
- api_version: the API version
- : a dict representing the object's state
- :return: None
- """
-
- if self.params.get('debug'):
- self.helper.enable_debug(reset_logfile=False)
- self.helper.log_argspec()
-
- resource_definition = self.params.get('resource_definition')
- if self.params.get('src'):
- resource_definition = self.load_resource_definition(self.params['src'])
- if resource_definition:
- resource_params = self.resource_to_parameters(resource_definition)
- self.params.update(resource_params)
-
- state = self.params.get('state', None)
- force = self.params.get('force', False)
- name = self.params.get('name')
- namespace = self.params.get('namespace', None)
- existing = None
-
- return_attributes = dict(changed=False, api_version=self.api_version)
- return_attributes[self.helper.base_model_name_snake] = {}
-
- try:
- auth_options = {}
- for key, value in self.helper.argspec.items():
- if value.get('auth_option') and self.params.get(key) is not None:
- auth_options[key] = self.params[key]
- self.helper.set_client_config(**auth_options)
- except KubernetesException as e:
- self.fail_json(msg='Error loading config', error=str(e))
-
- if state is None:
- # This is a list, rollback or ? module with no 'state' param
- if self.helper.base_model_name_snake.endswith('list'):
- # For list modules, execute a GET, and exit
- k8s_obj = self._read(name, namespace)
- return_attributes[self.kind] = k8s_obj.to_dict()
- self.exit_json(**return_attributes)
- elif self.helper.has_method('create'):
- # For a rollback, execute a POST, and exit
- k8s_obj = self._create(namespace)
- return_attributes[self.kind] = k8s_obj.to_dict()
- return_attributes['changed'] = True
- self.exit_json(**return_attributes)
- else:
- self.fail_json(msg="Missing state parameter. Expected one of: present, absent")
-
- # CRUD modules
- try:
- existing = self.helper.get_object(name, namespace)
- except KubernetesException as exc:
- self.fail_json(msg='Failed to retrieve requested object: {}'.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: {}".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[self.kind] = 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: {}".format(exc.message),
- error=exc.value.get('status'))
- return_attributes[self.kind] = 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: {}".format(exc.message))
- match, diff = self.helper.objects_match(existing, k8s_obj)
- if match:
- return_attributes[self.kind] = existing.to_dict()
- self.exit_json(**return_attributes)
- else:
- self.helper.log('Existing:')
- self.helper.log(json.dumps(existing.to_dict(), indent=4))
- self.helper.log('\nDifferences:')
- self.helper.log(json.dumps(diff, indent=4))
- # 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: {}".format(exc.message))
- return_attributes[self.kind] = k8s_obj.to_dict()
- return_attributes['changed'] = True
- self.exit_json(**return_attributes)
-
- 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: {}".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: {}".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)
- self.helper.log("Reading definition from {}".format(path))
- if not os.path.exists(path):
- self.fail_json(msg="Error accessing {}. 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: {}".format(exc))
- return result
-
- def resource_to_parameters(self, resource):
- """ Converts a resource definition to module parameters """
- parameters = {}
- for key, value in resource.items():
- if key in ('apiVersion', 'kind', 'status'):
- continue
- elif key == 'metadata' and isinstance(value, dict):
- for meta_key, meta_value in value.items():
- 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)
- self.helper.log("Request to parameters: {}".format(json.dumps(parameters)))
- return parameters
-
- def _add_parameter(self, request, path, parameters):
- for key, value in request.items():
- if path:
- param_name = '_'.join(path + [self.helper.attribute_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 {}, which does not map to a module "
- "parameter. If this looks like a problem with the module, please open an issue at "
- "github.com/openshift/openshift-restclient-python/issues").format(param_name)
- )
diff --git a/module_utils/openshift_common.py b/module_utils/openshift_common.py
deleted file mode 100644
index a57f970f..00000000
--- a/module_utils/openshift_common.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# Copyright 2017 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 .
-
-from ansible.module_utils.k8s_common import KubernetesAnsibleException, KubernetesAnsibleModule
-
-try:
- from openshift.helper.ansible import OpenShiftAnsibleModuleHelper, ARG_ATTRIBUTES_BLACKLIST
- from openshift.helper.exceptions import KubernetesException, OpenShiftException
- HAS_OPENSHIFT_HELPER = True
-except ImportError as exc:
- HAS_OPENSHIFT_HELPER = False
-
-
-class OpenShiftAnsibleException(KubernetesAnsibleException):
- pass
-
-
-class OpenShiftAnsibleModule(KubernetesAnsibleModule):
- def __init__(self, kind, api_version):
- if not HAS_OPENSHIFT_HELPER:
- raise OpenShiftAnsibleException(
- "This module requires the OpenShift Python client. Try `pip install openshift`"
- )
-
- try:
- super(OpenShiftAnsibleModule, self).__init__(kind, api_version)
- except KubernetesAnsibleException as exc:
- raise OpenShiftAnsibleException(exc.args)
-
- @staticmethod
- def get_helper(api_version, kind):
- return OpenShiftAnsibleModuleHelper(api_version, kind)
-
- def _create(self, namespace):
- if self.kind.lower() == 'project':
- return self._create_project()
- else:
- 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/tasks/main.yml b/tasks/main.yml
index 8dde0877..55c73ccf 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,7 +1,7 @@
# tasks/main.yml
---
-- name: Intall latest openshift client
+- name: Install latest openshift client
pip:
name: https://github.com/openshift/openshift-restclient-python/archive/master.tar.gz
state: latest