mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-09 14:50:02 -07:00
Provide Kubernetes resource validation to k8s module (#43352)
* Provide Kubernetes resource validation to k8s module Use kubernetes-validate to validate Kubernetes resource definitions against the published schema * Additional tests for kubernetes-validate * Improve k8s error messages on exceptions Parse the response body for the message rather than returning a JSON blob If we've validated and there are warnings, return those too - they can be more helpful ``` "msg": "Failed to patch object: {\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{}, \"status\":\"Failure\",\"message\":\"[pos 334]: json: decNum: got first char 'h'\",\"code\":500}\n", ``` vs ``` "msg": "Failed to patch object: [pos 334]: json: decNum: got first char 'h'\nresource validation error at spec.replicas: 'hello' is not of type u'integer'", ``` * Update versions used In particular openshift/origin:3.9.0 * Add changelog for k8s validate change
This commit is contained in:
parent
ae0054a79e
commit
aaf29c785f
11 changed files with 355 additions and 22 deletions
|
@ -0,0 +1,61 @@
|
|||
- hosts: localhost
|
||||
connection: local
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
recreate_crd_default_merge_expectation: recreate_crd is failed
|
||||
playbook_namespace: ansible-test-k8s-older-openshift
|
||||
|
||||
tasks:
|
||||
- python_requirements_facts:
|
||||
dependencies:
|
||||
- openshift==0.6.0
|
||||
- kubernetes==6.0.0
|
||||
|
||||
# append_hash
|
||||
- name: use append_hash with ConfigMap
|
||||
k8s:
|
||||
definition:
|
||||
metadata:
|
||||
name: config-map-test
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
data:
|
||||
hello: world
|
||||
append_hash: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_append_hash
|
||||
|
||||
- name: assert that append_hash fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_append_hash is failed
|
||||
- "k8s_append_hash.msg == 'openshift >= 0.7.FIXME is required for append_hash'"
|
||||
|
||||
# merge_type
|
||||
- include_role:
|
||||
name: k8s
|
||||
tasks_from: crd
|
||||
|
||||
# validate
|
||||
- name: attempt to use validate with older openshift
|
||||
k8s:
|
||||
definition:
|
||||
metadata:
|
||||
name: config-map-test
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
data:
|
||||
hello: world
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_validate
|
||||
|
||||
- name: assert that validate fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_validate is failed
|
||||
- "k8s_validate.msg == 'openshift >= 0.7.FIXME is required for validate'"
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: kuard
|
||||
name: kuard
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kuard
|
||||
unwanted: value
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kuard
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/kuar-demo/kuard-amd64:1
|
||||
name: kuard
|
|
@ -0,0 +1,20 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: kuard
|
||||
name: kuard
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: hello
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kuard
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kuard
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/kuar-demo/kuard-amd64:1
|
||||
name: kuard
|
|
@ -0,0 +1,117 @@
|
|||
- block:
|
||||
- name: Create a namespace
|
||||
k8s:
|
||||
name: "{{ playbook_namespace }}"
|
||||
kind: namespace
|
||||
|
||||
- name: incredibly simple ConfigMap
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: hello
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
register: k8s_with_validate
|
||||
|
||||
- name: assert that k8s_with_validate succeeds
|
||||
assert:
|
||||
that:
|
||||
- k8s_with_validate is successful
|
||||
|
||||
- name: extra property does not fail without strict
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/kuard-extra-property.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
strict: no
|
||||
|
||||
- name: extra property fails with strict
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/kuard-extra-property.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
strict: yes
|
||||
ignore_errors: yes
|
||||
register: extra_property
|
||||
|
||||
- name: check that extra property fails with strict
|
||||
assert:
|
||||
that:
|
||||
- extra_property is failed
|
||||
|
||||
- name: invalid type fails at validation stage
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/kuard-invalid-type.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
strict: no
|
||||
ignore_errors: yes
|
||||
register: invalid_type
|
||||
|
||||
- name: check that invalid type fails
|
||||
assert:
|
||||
that:
|
||||
- invalid_type is failed
|
||||
|
||||
- name: invalid type fails with warnings when fail_on_error is False
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/kuard-invalid-type.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: no
|
||||
strict: no
|
||||
ignore_errors: yes
|
||||
register: invalid_type_no_fail
|
||||
|
||||
- name: check that invalid type fails
|
||||
assert:
|
||||
that:
|
||||
- invalid_type_no_fail is failed
|
||||
|
||||
- name: setup custom resource definition
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/setup-crd.yml"
|
||||
|
||||
- name: add custom resource definition
|
||||
k8s:
|
||||
src: "{{ role_path }}/files/crd-resource.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
strict: yes
|
||||
register: unknown_kind
|
||||
|
||||
- name: check that unknown kind warns
|
||||
assert:
|
||||
that:
|
||||
- unknown_kind is successful
|
||||
- "'warnings' in unknown_kind"
|
||||
|
||||
always:
|
||||
- name: remove custom resource
|
||||
k8s:
|
||||
definition: "{{ lookup('file', role_path + '/files/crd-resource.yml') }}"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
|
||||
- name: remove custom resource definitions
|
||||
k8s:
|
||||
definition: "{{ lookup('file', role_path + '/files/setup-crd.yml') }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete namespace
|
||||
k8s:
|
||||
state: absent
|
||||
definition:
|
||||
- kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: "{{ playbook_namespace }}"
|
||||
ignore_errors: yes
|
|
@ -0,0 +1,9 @@
|
|||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
playbook_namespace: ansible-test-k8s-validate
|
||||
|
||||
tasks:
|
||||
- include_role:
|
||||
name: k8s
|
||||
tasks_from: validate_installed
|
|
@ -0,0 +1,21 @@
|
|||
- hosts: localhost
|
||||
connection: local
|
||||
|
||||
tasks:
|
||||
- k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: hello
|
||||
namespace: default
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_no_validate
|
||||
|
||||
- name: assert that k8s_no_validate fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_no_validate is failed
|
||||
- "k8s_no_validate.msg == 'kubernetes-validate python library is required to validate resources'"
|
|
@ -12,14 +12,26 @@ MYTMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
|
|||
# but for the python3 tests we need virtualenv to use python3
|
||||
PYTHON=${ANSIBLE_TEST_PYTHON_INTERPRETER:-python}
|
||||
|
||||
# Test graceful failure for missing kubernetes-validate
|
||||
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/openshift-validate-not-installed"
|
||||
source "${MYTMPDIR}/openshift-validate-not-installed/bin/activate"
|
||||
$PYTHON -m pip install openshift==0.8.1
|
||||
ansible-playbook -v playbooks/validate_not_installed.yml "$@"
|
||||
|
||||
# Test validate with kubernetes-validate
|
||||
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/openshift-validate-installed"
|
||||
source "${MYTMPDIR}/openshift-validate-installed/bin/activate"
|
||||
$PYTHON -m pip install openshift==0.8.1 kubernetes-validate==1.12.0
|
||||
ansible-playbook -v playbooks/validate_installed.yml "$@"
|
||||
|
||||
# Test graceful failure for older versions of openshift
|
||||
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/openshift-0.6.0"
|
||||
source "${MYTMPDIR}/openshift-0.6.0/bin/activate"
|
||||
$PYTHON -m pip install 'openshift==0.6.0' 'kubernetes==6.0.0'
|
||||
$PYTHON -m pip install openshift==0.6.0 kubernetes==6.0.0
|
||||
ansible-playbook -v playbooks/merge_type_fail.yml "$@"
|
||||
|
||||
# Run full test suite
|
||||
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/openshift-recent"
|
||||
source "${MYTMPDIR}/openshift-recent/bin/activate"
|
||||
$PYTHON -m pip install 'openshift==0.7.2'
|
||||
$PYTHON -m pip install openshift==0.8.1
|
||||
ansible-playbook -v playbooks/full_test.yml "$@"
|
||||
|
|
|
@ -44,7 +44,7 @@ class OpenShiftCloudProvider(CloudProvider):
|
|||
super(OpenShiftCloudProvider, self).__init__(args, config_extension='.kubeconfig')
|
||||
|
||||
# The image must be pinned to a specific version to guarantee CI passes with the version used.
|
||||
self.image = 'openshift/origin:v3.7.1'
|
||||
self.image = 'openshift/origin:v3.9.0'
|
||||
self.container_name = ''
|
||||
|
||||
def filter(self, targets, exclude):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue