Move integration test suite from molecule to ansible-test (#392)

Move integration test suite from molecule to ansible-test

SUMMARY

molecule has been replaced with ansible-test
some test cases have been updated

k8s_apply : remove duplicated tasks increasing the running time of the test
helm: use different namespaces for different test cases in order to wait for the namespace deletion before moving to the next test.
all: remove wait: yes at the end of each test when deleting namespace, the role used to create namespace will ensure that it is deleted before if existing.


ISSUE TYPE


Feature Pull Request

COMPONENT NAME

integration testing

Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Gonéri Le Bouder <goneri@lebouder.net>
Reviewed-by: None <None>
This commit is contained in:
abikouo
2022-03-11 09:03:00 +01:00
committed by GitHub
parent db78d3a505
commit fd61f8b15d
199 changed files with 1172 additions and 1835 deletions

6
.gitignore vendored
View File

@@ -15,4 +15,8 @@ tests/integration/cloud-config-*
.cache .cache
# Helm charts # Helm charts
molecule/default/*-chart-*.tgz tests/integration/*-chart-*.tgz
# ansible-test generated file
tests/integration/inventory
tests/integration/*-*.yml

View File

@@ -22,10 +22,7 @@ test-sanity:
ansible-test sanity --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS) ansible-test sanity --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
test-integration: test-integration:
ansible-test integration --docker -v --color --retry-on-error --python $(PYTHON_VERSION) --continue-on-error --diff --coverage $(?TEST_ARGS) ansible-test integration --diff --no-temp-workdir --color --skip-tags False --retry-on-error --continue-on-error --python $(PYTHON_VERSION) -v --coverage $(?TEST_ARGS)
test-molecule:
molecule test
test-unit: test-unit:
ansible-test units --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS) ansible-test units --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)

View File

@@ -1,308 +0,0 @@
---
- name: Converge
hosts: localhost
connection: local
collections:
- kubernetes.core
vars_files:
- vars/main.yml
tasks:
- name: Verify cluster is working.
k8s_info:
namespace: kube-system
kind: Pod
register: pod_list
- name: Verify cluster has more than 5 pods running.
assert:
that: (pod_list.resources | count) > 5
- name: Include access_review.yml
include_tasks:
file: tasks/access_review.yml
apply:
tags: [ access_review, k8s ]
tags:
- always
- name: Include append_hash.yml
include_tasks:
file: tasks/append_hash.yml
apply:
tags: [ append_hash, k8s ]
tags:
- always
- name: Include apply.yml
include_tasks:
file: tasks/apply.yml
apply:
tags: [ apply, k8s ]
tags:
- always
- name: Include cluster_info.yml
include_tasks:
file: tasks/cluster_info.yml
apply:
tags: [ cluster_info, k8s ]
tags:
- always
- name: Include crd.yml
include_tasks:
file: tasks/crd.yml
apply:
tags: [ crd, k8s ]
tags:
- always
- name: Include delete.yml
include_tasks:
file: tasks/delete.yml
apply:
tags: [ delete, k8s ]
tags:
- always
- name: Include exec.yml
include_tasks:
file: tasks/exec.yml
apply:
tags: [ exec, k8s ]
tags:
- always
- name: Include full.yml
include_tasks:
file: tasks/full.yml
apply:
tags: [ full, k8s ]
tags:
- always
- name: Include gc.yml
include_tasks:
file: tasks/gc.yml
apply:
tags: [ gc, k8s ]
tags:
- always
- name: Include info.yml
include_tasks:
file: tasks/info.yml
apply:
tags: [ info, k8s ]
tags:
- always
- name: Include json_patch.yml
include_tasks:
file: tasks/json_patch.yml
apply:
tags: [ json_patch, k8s ]
tags:
- always
- name: Include lists.yml
include_tasks:
file: tasks/lists.yml
apply:
tags: [ lists, k8s ]
tags:
- always
- name: Include log.yml
include_tasks:
file: tasks/log.yml
apply:
tags: [ log, k8s ]
tags:
- always
- name: Include rollback.yml
include_tasks:
file: tasks/rollback.yml
apply:
tags: [ rollback, k8s ]
tags:
- always
- name: Include scale.yml
include_tasks:
file: tasks/scale.yml
apply:
tags: [ scale, k8s ]
tags:
- always
- name: Include template.yml
include_tasks:
file: tasks/template.yml
apply:
tags: [ template, k8s ]
tags:
- always
- name: Include validate.yml
include_tasks:
file: tasks/validate.yml
apply:
tags: [ validate, k8s ]
tags:
- always
- name: Include waiter.yml
include_tasks:
file: tasks/waiter.yml
apply:
tags: [ waiter, k8s ]
tags:
- always
- name: Include merge_type.yml
include_tasks:
file: tasks/merge_type.yml
apply:
tags: [ merge_type, k8s ]
tags:
- always
- name: Include patched.yml
include_tasks:
file: tasks/patched.yml
apply:
tags: [ patched, k8s ]
tags:
- always
- name: Include lookup_k8s.yml
include_tasks:
file: tasks/lookup_k8s.yml
apply:
tags: [ lookup_k8s, k8s ]
tags:
- always
- name: Include label_selectors.yml
include_tasks:
file: tasks/label_selectors.yml
apply:
tags: [ label_selectors, k8s ]
tags:
- always
- name: Include diff.yml
include_tasks:
file: tasks/diff.yml
apply:
tags: [ diff, k8s ]
tags:
- always
- name: Include lookup_kustomize.yml
include_tasks:
file: tasks/lookup_kustomize.yml
apply:
tags: [ lookup_kustomize, k8s ]
tags:
- always
- name: Include generate_name.yml
include_tasks:
file: tasks/generate_name.yml
apply:
tags: [ generate_name, k8s ]
tags:
- always
- name: Include user_impersonation.yml
include_tasks:
file: tasks/user_impersonation.yml
apply:
tags: [ user_impersonation, k8s ]
tags:
- always
roles:
- role: helm
tags:
- helm
- role: k8scopy
tags:
- copy
- k8s
post_tasks:
- name: Ensure namespace exists
k8s:
api_version: v1
kind: Namespace
name: inventory
- name: Add a deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory
namespace: inventory
spec:
replicas: 1
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
wait_timeout: 120
vars:
k8s_pod_name: inventory
k8s_pod_image: python
k8s_pod_command:
- python
- '-m'
- http.server
k8s_pod_env:
- name: TEST
value: test
- meta: refresh_inventory
- name: Verify inventory and connection plugins
hosts: namespace_inventory_pods
gather_facts: no
vars:
file_content: |
Hello world
tasks:
- name: End play if host not running (TODO should we not add these to the inventory?)
meta: end_host
when: pod_phase != "Running"
- debug: var=hostvars
- setup:
- debug: var=ansible_facts
- name: Assert the TEST environment variable was retrieved
assert:
that: ansible_facts.env.TEST == 'test'
- name: Copy a file into the host
copy:
content: '{{ file_content }}'
dest: /tmp/test_file
- name: Retrieve the file from the host
slurp:
src: /tmp/test_file
register: slurped_file
- name: Assert the file content matches expectations
assert:
that: (slurped_file.content|b64decode) == file_content
- name: Delete inventory namespace
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Remove inventory namespace
k8s:
api_version: v1
kind: Namespace
name: inventory
state: absent

View File

@@ -1,35 +0,0 @@
---
driver:
name: delegated
options:
managed: false
login_cmd_template: 'docker exec -ti {instance} bash'
ansible_connection_options:
ansible_connection: docker
platforms:
- name: instance-kind
provisioner:
name: ansible
log: true
config_options:
inventory:
enable_plugins: kubernetes.core.k8s,yaml
lint: {}
inventory:
hosts:
plugin: kubernetes.core.k8s
host_vars:
localhost:
ansible_python_interpreter: '{{ ansible_playbook_python }}'
env:
ANSIBLE_FORCE_COLOR: 'true'
options:
vvv: True
scenario:
name: default
test_sequence:
- dependency
- syntax
- prepare
- converge
- verify

View File

@@ -1,16 +0,0 @@
---
- name: Prepare
hosts: localhost
connection: local
collections:
- kubernetes.core
tasks:
- name: Include drain.yml
include_tasks:
file: tasks/drain.yml
- name: Include taint.yml
include_tasks:
file: tasks/taint.yml

View File

@@ -1,217 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Aubin Bikouo <@abikouo>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
module: kubectl_file_compare
short_description: Compare file and directory using kubectl
author:
- Aubin Bikouo (@abikouo)
description:
- This module is used to validate k8s_cp module.
- Compare the local file/directory with the remote pod version
notes:
- This module authenticates on kubernetes cluster using default kubeconfig only.
options:
namespace:
description:
- The pod namespace name
type: str
required: yes
pod:
description:
- The pod name
type: str
required: yes
container:
description:
- The container to retrieve files from.
type: str
remote_path:
description:
- Path of the file or directory on Pod.
type: path
required: yes
local_path:
description:
- Path of the local file or directory.
type: path
content:
description:
- local content to compare with remote file from pod.
- mutually exclusive with option I(local_path).
type: path
required: yes
args:
description:
- The file is considered to be an executable.
- The tool will be run locally and on pod and compare result from output and stderr.
type: list
kubectl_path:
description:
- Path to the kubectl executable, if not specified it will be download.
type: path
'''
EXAMPLES = r'''
- name: compare local /tmp/foo with /tmp/bar in a remote pod
kubectl_file_compare:
namespace: some-namespace
pod: some-pod
remote_path: /tmp/bar
local_path: /tmp/foo
kubectl_path: /tmp/test/kubectl
- name: Compare executable running help command
kubectl_file_compare:
namespace: some-namespace
pod: some-pod
remote_path: /tmp/test/kubectl
local_path: kubectl
kubectl_path: /tmp/test/kubectl
args:
- "--help"
'''
RETURN = r'''
'''
import os
import filecmp
from tempfile import NamedTemporaryFile, TemporaryDirectory
from ansible.module_utils.basic import AnsibleModule
def kubectl_get_content(module, dest_dir):
kubectl_path = module.params.get('kubectl_path')
if kubectl_path is None:
kubectl_path = module.get_bin_path('kubectl', required=True)
namespace = module.params.get('namespace')
pod = module.params.get('pod')
file = module.params.get('remote_path')
cmd = [
kubectl_path,
'cp',
"{0}/{1}:{2}".format(namespace, pod, file)
]
container = module.params.get('container')
if container:
cmd += ['-c', container]
local_file = os.path.join(dest_dir, os.path.basename(module.params.get('remote_path')))
cmd.append(local_file)
rc, out, err = module.run_command(cmd)
return local_file, err, rc, out
def kubectl_run_from_pod(module):
kubectl_path = module.params.get('kubectl_path')
if kubectl_path is None:
kubectl_path = module.get_bin_path('kubectl', required=True)
cmd = [
kubectl_path,
'exec',
module.params.get('pod'),
'-n',
module.params.get('namespace')
]
container = module.params.get('container')
if container:
cmd += ['-c', container]
cmd += ['--', module.params.get('remote_path')]
cmd += module.params.get('args')
return module.run_command(cmd)
def compare_directories(dir1, dir2):
test = filecmp.dircmp(dir1, dir2)
if any([len(test.left_only) > 0, len(test.right_only) > 0, len(test.funny_files) > 0]):
return False
(t, mismatch, errors) = filecmp.cmpfiles(dir1, dir2, test.common_files, shallow=False)
if len(mismatch) > 0 or len(errors) > 0:
return False
for common_dir in test.common_dirs:
new_dir1 = os.path.join(dir1, common_dir)
new_dir2 = os.path.join(dir2, common_dir)
if not compare_directories(new_dir1, new_dir2):
return False
return True
def execute_module(module):
args = module.params.get('args')
local_path = module.params.get('local_path')
namespace = module.params.get('namespace')
pod = module.params.get('pod')
file = module.params.get('remote_path')
content = module.params.get('content')
if args:
pod_rc, pod_out, pod_err = kubectl_run_from_pod(module)
rc, out, err = module.run_command([module.params.get('local_path')] + args)
if rc == pod_rc and out == pod_out:
module.exit_json(msg="{0} and {1}/{2}:{3} are same.".format(
local_path, namespace, pod, file
), rc=rc, stderr=err, stdout=out)
result = dict(local=dict(rc=rc, out=out, err=err), remote=dict(rc=pod_rc, out=pod_out, err=pod_err))
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.", **result)
else:
with TemporaryDirectory() as tmpdirname:
file_from_pod, err, rc, out = kubectl_get_content(module=module, dest_dir=tmpdirname)
if not os.path.exists(file_from_pod):
module.fail_json(msg="failed to copy content from pod", error=err, output=out)
if content is not None:
with NamedTemporaryFile(mode="w") as tmp_file:
tmp_file.write(content)
tmp_file.flush()
if filecmp.cmp(file_from_pod, tmp_file.name):
module.exit_json(msg=f"defined content and {namespace}/{pod}:{file} are same.")
module.fail_json(msg=f"defined content and {namespace}/{pod}:{file} are same.")
if os.path.isfile(local_path):
if filecmp.cmp(file_from_pod, local_path):
module.exit_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
if os.path.isdir(local_path):
if compare_directories(file_from_pod, local_path):
module.exit_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
def main():
argument_spec = {}
argument_spec['namespace'] = {'type': 'str', 'required': True}
argument_spec['pod'] = {'type': 'str', 'required': True}
argument_spec['container'] = {}
argument_spec['remote_path'] = {'type': 'path', 'required': True}
argument_spec['local_path'] = {'type': 'path'}
argument_spec['content'] = {'type': 'str'}
argument_spec['kubectl_path'] = {'type': 'path'}
argument_spec['args'] = {'type': 'list'}
module = AnsibleModule(argument_spec=argument_spec,
mutually_exclusive=[('local_path', 'content')],
required_one_of=[['local_path', 'content']])
execute_module(module)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,8 @@
# slow - 11min
slow
time=313
helm_info
helm_plugin
helm_plugin_info
helm_repository
helm_template

View File

@@ -1,10 +1,6 @@
--- ---
helm_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz" helm_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm" helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
helm_namespace: helm
tiller_namespace: tiller
tiller_cluster_role: cluster-admin
chart_test: "ingress-nginx" chart_test: "ingress-nginx"
chart_test_local_path: "nginx-ingress" chart_test_local_path: "nginx-ingress"
@@ -17,3 +13,15 @@ chart_test_git_repo: "http://github.com/helm/charts.git"
chart_test_values: chart_test_values:
revisionHistoryLimit: 0 revisionHistoryLimit: 0
myValue: "changed" myValue: "changed"
test_namespace:
- "helm-diff"
- "helm-envvars"
- "helm-uninstall"
- "helm-not-installed"
- "helm-crd"
- "helm-url"
- "helm-repository"
- "helm-local-path-001"
- "helm-local-path-002"
- "helm-local-path-003"

View File

@@ -1,9 +1,9 @@
apiVersion: apiextensions.k8s.io/v1 apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition kind: CustomResourceDefinition
metadata: metadata:
name: foos.example.com name: foos.ansible.com
spec: spec:
group: example.com group: ansible.com
versions: versions:
- name: v1 - name: v1
served: true served: true

View File

@@ -4,10 +4,11 @@
# Copyright: (c) 2021, Ansible Project # Copyright: (c) 2021, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = r''' DOCUMENTATION = r"""
--- ---
module: helm_test_version module: helm_test_version
short_description: check helm executable version short_description: check helm executable version
@@ -28,16 +29,16 @@ options:
- version to test against helm binary. - version to test against helm binary.
type: str type: str
default: 3.7.0 default: 3.7.0
''' """
EXAMPLES = r''' EXAMPLES = r"""
- name: validate helm binary version is lower than 3.5.0 - name: validate helm binary version is lower than 3.5.0
helm_test_version: helm_test_version:
binary_path: path/to/helm binary_path: path/to/helm
version: "3.5.0" version: "3.5.0"
''' """
RETURN = r''' RETURN = r"""
message: message:
type: str type: str
description: Text message describing the test result. description: Text message describing the test result.
@@ -48,10 +49,12 @@ result:
description: Test result. description: Test result.
returned: always returned: always
sample: 1 sample: 1
''' """
import re import re
from ansible_collections.kubernetes.core.plugins.module_utils.version import LooseVersion from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@@ -59,18 +62,17 @@ from ansible.module_utils.basic import AnsibleModule
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
binary_path=dict(type='path'), binary_path=dict(type="path"), version=dict(type="str", default="3.7.0"),
version=dict(type='str', default='3.7.0'),
), ),
) )
bin_path = module.params.get('binary_path') bin_path = module.params.get("binary_path")
version = module.params.get('version') version = module.params.get("version")
if bin_path is not None: if bin_path is not None:
helm_cmd_common = bin_path helm_cmd_common = bin_path
else: else:
helm_cmd_common = 'helm' helm_cmd_common = "helm"
helm_cmd_common = module.get_bin_path(helm_cmd_common, required=True) helm_cmd_common = module.get_bin_path(helm_cmd_common, required=True)
rc, out, err = module.run_command([helm_cmd_common, "version"]) rc, out, err = module.run_command([helm_cmd_common, "version"])
@@ -89,5 +91,5 @@ def main():
module.exit_json(changed=False, result=False, message=message) module.exit_json(changed=False, result=False, message=message)
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@@ -1,3 +1,5 @@
--- ---
collections: collections:
- kubernetes.core - kubernetes.core
dependencies:
- remove_namespace

View File

@@ -6,7 +6,7 @@
- name: Create namespace - name: Create namespace
k8s: k8s:
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ test_namespace[4] }}"
- name: Copy test chart - name: Copy test chart
copy: copy:
@@ -17,7 +17,7 @@
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}" chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[4] }}"
name: test-crds name: test-crds
skip_crds: true skip_crds: true
register: install register: install
@@ -30,10 +30,10 @@
- name: Fail to create custom resource - name: Fail to create custom resource
k8s: k8s:
definition: definition:
apiVersion: example.com/v1 apiVersion: ansible.com/v1
kind: Foo kind: Foo
metadata: metadata:
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[4] }}"
name: test-foo name: test-foo
foobar: footest foobar: footest
ignore_errors: true ignore_errors: true
@@ -42,13 +42,13 @@
- assert: - assert:
that: that:
- result is failed - result is failed
- "result.msg.startswith('Failed to find exact match for example.com/v1.Foo')" - "result.msg.startswith('Failed to find exact match for ansible.com/v1.Foo')"
# Helm won't install CRDs into an existing release, so we need to delete this, first # Helm won't install CRDs into an existing release, so we need to delete this, first
- name: Uninstall chart - name: Uninstall chart
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[4] }}"
name: test-crds name: test-crds
state: absent state: absent
@@ -56,16 +56,16 @@
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}" chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[4] }}"
name: test-crds name: test-crds
- name: Create custom resource - name: Create custom resource
k8s: k8s:
definition: definition:
apiVersion: example.com/v1 apiVersion: ansible.com/v1
kind: Foo kind: Foo
metadata: metadata:
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[4] }}"
name: test-foo name: test-foo
foobar: footest foobar: footest
register: result register: result
@@ -85,16 +85,14 @@
- name: Remove namespace - name: Remove namespace
k8s: k8s:
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ test_namespace[4] }}"
state: absent state: absent
wait: true
wait_timeout: 180
ignore_errors: true ignore_errors: true
# CRDs aren't deleted with a namespace, so we need to manually delete it # CRDs aren't deleted with a namespace, so we need to manually delete it
- name: Remove CRD - name: Remove CRD
k8s: k8s:
kind: CustomResourceDefinition kind: CustomResourceDefinition
name: foos.example.com name: foos.ansible.com
state: absent state: absent
ignore_errors: true ignore_errors: true

View File

@@ -4,7 +4,7 @@
binary_path: "{{ helm_binary}}_fake" binary_path: "{{ helm_binary}}_fake"
name: test name: test
chart_ref: "{{ chart_test }}" chart_ref: "{{ chart_test }}"
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[3] }}"
ignore_errors: yes ignore_errors: yes
register: helm_missing_binary register: helm_missing_binary

View File

@@ -8,6 +8,7 @@
- set_fact: - set_fact:
chart_source: "https://github.com/kubernetes/kube-state-metrics/releases/download/kube-state-metrics-helm-chart-2.13.3/kube-state-metrics-2.13.3.tgz" chart_source: "https://github.com/kubernetes/kube-state-metrics/releases/download/kube-state-metrics-helm-chart-2.13.3/kube-state-metrics-2.13.3.tgz"
chart_name: "test-wait-uninstall" chart_name: "test-wait-uninstall"
helm_namespace: "{{ test_namespace[2] }}"
- name: Install chart - name: Install chart
helm: helm:
@@ -75,7 +76,5 @@
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ helm_namespace }}"
state: absent state: absent
wait: true
wait_timeout: 180
ignore_errors: true ignore_errors: true
when: test_version.result when: test_version.result

View File

@@ -3,7 +3,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: absent state: absent
name: does-not-exist name: does-not-exist
namespace: "{{ helm_namespace }}" namespace: "{{ test_namespace[1] }}"
environment: environment:
K8S_AUTH_HOST: somewhere K8S_AUTH_HOST: somewhere
register: _helm_result register: _helm_result

View File

@@ -1,5 +1,8 @@
--- ---
- name: Chart tests - name: Chart tests
vars:
chart_release_name: "test-{{ chart_name | default(source) }}"
chart_release_replaced_name: "test-{{ chart_name | default(source) }}-001"
block: block:
- name: Create temp directory - name: Create temp directory
tempfile: tempfile:
@@ -13,7 +16,7 @@
- name: Check helm_info empty - name: Check helm_info empty
helm_info: helm_info:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: empty_info register: empty_info
@@ -25,7 +28,7 @@
- name: "Install fail {{ chart_test }} from {{ source }}" - name: "Install fail {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -41,7 +44,7 @@
- name: "Install {{ chart_test }} from {{ source }} in check mode" - name: "Install {{ chart_test }} from {{ source }} in check mode"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -59,7 +62,7 @@
- name: "Install {{ chart_test }} from {{ source }}" - name: "Install {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -76,14 +79,14 @@
- name: Check helm_info content - name: Check helm_info content
helm_info: helm_info:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: content_info register: content_info
- name: Check helm_info content using release_state - name: Check helm_info content using release_state
helm_info: helm_info:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
release_state: release_state:
- deployed - deployed
@@ -99,7 +102,7 @@
- name: Check idempotency - name: Check idempotency
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -115,7 +118,7 @@
- name: "Add vars to {{ chart_test }} from {{ source }}" - name: "Add vars to {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -133,7 +136,7 @@
- name: Check idempotency after adding vars - name: Check idempotency after adding vars
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -151,7 +154,7 @@
- name: "Remove Vars to {{ chart_test }} from {{ source }}" - name: "Remove Vars to {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -168,7 +171,7 @@
- name: Check idempotency after removing vars - name: Check idempotency after removing vars
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -185,7 +188,7 @@
- name: "Upgrade {{ chart_test }} from {{ source }}" - name: "Upgrade {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}" chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_source_version_upgrade | default(omit) }}" chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -201,7 +204,7 @@
- name: Check idempotency after upgrade - name: Check idempotency after upgrade
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}" chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_source_version_upgrade | default(omit) }}" chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -218,7 +221,7 @@
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: absent state: absent
name: test name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -231,7 +234,7 @@
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: absent state: absent
name: test name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -244,7 +247,7 @@
- name: Install chart for replace option - name: Install chart for replace option
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test-0001 name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -255,11 +258,11 @@
that: that:
- install is changed - install is changed
- name: Remove {{ chart_test }} with --purge - name: "Remove {{ chart_release_replaced_name }} with --purge"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: absent state: absent
name: test-0001 name: "{{ chart_release_replaced_name }}"
purge: False purge: False
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -269,10 +272,10 @@
that: that:
- install is changed - install is changed
- name: Install chart again with same name test-0001 - name: "Install chart again with same name {{ chart_release_replaced_name }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test-0001 name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -288,7 +291,7 @@
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: absent state: absent
name: test-0001 name: "{{ chart_release_replaced_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -300,7 +303,7 @@
- name: "Install {{ chart_test }} from {{ source }} with values_files" - name: "Install {{ chart_test }} from {{ source }} with values_files"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -319,7 +322,7 @@
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)" - name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -361,7 +364,7 @@
- name: Release using non-existent context - name: Release using non-existent context
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: test name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
@@ -389,5 +392,3 @@
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ helm_namespace }}"
state: absent state: absent
wait: true
wait_timeout: 180

View File

@@ -22,6 +22,8 @@
chart_source_upgrade: "/tmp/helm_test_repo_upgrade/stable/{{ chart_test_local_path }}/" chart_source_upgrade: "/tmp/helm_test_repo_upgrade/stable/{{ chart_test_local_path }}/"
chart_test_version: "{{ chart_test_version_local_path }}" chart_test_version: "{{ chart_test_version_local_path }}"
chart_test_version_upgrade: "{{ chart_test_version_upgrade_local_path }}" chart_test_version_upgrade: "{{ chart_test_version_upgrade_local_path }}"
chart_name: "local-path-001"
helm_namespace: "{{ test_namespace[7] }}"
- name: Test appVersion idempotence - name: Test appVersion idempotence
vars: vars:
@@ -66,6 +68,8 @@
source: local_path source: local_path
chart_source: "/tmp/helm_test_appversion/test-chart/{{ chart_test }}-{{ chart_test_app_version }}-{{ chart_test_version }}.tgz" chart_source: "/tmp/helm_test_appversion/test-chart/{{ chart_test }}-{{ chart_test_app_version }}-{{ chart_test_version }}.tgz"
chart_source_upgrade: "/tmp/helm_test_appversion/test-chart/{{ chart_test }}-{{ chart_test_upgrade_app_version }}-{{ chart_test_version_upgrade }}.tgz" chart_source_upgrade: "/tmp/helm_test_appversion/test-chart/{{ chart_test }}-{{ chart_test_upgrade_app_version }}-{{ chart_test_version_upgrade }}.tgz"
chart_name: "local-path-002"
helm_namespace: "{{ test_namespace[8] }}"
- name: Test appVersion handling when null - name: Test appVersion handling when null
vars: vars:
@@ -94,6 +98,8 @@
source: local_path source: local_path
chart_source: "/tmp/helm_test_appversion/test-null/{{ chart_test }}/" chart_source: "/tmp/helm_test_appversion/test-null/{{ chart_test }}/"
chart_source_upgrade: "{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz" chart_source_upgrade: "{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz"
chart_name: "local-path-003"
helm_namespace: "{{ test_namespace[9] }}"
- name: Remove clone repos - name: Remove clone repos
file: file:

View File

@@ -12,6 +12,7 @@
chart_source: "test_helm/{{ chart_test }}" chart_source: "test_helm/{{ chart_test }}"
chart_source_version: "{{ chart_test_version }}" chart_source_version: "{{ chart_test_version }}"
chart_source_version_upgrade: "{{ chart_test_version_upgrade }}" chart_source_version_upgrade: "{{ chart_test_version_upgrade }}"
helm_namespace: "{{ test_namespace[6] }}"
- name: Add chart repo - name: Add chart repo
helm_repository: helm_repository:

View File

@@ -5,3 +5,4 @@
source: url source: url
chart_source: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version }}/{{ chart_test }}-{{ chart_test_version }}.tgz" chart_source: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version }}/{{ chart_test }}-{{ chart_test_version }}.tgz"
chart_source_upgrade: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version_upgrade }}/{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz" chart_source_upgrade: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version_upgrade }}/{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz"
helm_namespace: "{{ test_namespace[5] }}"

View File

@@ -4,6 +4,9 @@
test_chart_ref: "/tmp/test-chart" test_chart_ref: "/tmp/test-chart"
block: block:
- set_fact:
helm_namespace: "{{ test_namespace[0] }}"
- name: Install helm diff - name: Install helm diff
helm_plugin: helm_plugin:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
@@ -254,6 +257,4 @@
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ helm_namespace }}"
state: absent state: absent
wait: yes
wait_timeout: 180
ignore_errors: yes ignore_errors: yes

View File

@@ -0,0 +1,3 @@
context/target
time=42
k8s

View File

@@ -0,0 +1,102 @@
---
- name: Converge
hosts: localhost
connection: local
collections:
- kubernetes.core
vars_files:
- vars/main.yml
tasks:
- name: Delete existing namespace
k8s:
api_version: v1
kind: Namespace
name: inventory
wait: yes
state: absent
- name: Ensure namespace exists
k8s:
api_version: v1
kind: Namespace
name: inventory
- name: Add a deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory
namespace: inventory
spec:
replicas: 1
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
wait_timeout: 400
vars:
k8s_pod_name: inventory
k8s_pod_image: python
k8s_pod_command:
- python
- '-m'
- http.server
k8s_pod_env:
- name: TEST
value: test
- meta: refresh_inventory
- name: Verify inventory and connection plugins
hosts: namespace_inventory_pods
gather_facts: no
vars:
file_content: |
Hello world
tasks:
- name: End play if host not running (TODO should we not add these to the inventory?)
meta: end_host
when: pod_phase != "Running"
- debug: var=hostvars
- setup:
- debug: var=ansible_facts
- name: Assert the TEST environment variable was retrieved
assert:
that: ansible_facts.env.TEST == 'test'
- name: Copy a file into the host
copy:
content: '{{ file_content }}'
dest: /tmp/test_file
- name: Retrieve the file from the host
slurp:
src: /tmp/test_file
register: slurped_file
- name: Assert the file content matches expectations
assert:
that: (slurped_file.content|b64decode) == file_content
- name: Delete inventory namespace
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Remove inventory namespace
k8s:
api_version: v1
kind: Namespace
name: inventory
state: absent

View File

@@ -0,0 +1,2 @@
---
plugin: kubernetes.core.k8s

View File

@@ -0,0 +1,38 @@
---
k8s_pod_metadata:
labels:
app: "{{ k8s_pod_name }}"
k8s_pod_spec:
serviceAccount: "{{ k8s_pod_service_account }}"
containers:
- image: "{{ k8s_pod_image }}"
imagePullPolicy: Always
name: "{{ k8s_pod_name }}"
command: "{{ k8s_pod_command }}"
readinessProbe:
initialDelaySeconds: 15
exec:
command:
- /bin/true
resources: "{{ k8s_pod_resources }}"
ports: "{{ k8s_pod_ports }}"
env: "{{ k8s_pod_env }}"
k8s_pod_service_account: default
k8s_pod_resources:
limits:
cpu: "100m"
memory: "100Mi"
k8s_pod_command: []
k8s_pod_ports: []
k8s_pod_env: []
k8s_pod_template:
metadata: "{{ k8s_pod_metadata }}"
spec: "{{ k8s_pod_spec }}"

View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -eux
export ANSIBLE_INVENTORY_ENABLED=kubernetes.core.k8s,yaml
export ANSIBLE_PYTHON_INTERPRETER=auto_silent
ansible-playbook playbooks/play.yml -i playbooks/test.inventory_k8s.yml "$@"

View File

@@ -0,0 +1,2 @@
time=7
k8s

View File

@@ -0,0 +1,2 @@
time=14
k8s

View File

@@ -0,0 +1,2 @@
---
test_namespace: "append-hash"

View File

@@ -0,0 +1,2 @@
dependencies:
- setup_namespace

View File

@@ -3,14 +3,14 @@
- name: Ensure that append_hash namespace exists - name: Ensure that append_hash namespace exists
k8s: k8s:
kind: Namespace kind: Namespace
name: append-hash name: "{{ test_namespace }}"
- name: Create k8s_resource variable - name: Create k8s_resource variable
set_fact: set_fact:
k8s_resource: k8s_resource:
metadata: metadata:
name: config-map-test name: config-map-test
namespace: append-hash namespace: "{{ test_namespace }}"
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
data: data:
@@ -46,7 +46,7 @@
definition: definition:
metadata: metadata:
name: config-map-test name: config-map-test
namespace: append-hash namespace: "{{ test_namespace }}"
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
data: data:
@@ -65,5 +65,5 @@
- name: Ensure that namespace is removed - name: Ensure that namespace is removed
k8s: k8s:
kind: Namespace kind: Namespace
name: append-hash name: "{{ test_namespace }}"
state: absent state: absent

View File

@@ -0,0 +1,5 @@
# duration 9min
slow
k8s_service
k8s
time=192

View File

@@ -37,4 +37,6 @@ k8s_pod_template:
metadata: "{{ k8s_pod_metadata }}" metadata: "{{ k8s_pod_metadata }}"
spec: "{{ k8s_pod_spec }}" spec: "{{ k8s_pod_spec }}"
kubernetes_role_path: ../../tests/integration/targets/kubernetes test_namespace: "apply"
k8s_wait_timeout: 240

View File

@@ -0,0 +1,2 @@
dependencies:
- setup_namespace

View File

@@ -1,20 +1,17 @@
--- ---
- block: - block:
- set_fact:
apply_namespace: apply
- name: Ensure namespace exists - name: Ensure namespace exists
k8s: k8s:
definition: definition:
apiVersion: v1 apiVersion: v1
kind: Namespace kind: Namespace
metadata: metadata:
name: "{{ apply_namespace }}" name: "{{ test_namespace }}"
- name: Add a configmap - name: Add a configmap
k8s: k8s:
name: "apply-configmap" name: "apply-configmap"
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
kind: ConfigMap kind: ConfigMap
apiVersion: v1 apiVersion: v1
@@ -38,7 +35,7 @@
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: "apply-configmap" name: "apply-configmap"
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
data: data:
one: "1" one: "1"
two: "2" two: "2"
@@ -58,7 +55,7 @@
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: "apply-configmap" name: "apply-configmap"
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
data: data:
one: "1" one: "1"
two: "2" two: "2"
@@ -75,7 +72,7 @@
- name: Add same configmap again but using name and namespace args - name: Add same configmap again but using name and namespace args
k8s: k8s:
name: "apply-configmap" name: "apply-configmap"
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
kind: ConfigMap kind: ConfigMap
apiVersion: v1 apiVersion: v1
@@ -98,7 +95,7 @@
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: "apply-configmap" name: "apply-configmap"
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
data: data:
one: "1" one: "1"
three: "3" three: "3"
@@ -120,7 +117,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -138,7 +135,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -161,7 +158,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -185,7 +182,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -210,7 +207,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -239,7 +236,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -265,7 +262,7 @@
kind: Service kind: Service
metadata: metadata:
name: apply-svc name: apply-svc
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
app: whatever app: whatever
@@ -290,7 +287,7 @@
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
- name: Add a deployment - name: Add a deployment
k8s: k8s:
@@ -299,7 +296,7 @@
kind: Deployment kind: Deployment
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@@ -307,6 +304,7 @@
app: "{{ k8s_pod_name }}" app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}" template: "{{ k8s_pod_template }}"
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
apply: yes apply: yes
vars: vars:
k8s_pod_name: apply-deploy k8s_pod_name: apply-deploy
@@ -331,7 +329,7 @@
kind: Deployment kind: Deployment
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@@ -339,6 +337,7 @@
app: "{{ k8s_pod_name }}" app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}" template: "{{ k8s_pod_template }}"
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
apply: yes apply: yes
check_mode: yes check_mode: yes
vars: vars:
@@ -370,7 +369,7 @@
kind: Deployment kind: Deployment
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@@ -378,6 +377,7 @@
app: "{{ k8s_pod_name }}" app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}" template: "{{ k8s_pod_template }}"
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
apply: yes apply: yes
vars: vars:
k8s_pod_name: apply-deploy k8s_pod_name: apply-deploy
@@ -409,7 +409,7 @@
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
- name: Apply deployment after service account removed - name: Apply deployment after service account removed
k8s: k8s:
@@ -418,7 +418,7 @@
kind: Deployment kind: Deployment
metadata: metadata:
name: apply-deploy name: apply-deploy
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@@ -426,6 +426,7 @@
app: "{{ k8s_pod_name }}" app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}" template: "{{ k8s_pod_template }}"
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
apply: yes apply: yes
vars: vars:
k8s_pod_name: apply-deploy k8s_pod_name: apply-deploy
@@ -449,318 +450,6 @@
that: that:
- deploy_after_serviceaccount_removal is failed - deploy_after_serviceaccount_removal is failed
- name: Insert new service port
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: mesh
port: 8080
targetPort: 8080
- name: http
port: 8081
targetPort: 8081
apply: yes
register: k8s_service_4
- name: Check ports are correct
assert:
that:
- k8s_service_4 is changed
- k8s_service_4.result.spec.ports | length == 2
- k8s_service_4.result.spec.ports[0].port == 8080
- k8s_service_4.result.spec.ports[1].port == 8081
- name: Remove new service port (check mode)
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: http
port: 8081
targetPort: 8081
apply: yes
check_mode: yes
register: k8s_service_check
- name: Check ports are correct
assert:
that:
- k8s_service_check is changed
- k8s_service_check.result.spec.ports | length == 1
- k8s_service_check.result.spec.ports[0].port == 8081
- name: Remove new service port
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: http
port: 8081
targetPort: 8081
apply: yes
register: k8s_service_5
- name: Check ports are correct
assert:
that:
- k8s_service_5 is changed
- k8s_service_5.result.spec.ports | length == 1
- k8s_service_5.result.spec.ports[0].port == 8081
- name: Add a serviceaccount
k8s:
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
- name: Add a deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
spec:
replicas: 1
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
apply: yes
vars:
k8s_pod_name: apply-deploy
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
k8s_pod_service_account: apply-deploy
k8s_pod_ports:
- containerPort: 8080
name: http
protocol: TCP
- name: Remove the serviceaccount
k8s:
state: absent
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
- name: Update the earlier deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
spec:
replicas: 2
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
apply: yes
vars:
k8s_pod_name: apply-deploy
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple
k8s_pod_service_account: apply-deploy
k8s_pod_ports:
- containerPort: 8080
name: http
protocol: TCP
register: deploy_after_serviceaccount_removal
ignore_errors: yes
- name: Ensure that updating deployment after service account removal failed
assert:
that:
- deploy_after_serviceaccount_removal is failed
- name: Insert new service port
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: mesh
port: 8080
targetPort: 8080
- name: http
port: 8081
targetPort: 8081
apply: yes
register: k8s_service_4
- name: Check ports are correct
assert:
that:
- k8s_service_4 is changed
- k8s_service_4.result.spec.ports | length == 2
- k8s_service_4.result.spec.ports[0].port == 8080
- k8s_service_4.result.spec.ports[1].port == 8081
- name: Remove new service port (check mode)
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: http
port: 8081
targetPort: 8081
apply: yes
check_mode: yes
register: k8s_service_check
- name: Check ports are correct
assert:
that:
- k8s_service_check is changed
- k8s_service_check.result.spec.ports | length == 1
- k8s_service_check.result.spec.ports[0].port == 8081
- name: Remove new service port
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: apply-svc
namespace: "{{ apply_namespace }}"
spec:
selector:
app: whatever
ports:
- name: http
port: 8081
targetPort: 8081
apply: yes
register: k8s_service_5
- name: Check ports are correct
assert:
that:
- k8s_service_5 is changed
- k8s_service_5.result.spec.ports | length == 1
- k8s_service_5.result.spec.ports[0].port == 8081
- name: Add a serviceaccount
k8s:
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
- name: Add a deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
spec:
replicas: 1
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
apply: yes
vars:
k8s_pod_name: apply-deploy
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
k8s_pod_service_account: apply-deploy
k8s_pod_ports:
- containerPort: 8080
name: http
protocol: TCP
- name: Remove the serviceaccount
k8s:
state: absent
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
- name: Update the earlier deployment
k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: apply-deploy
namespace: "{{ apply_namespace }}"
spec:
replicas: 2
selector:
matchLabels:
app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}"
wait: yes
apply: yes
vars:
k8s_pod_name: apply-deploy
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple
k8s_pod_service_account: apply-deploy
k8s_pod_ports:
- containerPort: 8080
name: http
protocol: TCP
register: deploy_after_serviceaccount_removal
ignore_errors: yes
- name: Ensure that updating deployment after service account removal failed
assert:
that:
- deploy_after_serviceaccount_removal is failed
- name: Add a secret - name: Add a secret
k8s: k8s:
definition: definition:
@@ -768,7 +457,7 @@
kind: Secret kind: Secret
metadata: metadata:
name: apply-secret name: apply-secret
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
type: Opaque type: Opaque
stringData: stringData:
foo: bar foo: bar
@@ -787,7 +476,7 @@
kind: Secret kind: Secret
metadata: metadata:
name: apply-secret name: apply-secret
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
type: Opaque type: Opaque
stringData: stringData:
foo: bar foo: bar
@@ -805,7 +494,7 @@
kind: Secret kind: Secret
metadata: metadata:
name: apply-secret name: apply-secret
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
type: Opaque type: Opaque
stringData: stringData:
foo: bar foo: bar
@@ -824,7 +513,7 @@
kind: Secret kind: Secret
metadata: metadata:
name: apply-secret name: apply-secret
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
type: Opaque type: Opaque
data: data:
foo: YmFy foo: YmFy
@@ -838,7 +527,7 @@
- name: Create network policy (egress array with empty dict) - name: Create network policy (egress array with empty dict)
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
apply: true apply: true
definition: definition:
kind: NetworkPolicy kind: NetworkPolicy
@@ -865,7 +554,7 @@
- name: Apply network policy - name: Apply network policy
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
kind: NetworkPolicy kind: NetworkPolicy
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
@@ -899,7 +588,7 @@
# Server Side Apply # Server Side Apply
- name: Create Configmap using server side apply - field_manager not specified - name: Create Configmap using server side apply - field_manager not specified
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -921,7 +610,7 @@
- name: Create Configmap using server side apply - name: Create Configmap using server side apply
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -943,7 +632,7 @@
- name: Apply ConfigMap using same parameters - name: Apply ConfigMap using same parameters
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -963,7 +652,7 @@
- name: Apply ConfigMap adding new manager - name: Apply ConfigMap adding new manager
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -984,7 +673,7 @@
- name: Apply changes to Configmap using new field_manager - name: Apply changes to Configmap using new field_manager
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -1006,7 +695,7 @@
- name: Apply changes to Configmap using new field_manager and force_conflicts - name: Apply changes to Configmap using new field_manager and force_conflicts
k8s: k8s:
namespace: "{{ apply_namespace }}" namespace: "{{ test_namespace }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -1028,10 +717,9 @@
- result.result.metadata.managedFields[0].manager == 'manager-02' - result.result.metadata.managedFields[0].manager == 'manager-02'
- result.result.data.key == 'value-1' - result.result.data.key == 'value-1'
always: always:
- name: Remove namespace - name: Remove namespace
k8s: k8s:
kind: Namespace kind: Namespace
name: "{{ apply_namespace }}" name: "{{ test_namespace }}"
state: absent state: absent

View File

@@ -0,0 +1,2 @@
k8s_cluster_info
time=9

View File

@@ -0,0 +1,4 @@
k8s_exec
k8s_cp
k8s
time=101

View File

@@ -1,6 +1,6 @@
--- ---
# defaults file for k8copy # defaults file for k8copy
copy_namespace: copy test_namespace: copy
pod_with_one_container: pod_with_one_container:
name: pod-copy-0 name: pod-copy-0

View File

@@ -8,9 +8,9 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = r''' DOCUMENTATION = r"""
module: k8s_diff module: k8s_create_file
short_description: Create large file with a defined size. short_description: Create large file with a defined size.
@@ -36,18 +36,18 @@ options:
- If this flag is set to yes, the generated file content binary data. - If this flag is set to yes, the generated file content binary data.
type: bool type: bool
default: False default: False
''' """
EXAMPLES = r''' EXAMPLES = r"""
- name: create 150MB file - name: create 150MB file
k8s_diff: k8s_diff:
path: large_file.txt path: large_file.txt
size: 150 size: 150
''' """
RETURN = r''' RETURN = r"""
''' """
import os import os
@@ -57,17 +57,19 @@ from ansible.module_utils._text import to_native
def execute_module(module): def execute_module(module):
try: try:
size = module.params.get('size') * 1024 * 1024 size = module.params.get("size") * 1024 * 1024
path = module.params.get('path') path = module.params.get("path")
write_mode = "w" write_mode = "w"
if module.params.get('binary'): if module.params.get("binary"):
content = os.urandom(size) content = os.urandom(size)
write_mode = "wb" write_mode = "wb"
else: else:
content = "" content = ""
count = 0 count = 0
while len(content) < size: while len(content) < size:
content += "This file has been generated using ansible: {0}\n".format(count) content += "This file has been generated using ansible: {0}\n".format(
count
)
count += 1 count += 1
with open(path, write_mode) as f: with open(path, write_mode) as f:
@@ -79,13 +81,13 @@ def execute_module(module):
def main(): def main():
argument_spec = {} argument_spec = {}
argument_spec['size'] = {'type': 'int', 'default': 400} argument_spec["size"] = {"type": "int", "default": 400}
argument_spec['path'] = {'type': 'path', 'required': True} argument_spec["path"] = {"type": "path", "required": True}
argument_spec['binary'] = {'type': 'bool', 'default': False} argument_spec["binary"] = {"type": "bool", "default": False}
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleModule(argument_spec=argument_spec)
execute_module(module) execute_module(module)
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@@ -0,0 +1,247 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Aubin Bikouo <@abikouo>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r"""
module: kubectl_file_compare
short_description: Compare file and directory using kubectl
author:
- Aubin Bikouo (@abikouo)
description:
- This module is used to validate k8s_cp module.
- Compare the local file/directory with the remote pod version
notes:
- This module authenticates on kubernetes cluster using default kubeconfig only.
options:
namespace:
description:
- The pod namespace name
type: str
required: yes
pod:
description:
- The pod name
type: str
required: yes
container:
description:
- The container to retrieve files from.
type: str
remote_path:
description:
- Path of the file or directory on Pod.
type: path
required: yes
local_path:
description:
- Path of the local file or directory.
type: path
content:
description:
- local content to compare with remote file from pod.
- mutually exclusive with option I(local_path).
type: path
required: yes
args:
description:
- The file is considered to be an executable.
- The tool will be run locally and on pod and compare result from output and stderr.
type: list
kubectl_path:
description:
- Path to the kubectl executable, if not specified it will be download.
type: path
"""
EXAMPLES = r"""
- name: compare local /tmp/foo with /tmp/bar in a remote pod
kubectl_file_compare:
namespace: some-namespace
pod: some-pod
remote_path: /tmp/bar
local_path: /tmp/foo
kubectl_path: /tmp/test/kubectl
- name: Compare executable running help command
kubectl_file_compare:
namespace: some-namespace
pod: some-pod
remote_path: /tmp/test/kubectl
local_path: kubectl
kubectl_path: /tmp/test/kubectl
args:
- "--help"
"""
RETURN = r"""
"""
import os
import filecmp
from tempfile import NamedTemporaryFile, TemporaryDirectory
from ansible.module_utils.basic import AnsibleModule
def kubectl_get_content(module, dest_dir):
kubectl_path = module.params.get("kubectl_path")
if kubectl_path is None:
kubectl_path = module.get_bin_path("kubectl", required=True)
namespace = module.params.get("namespace")
pod = module.params.get("pod")
file = module.params.get("remote_path")
cmd = [kubectl_path, "cp", "{0}/{1}:{2}".format(namespace, pod, file)]
container = module.params.get("container")
if container:
cmd += ["-c", container]
local_file = os.path.join(
dest_dir, os.path.basename(module.params.get("remote_path"))
)
cmd.append(local_file)
rc, out, err = module.run_command(cmd)
return local_file, err, rc, out
def kubectl_run_from_pod(module):
kubectl_path = module.params.get("kubectl_path")
if kubectl_path is None:
kubectl_path = module.get_bin_path("kubectl", required=True)
cmd = [
kubectl_path,
"exec",
module.params.get("pod"),
"-n",
module.params.get("namespace"),
]
container = module.params.get("container")
if container:
cmd += ["-c", container]
cmd += ["--", module.params.get("remote_path")]
cmd += module.params.get("args")
return module.run_command(cmd)
def compare_directories(dir1, dir2):
test = filecmp.dircmp(dir1, dir2)
if any(
[len(test.left_only) > 0, len(test.right_only) > 0, len(test.funny_files) > 0]
):
return False
(t, mismatch, errors) = filecmp.cmpfiles(
dir1, dir2, test.common_files, shallow=False
)
if len(mismatch) > 0 or len(errors) > 0:
return False
for common_dir in test.common_dirs:
new_dir1 = os.path.join(dir1, common_dir)
new_dir2 = os.path.join(dir2, common_dir)
if not compare_directories(new_dir1, new_dir2):
return False
return True
def execute_module(module):
args = module.params.get("args")
local_path = module.params.get("local_path")
namespace = module.params.get("namespace")
pod = module.params.get("pod")
file = module.params.get("remote_path")
content = module.params.get("content")
if args:
pod_rc, pod_out, pod_err = kubectl_run_from_pod(module)
rc, out, err = module.run_command([module.params.get("local_path")] + args)
if rc == pod_rc and out == pod_out:
module.exit_json(
msg="{0} and {1}/{2}:{3} are same.".format(
local_path, namespace, pod, file
),
rc=rc,
stderr=err,
stdout=out,
)
result = dict(
local=dict(rc=rc, out=out, err=err),
remote=dict(rc=pod_rc, out=pod_out, err=pod_err),
)
module.fail_json(
msg=f"{local_path} and {namespace}/{pod}:{file} are same.", **result
)
else:
with TemporaryDirectory() as tmpdirname:
file_from_pod, err, rc, out = kubectl_get_content(
module=module, dest_dir=tmpdirname
)
if not os.path.exists(file_from_pod):
module.fail_json(
msg="failed to copy content from pod", error=err, output=out
)
if content is not None:
with NamedTemporaryFile(mode="w") as tmp_file:
tmp_file.write(content)
tmp_file.flush()
if filecmp.cmp(file_from_pod, tmp_file.name):
module.exit_json(
msg=f"defined content and {namespace}/{pod}:{file} are same."
)
module.fail_json(
msg=f"defined content and {namespace}/{pod}:{file} are same."
)
if os.path.isfile(local_path):
if filecmp.cmp(file_from_pod, local_path):
module.exit_json(
msg=f"{local_path} and {namespace}/{pod}:{file} are same."
)
module.fail_json(
msg=f"{local_path} and {namespace}/{pod}:{file} are same."
)
if os.path.isdir(local_path):
if compare_directories(file_from_pod, local_path):
module.exit_json(
msg=f"{local_path} and {namespace}/{pod}:{file} are same."
)
module.fail_json(
msg=f"{local_path} and {namespace}/{pod}:{file} are same."
)
def main():
argument_spec = {}
argument_spec["namespace"] = {"type": "str", "required": True}
argument_spec["pod"] = {"type": "str", "required": True}
argument_spec["container"] = {}
argument_spec["remote_path"] = {"type": "path", "required": True}
argument_spec["local_path"] = {"type": "path"}
argument_spec["content"] = {"type": "str"}
argument_spec["kubectl_path"] = {"type": "path"}
argument_spec["args"] = {"type": "list"}
module = AnsibleModule(
argument_spec=argument_spec,
mutually_exclusive=[("local_path", "content")],
required_one_of=[["local_path", "content"]],
)
execute_module(module)
if __name__ == "__main__":
main()

View File

@@ -1,3 +1,5 @@
--- ---
collections: collections:
- kubernetes.core - kubernetes.core
dependencies:
- setup_namespace

View File

@@ -1,4 +1,7 @@
--- ---
- set_fact:
copy_namespace: "{{ test_namespace }}"
- block: - block:
# Ensure namespace and create pod to perform tests on # Ensure namespace and create pod to perform tests on
- name: Ensure namespace exists - name: Ensure namespace exists

View File

@@ -0,0 +1,2 @@
time=22
k8s

View File

@@ -0,0 +1,2 @@
---
test_namespace: "crd"

View File

@@ -0,0 +1,3 @@
---
dependencies:
- setup_namespace

View File

@@ -1,13 +1,8 @@
--- ---
- block: - block:
- name: Create a namespace
k8s:
name: crd
kind: Namespace
- name: Install custom resource definitions - name: Install custom resource definitions
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/setup-crd.yml') }}" definition: "{{ lookup('file', 'setup-crd.yml') }}"
- name: Pause 5 seconds to avoid race condition - name: Pause 5 seconds to avoid race condition
pause: pause:
@@ -15,15 +10,15 @@
- name: Create custom resource definition - name: Create custom resource definition
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/crd-resource.yml') }}" definition: "{{ lookup('file', 'crd-resource.yml') }}"
namespace: crd namespace: "{{ test_namespace }}"
apply: "{{ create_crd_with_apply | default(omit) }}" apply: "{{ create_crd_with_apply | default(omit) }}"
register: create_crd register: create_crd
- name: Patch custom resource definition - name: Patch custom resource definition
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/crd-resource.yml') }}" definition: "{{ lookup('file', 'crd-resource.yml') }}"
namespace: crd namespace: "{{ test_namespace }}"
register: recreate_crd register: recreate_crd
ignore_errors: yes ignore_errors: yes
@@ -35,33 +30,32 @@
- block: - block:
- name: Recreate custom resource definition with merge_type - name: Recreate custom resource definition with merge_type
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/crd-resource.yml') }}" definition: "{{ lookup('file', 'crd-resource.yml') }}"
merge_type: merge_type:
- merge - merge
namespace: crd namespace: "{{ test_namespace }}"
register: recreate_crd_with_merge register: recreate_crd_with_merge
- name: Recreate custom resource definition with merge_type list - name: Recreate custom resource definition with merge_type list
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/crd-resource.yml') }}" definition: "{{ lookup('file', 'crd-resource.yml') }}"
merge_type: merge_type:
- strategic-merge - strategic-merge
- merge - merge
namespace: crd namespace: "{{ test_namespace }}"
register: recreate_crd_with_merge_list register: recreate_crd_with_merge_list
when: recreate_crd is successful when: recreate_crd is successful
- name: Remove crd - name: Remove crd
k8s: k8s:
definition: "{{ lookup('file', kubernetes_role_path + '/files/crd-resource.yml') }}" definition: "{{ lookup('file', 'crd-resource.yml') }}"
namespace: crd namespace: "{{ test_namespace }}"
state: absent state: absent
always: always:
- name: Remove crd namespace - name: Remove crd namespace
k8s: k8s:
kind: Namespace kind: Namespace
name: crd name: "{{ test_namespace }}"
state: absent state: absent
ignore_errors: yes

View File

@@ -0,0 +1,3 @@
time=70
k8s_info
k8s

View File

@@ -0,0 +1,25 @@
---
k8s_pod_template:
metadata:
labels:
app: "{{ k8s_pod_name }}"
spec:
serviceAccount: "default"
containers:
- image: "{{ k8s_pod_image }}"
imagePullPolicy: Always
name: "{{ k8s_pod_name }}"
command: []
readinessProbe:
initialDelaySeconds: 15
exec:
command:
- /bin/true
resources:
limits:
cpu: "100m"
memory: "100Mi"
ports: []
env: []
test_namespace: "delete"

View File

@@ -0,0 +1,3 @@
---
dependencies:
- setup_namespace

View File

@@ -1,16 +1,5 @@
--- ---
- block: - block:
- set_fact:
delete_namespace: delete
- name: Ensure namespace exists
k8s:
definition:
apiVersion: v1
kind: Namespace
metadata:
name: "{{ delete_namespace }}"
- name: Add a daemonset - name: Add a daemonset
k8s: k8s:
definition: definition:
@@ -18,14 +7,14 @@
kind: DaemonSet kind: DaemonSet
metadata: metadata:
name: delete-daemonset name: delete-daemonset
namespace: "{{ delete_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
selector: selector:
matchLabels: matchLabels:
app: "{{ k8s_pod_name }}" app: "{{ k8s_pod_name }}"
template: "{{ k8s_pod_template }}" template: "{{ k8s_pod_template }}"
wait: yes wait: yes
wait_timeout: 180 wait_timeout: 400
vars: vars:
k8s_pod_name: delete-ds k8s_pod_name: delete-ds
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1 k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1
@@ -38,7 +27,7 @@
- name: Check if pods exist - name: Check if pods exist
k8s_info: k8s_info:
namespace: "{{ delete_namespace }}" namespace: "{{ test_namespace }}"
kind: Pod kind: Pod
label_selectors: label_selectors:
- "app={{ k8s_pod_name }}" - "app={{ k8s_pod_name }}"
@@ -55,13 +44,13 @@
k8s: k8s:
kind: DaemonSet kind: DaemonSet
name: delete-daemonset name: delete-daemonset
namespace: "{{ delete_namespace }}" namespace: "{{ test_namespace }}"
state: absent state: absent
wait: yes wait: yes
- name: Show status of pods - name: Show status of pods
k8s_info: k8s_info:
namespace: "{{ delete_namespace }}" namespace: "{{ test_namespace }}"
kind: Pod kind: Pod
label_selectors: label_selectors:
- "app={{ k8s_pod_name }}" - "app={{ k8s_pod_name }}"
@@ -74,7 +63,7 @@
- name: Check if pods still exist - name: Check if pods still exist
k8s_info: k8s_info:
namespace: "{{ delete_namespace }}" namespace: "{{ test_namespace }}"
kind: Pod kind: Pod
label_selectors: label_selectors:
- "app={{ k8s_pod_name }}" - "app={{ k8s_pod_name }}"
@@ -91,5 +80,5 @@
- name: Remove namespace - name: Remove namespace
k8s: k8s:
kind: Namespace kind: Namespace
name: "{{ delete_namespace }}" name: "{{ test_namespace }}"
state: absent state: absent

View File

@@ -0,0 +1,2 @@
time=20
k8s

View File

@@ -0,0 +1,3 @@
---
test_namespace: "diff"
diff_configmap: "diff-configmap"

View File

@@ -0,0 +1,2 @@
dependencies:
- setup_namespace

View File

@@ -1,20 +1,14 @@
--- ---
- set_fact:
diff_namespace: "diff"
diff_configmap: "diff-configmap"
- block: - block:
- name: Ensure namespace - set_fact:
k8s: diff_namespace: "{{ test_namespace }}"
kind: Namespace
name: '{{ diff_namespace }}'
# Using option 'apply' set to 'yes' # Using option 'apply' set to 'yes'
- name: Create Pod using apply and diff set to yes - name: Create Pod using apply and diff set to yes
k8s: k8s:
namespace: '{{ diff_namespace }}' namespace: '{{ diff_namespace }}'
apply: yes apply: yes
template: "pod_diff.j2" template: "pod.j2"
diff: yes diff: yes
vars: vars:
pod_name: "pod-apply" pod_name: "pod-apply"
@@ -31,7 +25,7 @@
k8s: k8s:
namespace: '{{ diff_namespace }}' namespace: '{{ diff_namespace }}'
apply: yes apply: yes
template: "pod_diff.j2" template: "pod.j2"
diff: no diff: no
vars: vars:
pod_name: "pod-apply" pod_name: "pod-apply"
@@ -49,7 +43,7 @@
k8s: k8s:
namespace: '{{ diff_namespace }}' namespace: '{{ diff_namespace }}'
state: present state: present
template: "pod_diff.j2" template: "pod.j2"
vars: vars:
pod_name: "pod-patch" pod_name: "pod-patch"
pod_image: "busybox:1.32.0" pod_image: "busybox:1.32.0"
@@ -59,7 +53,7 @@
k8s: k8s:
namespace: '{{ diff_namespace }}' namespace: '{{ diff_namespace }}'
state: patched state: patched
template: "pod_diff.j2" template: "pod.j2"
diff: no diff: no
vars: vars:
pod_name: "pod-patch" pod_name: "pod-patch"
@@ -77,7 +71,7 @@
k8s: k8s:
namespace: '{{ diff_namespace }}' namespace: '{{ diff_namespace }}'
state: patched state: patched
template: "pod_diff.j2" template: "pod.j2"
diff: yes diff: yes
vars: vars:
pod_name: "pod-patch" pod_name: "pod-patch"
@@ -151,3 +145,4 @@
state: absent state: absent
kind: Namespace kind: Namespace
name: '{{ diff_namespace }}' name: '{{ diff_namespace }}'
ignore_errors: true

View File

@@ -0,0 +1,4 @@
k8s_drain
k8s
k8s_info
time=78

View File

@@ -0,0 +1,3 @@
---
test_namespace: "drain"
k8s_wait_timeout: 400

View File

@@ -0,0 +1,3 @@
---
dependencies:
- setup_namespace

View File

@@ -2,16 +2,10 @@
- block: - block:
- name: Set common facts - name: Set common facts
set_fact: set_fact:
drain_namespace: "drain"
drain_daemonset_name: "promotheus-dset" drain_daemonset_name: "promotheus-dset"
drain_pod_name: "pod-drain" drain_pod_name: "pod-drain"
drain_deployment_emptydir_name: "deployment-emptydir-drain" drain_deployment_emptydir_name: "deployment-emptydir-drain"
- name: Create {{ drain_namespace }} namespace
k8s:
kind: Namespace
name: '{{ drain_namespace }}'
# It seems that the default ServiceAccount can take a bit to be created # It seems that the default ServiceAccount can take a bit to be created
# right after a cluster is brought up. This can lead to the ServiceAccount # right after a cluster is brought up. This can lead to the ServiceAccount
# admission controller rejecting a Pod creation request because the # admission controller rejecting a Pod creation request because the
@@ -20,7 +14,7 @@
k8s_info: k8s_info:
kind: ServiceAccount kind: ServiceAccount
name: default name: default
namespace: "{{ drain_namespace }}" namespace: "{{ test_namespace }}"
wait: yes wait: yes
- name: list cluster nodes - name: list cluster nodes
@@ -43,7 +37,7 @@
- name: Deploy daemonset on cluster - name: Deploy daemonset on cluster
k8s: k8s:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
definition: definition:
apiVersion: apps/v1 apiVersion: apps/v1
kind: DaemonSet kind: DaemonSet
@@ -75,8 +69,9 @@
- name: Create Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet. - name: Create Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.
k8s: k8s:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
definition: definition:
apiVersion: v1 apiVersion: v1
kind: Pod kind: Pod
@@ -102,8 +97,9 @@
- name: Create Deployment with an emptyDir volume. - name: Create Deployment with an emptyDir volume.
k8s: k8s:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
wait: yes wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
definition: definition:
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
@@ -147,7 +143,7 @@
- name: Register emptyDir Pod name - name: Register emptyDir Pod name
k8s_info: k8s_info:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
kind: Pod kind: Pod
label_selectors: label_selectors:
- "drain = emptyDir" - "drain = emptyDir"
@@ -180,7 +176,7 @@
- name: Get pods - name: Get pods
k8s_info: k8s_info:
kind: Pod kind: Pod
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
register: Pod register: Pod
- name: assert that pods are running on cordoned node - name: assert that pods are running on cordoned node
@@ -244,7 +240,7 @@
- name: assert that unmanaged pod were deleted - name: assert that unmanaged pod were deleted
k8s_info: k8s_info:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
kind: Pod kind: Pod
name: '{{ drain_pod_name }}' name: '{{ drain_pod_name }}'
register: _result register: _result
@@ -252,7 +248,7 @@
- name: assert that emptyDir pod was deleted - name: assert that emptyDir pod was deleted
k8s_info: k8s_info:
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
kind: Pod kind: Pod
name: "{{ emptydir_pod_result.resources[0].metadata.name }}" name: "{{ emptydir_pod_result.resources[0].metadata.name }}"
register: _result register: _result
@@ -276,7 +272,7 @@
- name: Get DaemonSet - name: Get DaemonSet
k8s_info: k8s_info:
kind: DaemonSet kind: DaemonSet
namespace: '{{ drain_namespace }}' namespace: '{{ test_namespace }}'
name: '{{ drain_daemonset_name }}' name: '{{ drain_daemonset_name }}'
register: dset_result register: dset_result
@@ -302,4 +298,4 @@
k8s: k8s:
state: absent state: absent
kind: namespace kind: namespace
name: '{{ drain_namespace }}' name: '{{ test_namespace }}'

View File

@@ -0,0 +1,3 @@
k8s_exec
k8s
time=23

View File

@@ -0,0 +1,2 @@
---
test_namespace: "k8s-exec"

View File

@@ -0,0 +1,3 @@
---
dependencies:
- setup_namespace

View File

@@ -1,13 +1,13 @@
--- ---
- vars: - vars:
exec_namespace: k8s-exec k8s_wait_timeout: 400
pod: sleep-pod pod: sleep-pod
exec_pod_definition: exec_pod_definition:
apiVersion: v1 apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: "{{ pod }}" name: "{{ pod }}"
namespace: "{{ exec_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
containers: containers:
- name: sleeper - name: sleeper
@@ -19,7 +19,7 @@
kind: Pod kind: Pod
metadata: metadata:
name: "{{ multi_container_pod_name }}" name: "{{ multi_container_pod_name }}"
namespace: "{{ exec_namespace }}" namespace: "{{ test_namespace }}"
spec: spec:
containers: containers:
- name: sleeper-1 - name: sleeper-1
@@ -30,22 +30,17 @@
command: ["sleep", "infinity"] command: ["sleep", "infinity"]
block: block:
- name: "Ensure that {{ exec_namespace }} namespace exists"
k8s:
kind: Namespace
name: "{{ exec_namespace }}"
- name: "Create a pod" - name: "Create a pod"
k8s: k8s:
definition: "{{ exec_pod_definition }}" definition: "{{ exec_pod_definition }}"
wait: yes wait: yes
wait_sleep: 1 wait_sleep: 1
wait_timeout: 30 wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
- name: "Execute a command" - name: "Execute a command"
k8s_exec: k8s_exec:
pod: "{{ pod }}" pod: "{{ pod }}"
namespace: "{{ exec_namespace }}" namespace: "{{ test_namespace }}"
command: cat /etc/resolv.conf command: cat /etc/resolv.conf
register: output register: output
@@ -60,7 +55,7 @@
- name: Check if rc is returned for the given command - name: Check if rc is returned for the given command
k8s_exec: k8s_exec:
namespace: "{{ exec_namespace }}" namespace: "{{ test_namespace }}"
pod: "{{ pod }}" pod: "{{ pod }}"
command: 'false' command: 'false'
register: command_status register: command_status
@@ -77,12 +72,12 @@
definition: "{{ multi_container_pod_definition }}" definition: "{{ multi_container_pod_definition }}"
wait: yes wait: yes
wait_sleep: 1 wait_sleep: 1
wait_timeout: 30 wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
- name: Execute command on the first container of the pod - name: Execute command on the first container of the pod
k8s_exec: k8s_exec:
pod: "{{ multi_container_pod_name }}" pod: "{{ multi_container_pod_name }}"
namespace: "{{ exec_namespace }}" namespace: "{{ test_namespace }}"
command: echo hello command: echo hello
register: output register: output
@@ -95,5 +90,5 @@
- name: "Cleanup namespace" - name: "Cleanup namespace"
k8s: k8s:
kind: Namespace kind: Namespace
name: "{{ exec_namespace }}" name: "{{ test_namespace }}"
state: absent state: absent

View File

@@ -0,0 +1,3 @@
time=57
k8s
k8s_info

View File

@@ -0,0 +1,10 @@
---
test_namespace:
- testing
- testing1
- testing2
- testing3
- testing4
- testing5
- testing6
- test-namespace-module-defaults

View File

@@ -0,0 +1,3 @@
---
dependencies:
- remove_namespace

View File

@@ -0,0 +1 @@
time=142

Some files were not shown because too many files have changed in this diff Show More