Add proper k8s *List kind support (#52529)

* Add proper k8s *List kind support

* set defaults more intelligently

* reimplement list support so that it will work in all versions of the client

* clean up debugging code
This commit is contained in:
Fabian von Feilitzsch 2019-02-22 21:10:42 -05:00 committed by Will Thames
parent cc9c72d6f8
commit 52ec80fbe9
3 changed files with 168 additions and 16 deletions

View file

@ -130,17 +130,34 @@ class KubernetesRawModule(KubernetesAnsibleModule):
}
}]
def flatten_list_kind(self, list_resource, definitions):
flattened = []
parent_api_version = list_resource.group_version if list_resource else None
parent_kind = list_resource.kind[:-4] if list_resource else None
for definition in definitions.get('items', []):
resource = self.find_resource(definition.get('kind', parent_kind), definition.get('apiVersion', parent_api_version), fail=True)
flattened.append((resource, self.set_defaults(resource, definition)))
return flattened
def execute_module(self):
changed = False
results = []
self.client = self.get_api_client()
flattened_definitions = []
for definition in self.resource_definitions:
kind = definition.get('kind', self.kind)
search_kind = kind
if kind.lower().endswith('list'):
search_kind = kind[:-4]
api_version = definition.get('apiVersion', self.api_version)
resource = self.find_resource(search_kind, api_version, fail=True)
if kind.endswith('List'):
resource = self.find_resource(kind, api_version, fail=False)
flattened_definitions.extend(self.flatten_list_kind(resource, definition))
else:
resource = self.find_resource(kind, api_version, fail=True)
flattened_definitions.append((resource, definition))
for (resource, definition) in flattened_definitions:
kind = definition.get('kind', self.kind)
api_version = definition.get('apiVersion', self.api_version)
definition = self.set_defaults(resource, definition)
self.warnings = []
if self.params['validate'] is not None:
@ -177,12 +194,12 @@ class KubernetesRawModule(KubernetesAnsibleModule):
def set_defaults(self, resource, definition):
definition['kind'] = resource.kind
definition['apiVersion'] = resource.group_version
if not definition.get('metadata'):
definition['metadata'] = {}
if self.name and not definition['metadata'].get('name'):
definition['metadata']['name'] = self.name
if resource.namespaced and self.namespace and not definition['metadata'].get('namespace'):
definition['metadata']['namespace'] = self.namespace
metadata = definition.get('metadata', {})
if self.name and not metadata.get('name'):
metadata['name'] = self.name
if resource.namespaced and self.namespace and not metadata.get('namespace'):
metadata['namespace'] = self.namespace
definition['metadata'] = metadata
return definition
def perform_action(self, resource, definition):
@ -197,12 +214,6 @@ class KubernetesRawModule(KubernetesAnsibleModule):
self.remove_aliases()
if definition['kind'].endswith('List'):
result['result'] = resource.get(namespace=namespace).to_dict()
result['changed'] = False
result['method'] = 'get'
return result
try:
# ignore append_hash for resources other than ConfigMap and Secret
if self.append_hash and definition['kind'] in ['ConfigMap', 'Secret']:

View file

@ -0,0 +1,140 @@
---
- name: Ensure testing1 namespace exists
k8s:
api_version: v1
kind: Namespace
name: testing1
- block:
- name: Create configmaps
k8s:
namespace: testing1
definition:
apiVersion: v1
kind: ConfigMapList
items: '{{ configmaps }}'
- name: Get ConfigMaps
k8s_facts:
api_version: v1
kind: ConfigMap
namespace: testing1
label_selectors:
- app=test
register: cms
- name: All three configmaps should exist
assert:
that: item.data.a is defined
with_items: '{{ cms.resources }}'
- name: Delete configmaps
k8s:
state: absent
namespace: testing1
definition:
apiVersion: v1
kind: ConfigMapList
items: '{{ configmaps }}'
- name: Get ConfigMaps
k8s_facts:
api_version: v1
kind: ConfigMap
namespace: testing1
label_selectors:
- app=test
register: cms
- name: All three configmaps should not exist
assert:
that: not cms.resources
vars:
configmaps:
- metadata:
name: list-example-1
labels:
app: test
data:
a: first
- metadata:
name: list-example-2
labels:
app: test
data:
a: second
- metadata:
name: list-example-3
labels:
app: test
data:
a: third
- block:
- name: Create list of arbitrary resources
k8s:
namespace: testing1
definition:
apiVersion: v1
kind: List
namespace: testing1
items: '{{ resources }}'
- name: Get the created resources
k8s_facts:
api_version: '{{ item.apiVersion }}'
kind: '{{ item.kind }}'
namespace: testing1
name: '{{ item.metadata.name }}'
register: list_resources
with_items: '{{ resources }}'
- name: All resources should exist
assert:
that: ((list_resources.results | sum(attribute="resources", start=[])) | length) == (resources | length)
- name: Delete list of arbitrary resources
k8s:
state: absent
namespace: testing1
definition:
apiVersion: v1
kind: List
namespace: testing1
items: '{{ resources }}'
- name: Get the resources
k8s_facts:
api_version: '{{ item.apiVersion }}'
kind: '{{ item.kind }}'
namespace: testing1
name: '{{ item.metadata.name }}'
register: list_resources
with_items: '{{ resources }}'
- name: The resources should not exist
assert:
that: not ((list_resources.results | sum(attribute="resources", start=[])) | length)
vars:
resources:
- apiVersion: v1
kind: ConfigMap
metadata:
name: list-example-4
data:
key: value
- apiVersion: v1
kind: Service
metadata:
name: list-example-svc
labels:
app: test
spec:
selector:
app: test
ports:
- protocol: TCP
targetPort: 8000
name: port-8000-tcp
port: 8000

View file

@ -285,6 +285,7 @@
loop: "{{ k8s_facts.results }}"
- include_tasks: crd.yml
- include_tasks: lists.yml
- include_tasks: append_hash.yml
always: