Skip to content

Commit

Permalink
Merge pull request #4669 from kwoodson/storageclass
Browse files Browse the repository at this point in the history
Merged by openshift-bot
  • Loading branch information
OpenShift Bot authored Jul 18, 2017
2 parents 057a58d + 94923be commit 7422035
Show file tree
Hide file tree
Showing 10 changed files with 2,240 additions and 16 deletions.
1,688 changes: 1,688 additions & 0 deletions roles/lib_openshift/library/oc_storageclass.py

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions roles/lib_openshift/src/ansible/oc_storageclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# pylint: skip-file
# flake8: noqa

def main():
'''
ansible oc module for storageclass
'''

module = AnsibleModule(
argument_spec=dict(
kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'),
state=dict(default='present', type='str', choices=['present', 'absent', 'list']),
debug=dict(default=False, type='bool'),
name=dict(default=None, type='str'),
annotations=dict(default=None, type='dict'),
parameters=dict(default=None, type='dict'),
provisioner=dict(default='aws-ebs', type='str', choices=['aws-ebs', 'gce-pd', 'glusterfs', 'cinder']),
api_version=dict(default='v1', type='str'),
default_storage_class=dict(default="false", type='str'),
),
supports_check_mode=True,
)

rval = OCStorageClass.run_ansible(module.params, module.check_mode)
if 'failed' in rval:
return module.fail_json(**rval)

return module.exit_json(**rval)


if __name__ == '__main__':
main()
155 changes: 155 additions & 0 deletions roles/lib_openshift/src/class/oc_storageclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# pylint: skip-file
# flake8: noqa

# pylint: disable=too-many-instance-attributes
class OCStorageClass(OpenShiftCLI):
''' Class to wrap the oc command line tools '''
kind = 'storageclass'

# pylint allows 5
# pylint: disable=too-many-arguments
def __init__(self,
config,
verbose=False):
''' Constructor for OCStorageClass '''
super(OCStorageClass, self).__init__(None, kubeconfig=config.kubeconfig, verbose=verbose)
self.config = config
self.storage_class = None

def exists(self):
''' return whether a storageclass exists'''
if self.storage_class:
return True

return False

def get(self):
'''return storageclass '''
result = self._get(self.kind, self.config.name)
if result['returncode'] == 0:
self.storage_class = StorageClass(content=result['results'][0])
elif '\"%s\" not found' % self.config.name in result['stderr']:
result['returncode'] = 0
result['results'] = [{}]

return result

def delete(self):
'''delete the object'''
return self._delete(self.kind, self.config.name)

def create(self):
'''create the object'''
return self._create_from_content(self.config.name, self.config.data)

def update(self):
'''update the object'''
# parameters are currently unable to be updated. need to delete and recreate
self.delete()
# pause here and attempt to wait for delete.
# Better option would be to poll
import time
time.sleep(5)
return self.create()

def needs_update(self):
''' verify an update is needed '''
# check if params have updated
if self.storage_class.get_parameters() != self.config.parameters:
return True

for anno_key, anno_value in self.storage_class.get_annotations().items():
if 'is-default-class' in anno_key and anno_value != self.config.default_storage_class:
return True

return False

@staticmethod
# pylint: disable=too-many-return-statements,too-many-branches
# TODO: This function should be refactored into its individual parts.
def run_ansible(params, check_mode):
'''run the ansible idempotent code'''

rconfig = StorageClassConfig(params['name'],
provisioner="kubernetes.io/{}".format(params['provisioner']),
parameters=params['parameters'],
annotations=params['annotations'],
api_version="storage.k8s.io/{}".format(params['api_version']),
default_storage_class=params.get('default_storage_class', 'false'),
kubeconfig=params['kubeconfig'],
)

oc_sc = OCStorageClass(rconfig, verbose=params['debug'])

state = params['state']

api_rval = oc_sc.get()

#####
# Get
#####
if state == 'list':
return {'changed': False, 'results': api_rval['results'], 'state': 'list'}

########
# Delete
########
if state == 'absent':
if oc_sc.exists():

if check_mode:
return {'changed': True, 'msg': 'Would have performed a delete.'}

api_rval = oc_sc.delete()

return {'changed': True, 'results': api_rval, 'state': 'absent'}

return {'changed': False, 'state': 'absent'}

if state == 'present':
########
# Create
########
if not oc_sc.exists():

if check_mode:
return {'changed': True, 'msg': 'Would have performed a create.'}

# Create it here
api_rval = oc_sc.create()

if api_rval['returncode'] != 0:
return {'failed': True, 'msg': api_rval}

# return the created object
api_rval = oc_sc.get()

if api_rval['returncode'] != 0:
return {'failed': True, 'msg': api_rval}

return {'changed': True, 'results': api_rval, 'state': 'present'}

########
# Update
########
if oc_sc.needs_update():
api_rval = oc_sc.update()

if api_rval['returncode'] != 0:
return {'failed': True, 'msg': api_rval}

# return the created object
api_rval = oc_sc.get()

if api_rval['returncode'] != 0:
return {'failed': True, 'msg': api_rval}

return {'changed': True, 'results': api_rval, 'state': 'present'}

return {'changed': False, 'results': api_rval, 'state': 'present'}


return {'failed': True,
'changed': False,
'msg': 'Unknown state passed. %s' % state,
'state': 'unknown'}
86 changes: 86 additions & 0 deletions roles/lib_openshift/src/doc/storageclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# flake8: noqa
# pylint: skip-file

DOCUMENTATION = '''
---
module: oc_storageclass
short_description: Create, modify, and idempotently manage openshift storageclasses.
description:
- Manage openshift storageclass objects programmatically.
options:
state:
description:
- State represents whether to create, modify, delete, or list
required: False
default: present
choices: ["present", "absent", "list"]
aliases: []
kubeconfig:
description:
- The path for the kubeconfig file to use for authentication
required: false
default: /etc/origin/master/admin.kubeconfig
aliases: []
debug:
description:
- Turn on debug output.
required: false
default: False
aliases: []
name:
description:
- Name of the object that is being queried.
required: false
default: None
aliases: []
provisioner:
description:
- Any annotations to add to the storageclass
required: false
default: 'aws-ebs'
aliases: []
default_storage_class:
description:
- Whether or not this is the default storage class
required: false
default: False
aliases: []
parameters:
description:
- A dictionary with the parameters to configure the storageclass. This will be based on provisioner
required: false
default: None
aliases: []
api_version:
description:
- The api version.
required: false
default: v1
aliases: []
author:
- "Kenny Woodson <[email protected]>"
extends_documentation_fragment: []
'''

EXAMPLES = '''
- name: get storageclass
run_once: true
oc_storageclass:
name: gp2
state: list
register: registry_sc_out

- name: create the storageclass
oc_storageclass:
run_once: true
name: gp2
parameters:
type: gp2
encrypted: 'true'
kmsKeyId: '<full kms key arn>'
provisioner: aws-ebs
default_storage_class: False
register: sc_out
notify:
- restart openshift master services
'''
76 changes: 76 additions & 0 deletions roles/lib_openshift/src/lib/storageclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# pylint: skip-file
# flake8: noqa


# pylint: disable=too-many-instance-attributes
class StorageClassConfig(object):
''' Handle service options '''
# pylint: disable=too-many-arguments
def __init__(self,
name,
provisioner=None,
parameters=None,
annotations=None,
default_storage_class="false",
api_version='v1',
kubeconfig='/etc/origin/master/admin.kubeconfig'):
''' constructor for handling storageclass options '''
self.name = name
self.parameters = parameters
self.annotations = annotations
self.provisioner = provisioner
self.api_version = api_version
self.default_storage_class = str(default_storage_class).lower()
self.kubeconfig = kubeconfig
self.data = {}

self.create_dict()

def create_dict(self):
''' instantiates a storageclass dict '''
self.data['apiVersion'] = self.api_version
self.data['kind'] = 'StorageClass'
self.data['metadata'] = {}
self.data['metadata']['name'] = self.name

self.data['metadata']['annotations'] = {}
if self.annotations is not None:
self.data['metadata']['annotations'] = self.annotations

self.data['metadata']['annotations']['storageclass.beta.kubernetes.io/is-default-class'] = \
self.default_storage_class

if self.provisioner is None:
self.data['provisioner'] = 'kubernetes.io/aws-ebs'
else:
self.data['provisioner'] = self.provisioner

self.data['parameters'] = {}
if self.parameters is not None:
self.data['parameters'].update(self.parameters)

# default to aws if no params were passed
else:
self.data['parameters']['type'] = 'gp2'



# pylint: disable=too-many-instance-attributes,too-many-public-methods
class StorageClass(Yedit):
''' Class to model the oc storageclass object '''
annotations_path = "metadata.annotations"
provisioner_path = "provisioner"
parameters_path = "parameters"
kind = 'StorageClass'

def __init__(self, content):
'''StorageClass constructor'''
super(StorageClass, self).__init__(content=content)

def get_annotations(self):
''' get a list of ports '''
return self.get(StorageClass.annotations_path) or {}

def get_parameters(self):
''' get the service selector'''
return self.get(StorageClass.parameters_path) or {}
11 changes: 11 additions & 0 deletions roles/lib_openshift/src/sources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,17 @@ oc_service.py:
- class/oc_service.py
- ansible/oc_service.py

oc_storageclass.py:
- doc/generated
- doc/license
- lib/import.py
- doc/storageclass
- ../../lib_utils/src/class/yedit.py
- lib/base.py
- lib/storageclass.py
- class/oc_storageclass.py
- ansible/oc_storageclass.py

oc_user.py:
- doc/generated
- doc/license
Expand Down
Loading

0 comments on commit 7422035

Please sign in to comment.