mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-30 15:23:03 +00:00
merge with main
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
---
|
||||
minor_changes:
|
||||
- k8s - wait for all pods to update when rolling out daemonset changes (https://github.com/ansible-collections/kubernetes.core/pull/102).
|
||||
3
changelogs/fragments/90-k8s-add-parameter-patch_only.yml
Normal file
3
changelogs/fragments/90-k8s-add-parameter-patch_only.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
minor_changes:
|
||||
- k8s - support ``patched`` value for ``state`` option. patched state is an existing resource that has a given patch applied (https://github.com/ansible-collections/kubernetes.core/pull/90).
|
||||
@@ -141,6 +141,14 @@
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Include patched.yml
|
||||
include_tasks:
|
||||
file: tasks/patched.yml
|
||||
apply:
|
||||
tags: [ patched, k8s ]
|
||||
tags:
|
||||
- always
|
||||
|
||||
roles:
|
||||
- role: helm
|
||||
tags:
|
||||
|
||||
123
molecule/default/tasks/patched.yml
Normal file
123
molecule/default/tasks/patched.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
- block:
|
||||
- set_fact:
|
||||
patch_only_namespace:
|
||||
first: patched-namespace-1
|
||||
second: patched-namespace-2
|
||||
|
||||
- name: Ensure namespace {{ patch_only_namespace.first }} exist
|
||||
kubernetes.core.k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ patch_only_namespace.first }}"
|
||||
labels:
|
||||
existingLabel: "labelValue"
|
||||
annotations:
|
||||
existingAnnotation: "annotationValue"
|
||||
wait: yes
|
||||
|
||||
- name: Ensure namespace {{ patch_only_namespace.second }} does not exist
|
||||
kubernetes.core.k8s_info:
|
||||
kind: namespace
|
||||
name: "{{ patch_only_namespace.second }}"
|
||||
register: second_namespace
|
||||
|
||||
- name: assert that second namespace does not exist
|
||||
assert:
|
||||
that:
|
||||
- second_namespace.resources | length == 0
|
||||
|
||||
- name: apply patch on existing resource
|
||||
kubernetes.core.k8s:
|
||||
state: patched
|
||||
wait: yes
|
||||
definition: |
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ patch_only_namespace.first }}"
|
||||
labels:
|
||||
ansible: patched
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ patch_only_namespace.second }}"
|
||||
labels:
|
||||
ansible: patched
|
||||
register: patch_resource
|
||||
|
||||
- name: assert that patch succeed
|
||||
assert:
|
||||
that:
|
||||
- patch_resource.changed
|
||||
- patch_resource.result.results | selectattr('warning', 'defined') | list | length == 1
|
||||
|
||||
- name: Ensure namespace {{ patch_only_namespace.first }} was patched correctly
|
||||
kubernetes.core.k8s_info:
|
||||
kind: namespace
|
||||
name: "{{ patch_only_namespace.first }}"
|
||||
register: first_namespace
|
||||
|
||||
- name: assert labels are as expected
|
||||
assert:
|
||||
that:
|
||||
- first_namespace.resources[0].metadata.labels.ansible == "patched"
|
||||
- first_namespace.resources[0].metadata.labels.existingLabel == "labelValue"
|
||||
- first_namespace.resources[0].metadata.annotations.existingAnnotation == "annotationValue"
|
||||
- name: Ensure namespace {{ patch_only_namespace.second }} was not created
|
||||
kubernetes.core.k8s_info:
|
||||
kind: namespace
|
||||
name: "{{ patch_only_namespace.second }}"
|
||||
register: second_namespace
|
||||
|
||||
- name: assert that second namespace does not exist
|
||||
assert:
|
||||
that:
|
||||
- second_namespace.resources | length == 0
|
||||
|
||||
- name: patch all resources (create if does not exist)
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition: |
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ patch_only_namespace.first }}"
|
||||
labels:
|
||||
patch: ansible
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ patch_only_namespace.second }}"
|
||||
labels:
|
||||
patch: ansible
|
||||
wait: yes
|
||||
register: patch_resource
|
||||
|
||||
- name: Ensure namespace {{ patch_only_namespace.second }} was created
|
||||
kubernetes.core.k8s_info:
|
||||
kind: namespace
|
||||
name: "{{ patch_only_namespace.second }}"
|
||||
register: second_namespace
|
||||
|
||||
- name: assert that second namespace exist
|
||||
assert:
|
||||
that:
|
||||
- second_namespace.resources | length == 1
|
||||
|
||||
always:
|
||||
- name: Remove namespace
|
||||
kubernetes.core.k8s:
|
||||
kind: Namespace
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- "{{ patch_only_namespace.first }}"
|
||||
- "{{ patch_only_namespace.second }}"
|
||||
ignore_errors: true
|
||||
@@ -54,6 +54,9 @@
|
||||
vars:
|
||||
k8s_pod_name: wait-ds
|
||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1
|
||||
k8s_pod_command:
|
||||
- sleep
|
||||
- "600"
|
||||
register: ds
|
||||
|
||||
- name: Check that daemonset wait worked
|
||||
@@ -82,6 +85,9 @@
|
||||
vars:
|
||||
k8s_pod_name: wait-ds
|
||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:2
|
||||
k8s_pod_command:
|
||||
- sleep
|
||||
- "600"
|
||||
register: update_ds_check_mode
|
||||
check_mode: yes
|
||||
|
||||
@@ -112,6 +118,9 @@
|
||||
vars:
|
||||
k8s_pod_name: wait-ds
|
||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:3
|
||||
k8s_pod_command:
|
||||
- sleep
|
||||
- "600"
|
||||
register: ds
|
||||
|
||||
- name: Get updated pods
|
||||
|
||||
@@ -404,6 +404,7 @@ class K8sAnsibleMixin(object):
|
||||
|
||||
def _daemonset_ready(daemonset):
|
||||
return (daemonset.status and daemonset.status.desiredNumberScheduled is not None
|
||||
and daemonset.status.updatedNumberScheduled == daemonset.status.desiredNumberScheduled
|
||||
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
|
||||
and daemonset.status.observedGeneration == daemonset.metadata.generation
|
||||
and not daemonset.status.unavailableReplicas)
|
||||
@@ -548,7 +549,8 @@ class K8sAnsibleMixin(object):
|
||||
if self.params['validate'] is not None:
|
||||
self.warnings = self.validate(definition)
|
||||
result = self.perform_action(resource, definition)
|
||||
result['warnings'] = self.warnings
|
||||
if self.warnings:
|
||||
result['warnings'] = self.warnings
|
||||
changed = changed or result['changed']
|
||||
results.append(result)
|
||||
|
||||
@@ -690,6 +692,7 @@ class K8sAnsibleMixin(object):
|
||||
else:
|
||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
||||
return result
|
||||
|
||||
else:
|
||||
if apply:
|
||||
if self.check_mode:
|
||||
@@ -734,7 +737,14 @@ class K8sAnsibleMixin(object):
|
||||
return result
|
||||
|
||||
if not existing:
|
||||
if self.check_mode:
|
||||
if state == 'patched':
|
||||
# Silently skip this resource (do not raise an error) as 'patch_only' is set to true
|
||||
result['changed'] = False
|
||||
result['warning'] = "resource 'kind={kind},name={name}' was not found but will not be created as 'state'\
|
||||
parameter has been set to '{state}'".format(
|
||||
kind=definition['kind'], name=origin_name, state=state)
|
||||
return result
|
||||
elif self.check_mode:
|
||||
k8s_obj = _encode_stringdata(definition)
|
||||
else:
|
||||
try:
|
||||
@@ -784,7 +794,7 @@ class K8sAnsibleMixin(object):
|
||||
match = False
|
||||
diffs = []
|
||||
|
||||
if existing and force:
|
||||
if state == 'present' and existing and force:
|
||||
if self.check_mode:
|
||||
k8s_obj = _encode_stringdata(definition)
|
||||
else:
|
||||
|
||||
@@ -30,7 +30,6 @@ description:
|
||||
- Supports check mode.
|
||||
|
||||
extends_documentation_fragment:
|
||||
- kubernetes.core.k8s_state_options
|
||||
- kubernetes.core.k8s_name_options
|
||||
- kubernetes.core.k8s_resource_options
|
||||
- kubernetes.core.k8s_auth_options
|
||||
@@ -38,6 +37,21 @@ extends_documentation_fragment:
|
||||
- kubernetes.core.k8s_delete_options
|
||||
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Determines if an object should be created, patched, or deleted. When set to C(present), an object will be
|
||||
created, if it does not already exist. If set to C(absent), an existing object will be deleted. If set to
|
||||
C(present), an existing object will be patched, if its attributes differ from those specified using
|
||||
I(resource_definition) or I(src).
|
||||
- C(patched) state is an existing resource that has a given patch applied. If the resource doesn't exist, silently skip it (do not raise an error).
|
||||
type: str
|
||||
default: present
|
||||
choices: [ absent, present, patched ]
|
||||
force:
|
||||
description:
|
||||
- If set to C(yes), and I(state) is C(present), an existing object will be replaced.
|
||||
type: bool
|
||||
default: no
|
||||
merge_type:
|
||||
description:
|
||||
- Whether to override the default patch merge approach with a specific type. By default, the strategic
|
||||
@@ -235,7 +249,6 @@ EXAMPLES = r'''
|
||||
wait_condition:
|
||||
type: Progressing
|
||||
status: Unknown
|
||||
reason: DeploymentPaused
|
||||
|
||||
# Wait for this service to have acquired an External IP
|
||||
- name: Create ingress and wait for ip to be assigned
|
||||
@@ -245,12 +258,24 @@ EXAMPLES = r'''
|
||||
wait_property:
|
||||
property: status.loadBalancer.ingress[*].ip
|
||||
|
||||
# Wait for containers inside pod to be running
|
||||
- name: Create Pod and wait for containers for be running
|
||||
kubernetes.core.k8s:
|
||||
template: pod.yaml
|
||||
wait: yes
|
||||
wait_property:
|
||||
property: status.containerStatuses[*].state.running
|
||||
|
||||
# Patch existing namespace : add label
|
||||
- name: add label to existing namespace
|
||||
kubernetes.core.k8s:
|
||||
state: patched
|
||||
kind: Namespace
|
||||
name: patch_namespace
|
||||
definition:
|
||||
metadata:
|
||||
labels:
|
||||
support: patch
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
@@ -299,7 +324,7 @@ import copy
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, WAIT_ARG_SPEC, NAME_ARG_SPEC, COMMON_ARG_SPEC, RESOURCE_ARG_SPEC, DELETE_OPTS_ARG_SPEC)
|
||||
AUTH_ARG_SPEC, WAIT_ARG_SPEC, NAME_ARG_SPEC, RESOURCE_ARG_SPEC, DELETE_OPTS_ARG_SPEC)
|
||||
|
||||
|
||||
def validate_spec():
|
||||
@@ -311,8 +336,7 @@ def validate_spec():
|
||||
|
||||
|
||||
def argspec():
|
||||
argument_spec = copy.deepcopy(COMMON_ARG_SPEC)
|
||||
argument_spec.update(copy.deepcopy(NAME_ARG_SPEC))
|
||||
argument_spec = copy.deepcopy(NAME_ARG_SPEC)
|
||||
argument_spec.update(copy.deepcopy(RESOURCE_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||
@@ -323,6 +347,9 @@ def argspec():
|
||||
argument_spec['template'] = dict(type='raw', default=None)
|
||||
argument_spec['delete_options'] = dict(type='dict', default=None, options=copy.deepcopy(DELETE_OPTS_ARG_SPEC))
|
||||
argument_spec['continue_on_error'] = dict(type='bool', default=False)
|
||||
argument_spec['state'] = dict(default='present', choices=['present', 'absent', 'patched'])
|
||||
argument_spec['force'] = dict(type='bool', default=False)
|
||||
|
||||
return argument_spec
|
||||
|
||||
|
||||
@@ -334,6 +361,7 @@ def execute_module(module, k8s_ansible_mixin):
|
||||
k8s_ansible_mixin.fail_json = k8s_ansible_mixin.module.fail_json
|
||||
k8s_ansible_mixin.fail = k8s_ansible_mixin.module.fail_json
|
||||
k8s_ansible_mixin.exit_json = k8s_ansible_mixin.module.exit_json
|
||||
k8s_ansible_mixin.warn = k8s_ansible_mixin.module.warn
|
||||
k8s_ansible_mixin.warnings = []
|
||||
|
||||
k8s_ansible_mixin.kind = k8s_ansible_mixin.params.get('kind')
|
||||
|
||||
Reference in New Issue
Block a user