Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Kohl's Custom Changes Into Master Branch #10

Merged
merged 5 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ variables from the file specified.
Role Variables
--------------

* `generate_resources` - A flag to generate resources as json files
rather than provisioning them. Defaults to `False`. See
[additional notes on the generate_resources flag](#Additional-notes-on-the-generate_resources-flag)
for more details.

* `oc_cmd_base` - The base `oc` command. Defaults to "oc", but can be set to
specify a different path or add custom options

Expand Down Expand Up @@ -408,6 +413,21 @@ specified above for `projects[*].resources` with the
addition that each entry here must specify `metadata.namespace` to specify
the target project for the resource.

### Additional notes on the `generate_resources` flag

* All files will be created in a directory named `manifests` in the format
`<scope>_<kind>_<name>.json` where:
* `scope` is "cluster" for a cluster resource, or the target namespace name
* `kind` is the Kubernetes resource kind
* `name` is the metadata name for the resource
* If a project does not exist, this role will still attempt to create the project.
* Modification actions to a resource requires the resource to exist so it can be
used for comparison.
* If service accounts, role bindings, and cluster role bindings are defined as
`service_accounts`, `role_bindings`, and `cluster_role_bindings` variables,
the role will attempt to apply them. If you want them to be generated, you
would have to define them as you would any other resource.

Example Playbook with Provisioning by Role Variables
----------------------------------------------------

Expand Down
2 changes: 2 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ openshift_resource_path:
openshift_provision_change_record: ''

openshift_provision_cluster_vars: {}

generate_resources: false
52 changes: 41 additions & 11 deletions library/openshift_provision.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,12 @@ def compare_set_list(path, src, dst):
return list(compare_values(['/' + field], current, config))

def set_dict_defaults(d, default):
for k, v in default.items():
if k not in d:
d[k] = v
if d is None:
d = default.items()
else:
for k, v in default.items():
if k not in d:
d[k] = v
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block of code should fix gnuthought#53


def normalize_cpu_units(cpu):
cpu = str(cpu)
Expand Down Expand Up @@ -302,7 +305,7 @@ def merge_dict(merged, patch, overwrite=True):

def mark_list_is_set(lst, key_name=None):
lst.append({
'__special_list_type__': 'set'
'__special_list_type__': 'set'
})

def list_is_set(lst):
Expand Down Expand Up @@ -838,8 +841,8 @@ def normalize_PolicyRule_V1(rule):
# to always be null? Remove for comparison.
if 'attributeRestrictions' in rule and rule['attributeRestrictions'] == None:
del rule['attributeRestrictions']



def normalize_Probe_V1(probe):
if probe == None:
Expand Down Expand Up @@ -1055,6 +1058,7 @@ def __init__(self, module):
self.patch = None
self.patch_type = module.params['patch_type']
self.resource = module.params['resource']
self.generate_resources = module.params['generate_resources']

if not 'kind' in self.resource:
raise Exception('resource must define kind')
Expand Down Expand Up @@ -1393,13 +1397,15 @@ def provision(self):
if self.action == 'create':
if current_resource:
self.resource = current_resource
return
if not self.generate_resources:
return
elif self.action == 'apply':
if current_resource != None:
patch = self.compare_resource(current_resource)
if not patch:
self.resource = current_resource
return
if not self.generate_resources:
return
# If current resource does not match last_applied_configuration
# then we must switch to replace mode or risk unexpected behavior
if( current_resource_version
Expand All @@ -1413,18 +1419,21 @@ def provision(self):
patch = self.check_patch(current_resource)
if not patch:
self.resource = current_resource
return
if not self.generate_resources:
return
elif self.action == 'replace':
if current_resource == None:
self.action = 'create'
else:
patch = self.compare_resource(current_resource)
if not patch:
self.resource = current_resource
return
if not self.generate_resources:
return
elif self.action == 'delete':
if current_resource == None:
return
if not self.generate_resources:
return
elif self.action == 'ignore':
return

Expand All @@ -1439,6 +1448,21 @@ def provision(self):
if self.module.check_mode:
return

if self.generate_resources:
if not self.namespace:
scope = "cluster"
else:
scope = self.namespace

if not os.path.exists('./manifests'):
os.mkdir('./manifests')

resource_filename = "%s_%s_%s.json" % (scope, self.resource['kind'], self.resource['metadata']['name'])
resource_file = open("./manifests/" + resource_filename, 'w')
resource_file.write(str(json.dumps(self.resource)))
resource_file.close()
return

# Perform action on resource
if self.action == 'delete':
command = ['delete', self.resource['kind'], self.resource['metadata']['name']]
Expand Down Expand Up @@ -1495,6 +1519,12 @@ def run_module():
'fail_on_change': {
'type': 'bool',
'default': False
},
# Use role as resource generator instead of provisioner
'generate_resources': {
'type': 'bool',
'required': False,
'default': False
}
}

Expand Down
1 change: 1 addition & 0 deletions tasks/cluster-resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
connection:
oc_cmd: "{{ oc_cmd }}"
resource: "{{ resource }}"
generate_resources: "{{ generate_resources }}"
with_items: "{{ resource_list }}"
loop_control:
loop_var: resource
Expand Down
1 change: 1 addition & 0 deletions tasks/group.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
action: apply
connection:
oc_cmd: "{{ oc_cmd }}"
generate_resources: "{{ generate_resources }}"
resource:
apiVersion: v1
kind: Group
Expand Down
3 changes: 2 additions & 1 deletion tasks/helm-chart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

- name: Fetch helm chart
command: >-
helm fetch
helm fetch
{% if 'ca_file' in helm_chart.fetch %}--ca-file {{ helm_chart.fetch.ca_file | quote }}{% endif %}
{% if 'cert_file' in helm_chart.fetch %}--cert-file {{ helm_chart.fetch.cert_file | quote }}{% endif %}
{% if helm_chart.fetch.devel | default(False) | bool %}--devel{% endif %}
Expand Down Expand Up @@ -87,6 +87,7 @@
oc_cmd: "{{ oc_cmd }}"
namespace: "{{ project.name if project is defined else '' }}"
resource: "{{ item }}"
generate_resources: "{{ generate_resources }}"
with_items: "{{ process_helm_template.stdout | yaml_to_resource_list }}"
vars:
provision_action: >-
Expand Down
1 change: 1 addition & 0 deletions tasks/process-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
oc_cmd: "{{ oc_cmd }}"
namespace: "{{ project.name if project is defined else '' }}"
resource: "{{ item }}"
generate_resources: "{{ generate_resources }}"
with_items: >-
{{ process_template.stdout | from_json | json_query('items') }}
vars:
Expand Down
1 change: 1 addition & 0 deletions tasks/project-resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
oc_cmd: "{{ oc_cmd }}"
namespace: "{{ project.name }}"
resource: "{{ resource }}"
generate_resources: "{{ generate_resources }}"
with_items: "{{ resource_list }}"
loop_control:
loop_var: resource
Expand Down
66 changes: 66 additions & 0 deletions tests/test-openshift_provision-generate_resource.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
- name: Set Facts
hosts: localhost
connection: local
vars_files:
- login-creds.yml
tasks:
- include_tasks: setup-test.yml
- set_fact:
ignore_differences:
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: ''
creationTimestamp: null
selfLink: null
namespace: provision-test
spec:
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800

- name: Test Provision
hosts: localhost
connection: local
vars:
provision_service: >-
{{ lookup('template', 'resources/test-service.yml.j2')
| from_yaml }}
service_ports:
- name: 8080-tcp
port: 8080

roles:
- role: openshift-provision
openshift_clusters:
- projects:
- name: provision-test

tasks:
- name: Provision Service
openshift_provision:
connection: "{{ openshift_connection }}"
namespace: provision-test
resource: "{{ provision_service }}"
generate_resources: True

- name: Get Service
command: cat ./manifests/provision-test_Service_test-service.json
register: get_service
changed_when: false

- name: Verify Service
fail:
msg: |
Service not defined as expected
>>>
{{ cmp_service | to_yaml }}
===
{{ got_service | to_yaml }}
<<<
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 56, 58, and 60 look messed up to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seanmalloy I don't believe this is messed up, I believe I had used a different test as an example.
Ref:

- name: Verify ClusterResourceQuota Update
fail:
msg: |
ClusterResourceQuota not defined as expected
>>>
{{ cmp_clusterresourcequota | to_yaml }}
===
{{ got_clusterresourcequota | to_yaml }}
<<<

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vinny-sabatini sounds good

vars:
got_service: "{{ get_service.stdout | from_json | combine(ignore_differences, recursive=True) }}"
cmp_service: "{{ provision_service | combine(ignore_differences, recursive=True) }}"
when: >-
cmp_service.metadata != got_service.metadata or
cmp_service.spec != got_service.spec