mirror of
https://github.com/openshift/community.okd.git
synced 2026-03-26 19:03:14 +00:00
Add Molecule tests (#7)
* Initial port to molecule * Get molecule tests to run * Draw the rest of the owl * use local dir for storing collection during CI run * Add dockerfile, install community.kubernetes collection before sanity check * Add clean step to Makefile * Get sanity tests working * Update sanity test to use makefile * Add ignores for 2.11 so devel passes * Update description * Code review * Add OWNERS file for prow
This commit is contained in:
committed by
GitHub
parent
3db69dea2b
commit
ee21083985
2
.github/workflows/ansible-test.yml
vendored
2
.github/workflows/ansible-test.yml
vendored
@@ -51,7 +51,7 @@ jobs:
|
||||
# The docker container has all the pinned dependencies that are required.
|
||||
# Explicity specify the version of Python we want to test
|
||||
- name: Run sanity tests
|
||||
run: ansible-test sanity --docker -v --color --python ${{ matrix.python }}
|
||||
run: make test-sanity TEST_ARGS='--python ${{ matrix.python }}'
|
||||
working-directory: ./ansible_collections/community/okd
|
||||
|
||||
###
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,9 @@
|
||||
*.log
|
||||
__pycache__/
|
||||
|
||||
# temp collection path
|
||||
# Can't ignore this directory for now, as the files have to be viewable by git in order to be sanity-checked
|
||||
# ansible_collections/
|
||||
# Galaxy artifacts.
|
||||
*.tar.gz
|
||||
|
||||
|
||||
33
.yamllint
Normal file
33
.yamllint
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
# Based on ansible-lint config
|
||||
extends: default
|
||||
|
||||
rules:
|
||||
braces:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
brackets:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
colons:
|
||||
max-spaces-after: -1
|
||||
level: error
|
||||
commas:
|
||||
max-spaces-after: -1
|
||||
level: error
|
||||
comments: disable
|
||||
comments-indentation: disable
|
||||
document-start: disable
|
||||
empty-lines:
|
||||
max: 3
|
||||
level: error
|
||||
hyphens:
|
||||
level: error
|
||||
indentation: disable
|
||||
key-duplicates: enable
|
||||
line-length: disable
|
||||
new-line-at-end-of-file: disable
|
||||
new-lines:
|
||||
type: unix
|
||||
trailing-spaces: disable
|
||||
truthy: disable
|
||||
18
Makefile
Normal file
18
Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
# Also needs to be updated in galaxy.yml
|
||||
VERSION = 0.1.0
|
||||
|
||||
clean:
|
||||
rm -f community-okd-${VERSION}.tar.gz
|
||||
rm -rf ansible_collections
|
||||
|
||||
build: clean
|
||||
ansible-galaxy collection build
|
||||
|
||||
install: build
|
||||
ansible-galaxy collection install -p ansible_collections community-okd-${VERSION}.tar.gz
|
||||
|
||||
test-sanity: install
|
||||
cd ansible_collections/community/okd && ansible-test sanity -v --docker --color $(TEST_ARGS)
|
||||
|
||||
test-integration: install
|
||||
molecule test
|
||||
6
OWNERS
Normal file
6
OWNERS
Normal file
@@ -0,0 +1,6 @@
|
||||
approvers:
|
||||
- geerlingguy
|
||||
- fabianvf
|
||||
reviewers:
|
||||
- geerlingguy
|
||||
- fabianvf
|
||||
19
README.md
19
README.md
@@ -12,6 +12,8 @@ Click on the name of a plugin or module to view that content's documentation:
|
||||
|
||||
- **Inventory Source**:
|
||||
- [openshift](https://docs.ansible.com/ansible/2.10/collections/community/kubernetes/openshift_inventory.html)
|
||||
- **Modules**:
|
||||
- [k8s](https://docs.ansible.com/ansible/latest/modules/k8s_module.html)
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
@@ -54,14 +56,19 @@ For documentation on how to use individual plugins included in this collection,
|
||||
|
||||
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||
|
||||
### Testing with `ansible-test`
|
||||
The `tests` directory contains configuration for running sanity tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
||||
|
||||
The `tests` directory contains configuration for running sanity and integration tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
||||
You can run the `ansible-test` sanity tests with the command:
|
||||
|
||||
You can run the collection's test suites with the commands:
|
||||
make test-sanity
|
||||
|
||||
ansible-test sanity --docker -v --color
|
||||
ansible-test integration --docker -v --color
|
||||
The `molecule` directory contains configuration for running integration tests using [`molecule`](https://molecule.readthedocs.io/).
|
||||
|
||||
You can run the `molecule` integration tests with the command:
|
||||
|
||||
make test-integration
|
||||
|
||||
These commands will create a directory called `ansible_collections` which should not be committed or added to the `.gitignore` (Tracking issue: https://github.com/ansible/ansible/issues/68499)
|
||||
|
||||
## Publishing New Versions
|
||||
|
||||
@@ -69,7 +76,7 @@ The current process for publishing new versions of the OKD Collection is manual,
|
||||
|
||||
1. Ensure you're running Ansible from devel, so the [`build_ignore` key](https://github.com/ansible/ansible/issues/67130) in `galaxy.yml` is used.
|
||||
1. Run `git clean -x -d -f` in this repository's directory to clean out any extra files which should not be included.
|
||||
1. Update `galaxy.yml` and this README's `requirements.yml` example with the new `version` for the collection.
|
||||
1. Update `galaxy.yml`, the `Makefile`, and this README's `requirements.yml` example with the new `version` for the collection.
|
||||
1. Update the CHANGELOG:
|
||||
1. Make sure you have [`antsibull-changelog`](https://pypi.org/project/antsibull-changelog/) installed.
|
||||
1. Make sure there are fragments for all known changes in `changelogs/fragments`.
|
||||
|
||||
14
ci/Dockerfile
Normal file
14
ci/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM registry.access.redhat.com/ubi8/ubi
|
||||
|
||||
RUN yum install -y make python3 python3-devel python3-pip python3-setuptools \
|
||||
&& pip3 install --upgrade setuptools pip \
|
||||
&& pip3 install \
|
||||
openshift \
|
||||
ansible \
|
||||
molecule
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
COPY . /src
|
||||
|
||||
USER 1001
|
||||
@@ -23,7 +23,5 @@ tags:
|
||||
- openshift
|
||||
- okd
|
||||
- cluster
|
||||
# Also needs to be updated in the Makefile
|
||||
version: 0.1.0
|
||||
build_ignore:
|
||||
- .DS_Store
|
||||
- '*.tar.gz'
|
||||
|
||||
59
molecule/default/converge.yml
Normal file
59
molecule/default/converge.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: '{{ virtualenv_interpreter }}'
|
||||
tasks:
|
||||
# OpenShift Resources
|
||||
- name: Create a project
|
||||
community.okd.k8s:
|
||||
name: testing
|
||||
kind: Project
|
||||
api_version: project.openshift.io/v1
|
||||
apply: no
|
||||
register: output
|
||||
|
||||
- name: show output
|
||||
debug:
|
||||
var: output
|
||||
|
||||
- name: Create deployment config
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
inline: &dc
|
||||
apiVersion: v1
|
||||
kind: DeploymentConfig
|
||||
metadata:
|
||||
name: elastic
|
||||
labels:
|
||||
app: galaxy
|
||||
service: elastic
|
||||
namespace: testing
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: galaxy
|
||||
service: elastic
|
||||
spec:
|
||||
containers:
|
||||
- name: elastic
|
||||
volumeMounts:
|
||||
- mountPath: /usr/share/elasticsearch/data
|
||||
name: elastic-volume
|
||||
command: ['elasticsearch']
|
||||
image: 'ansible/galaxy-elasticsearch:2.4.6'
|
||||
volumes:
|
||||
- name: elastic-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: elastic-volume
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Rolling
|
||||
register: output
|
||||
|
||||
- name: Show output
|
||||
debug:
|
||||
var: output
|
||||
6
molecule/default/destroy.yml
Normal file
6
molecule/default/destroy.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Destroy
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: no
|
||||
tasks: []
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
38
molecule/default/molecule.yml
Normal file
38
molecule/default/molecule.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
driver:
|
||||
name: delegated
|
||||
platforms:
|
||||
- name: cluster
|
||||
groups:
|
||||
- k8s
|
||||
provisioner:
|
||||
name: ansible
|
||||
lint: |
|
||||
set -e
|
||||
ansible-lint
|
||||
inventory:
|
||||
host_vars:
|
||||
localhost:
|
||||
virtualenv: ${MOLECULE_EPHEMERAL_DIRECTORY}/virtualenv
|
||||
virtualenv_command: '{{ ansible_playbook_python }} -m virtualenv'
|
||||
virtualenv_interpreter: '{{ virtualenv }}/bin/python'
|
||||
playbook_namespace: molecule-tests
|
||||
env:
|
||||
ANSIBLE_FORCE_COLOR: 'true'
|
||||
ANSIBLE_COLLECTIONS_PATHS: ${MOLECULE_PROJECT_DIRECTORY}
|
||||
verifier:
|
||||
name: ansible
|
||||
lint: |
|
||||
set -e
|
||||
ansible-lint
|
||||
scenario:
|
||||
name: default
|
||||
test_sequence:
|
||||
- lint
|
||||
- syntax
|
||||
- prepare
|
||||
- converge
|
||||
- idempotence
|
||||
- verify
|
||||
17
molecule/default/prepare.yml
Normal file
17
molecule/default/prepare.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Prepare
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: no
|
||||
|
||||
tasks:
|
||||
- pip:
|
||||
name: virtualenv
|
||||
|
||||
- pip:
|
||||
name:
|
||||
- openshift>=0.9.2
|
||||
- coverage
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
virtualenv_command: "{{ virtualenv_command }}"
|
||||
virtualenv_site_packages: no
|
||||
@@ -1,16 +1,13 @@
|
||||
---
|
||||
- block:
|
||||
- name: Create a namespace
|
||||
community.kubernetes.k8s:
|
||||
- name: Create a project
|
||||
community.okd.k8s:
|
||||
name: "{{ playbook_namespace }}"
|
||||
kind: Namespace
|
||||
|
||||
- copy:
|
||||
src: files
|
||||
dest: "{{ remote_tmp_dir }}"
|
||||
kind: Project
|
||||
api_version: project.openshift.io/v1
|
||||
|
||||
- name: incredibly simple ConfigMap
|
||||
community.kubernetes.k8s:
|
||||
community.okd.k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
@@ -27,16 +24,16 @@
|
||||
- k8s_with_validate is successful
|
||||
|
||||
- name: extra property does not fail without strict
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/kuard-extra-property.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/kuard-extra-property.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
strict: no
|
||||
|
||||
- name: extra property fails with strict
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/kuard-extra-property.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/kuard-extra-property.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
@@ -50,8 +47,8 @@
|
||||
- extra_property is failed
|
||||
|
||||
- name: invalid type fails at validation stage
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/kuard-invalid-type.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/kuard-invalid-type.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
@@ -65,8 +62,8 @@
|
||||
- invalid_type is failed
|
||||
|
||||
- name: invalid type fails with warnings when fail_on_error is False
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/kuard-invalid-type.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/kuard-invalid-type.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: no
|
||||
@@ -80,16 +77,16 @@
|
||||
- invalid_type_no_fail is failed
|
||||
|
||||
- name: setup custom resource definition
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/setup-crd.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/setup-crd.yml"
|
||||
|
||||
- name: wait a few seconds
|
||||
pause:
|
||||
seconds: 5
|
||||
|
||||
- name: add custom resource definition
|
||||
community.kubernetes.k8s:
|
||||
src: "{{ remote_tmp_dir }}/files/crd-resource.yml"
|
||||
community.okd.k8s:
|
||||
src: "files/crd-resource.yml"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
@@ -104,23 +101,23 @@
|
||||
|
||||
always:
|
||||
- name: remove custom resource
|
||||
community.kubernetes.k8s:
|
||||
definition: "{{ lookup('file', role_path + '/files/crd-resource.yml') }}"
|
||||
community.okd.k8s:
|
||||
definition: "{{ lookup('file', 'files/crd-resource.yml') }}"
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
|
||||
- name: remove custom resource definitions
|
||||
community.kubernetes.k8s:
|
||||
definition: "{{ lookup('file', role_path + '/files/setup-crd.yml') }}"
|
||||
community.okd.k8s:
|
||||
definition: "{{ lookup('file', 'files/setup-crd.yml') }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete namespace
|
||||
community.kubernetes.k8s:
|
||||
community.okd.k8s:
|
||||
state: absent
|
||||
definition:
|
||||
- kind: Namespace
|
||||
apiVersion: v1
|
||||
- kind: Project
|
||||
apiVersion: project.openshift.io/v1
|
||||
metadata:
|
||||
name: "{{ playbook_namespace }}"
|
||||
ignore_errors: yes
|
||||
@@ -6,7 +6,7 @@
|
||||
# - kubernetes
|
||||
# - kubernetes-validate
|
||||
|
||||
- community.kubernetes.k8s:
|
||||
- community.okd.k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
26
molecule/default/verify.yml
Normal file
26
molecule/default/verify.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: '{{ virtualenv_interpreter }}'
|
||||
|
||||
tasks:
|
||||
|
||||
- pip:
|
||||
name: kubernetes-validate==1.12.0
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
virtualenv_command: "{{ virtualenv_command }}"
|
||||
virtualenv_site_packages: no
|
||||
|
||||
- import_tasks: tasks/validate_installed.yml
|
||||
|
||||
- pip:
|
||||
name: kubernetes-validate
|
||||
state: absent
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
virtualenv_command: "{{ virtualenv_command }}"
|
||||
virtualenv_site_packages: no
|
||||
|
||||
- import_tasks: tasks/validate_not_installed.yml
|
||||
336
plugins/modules/k8s.py
Normal file
336
plugins/modules/k8s.py
Normal file
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2018, Chris Houseknecht <@chouseknecht>
|
||||
# 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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
|
||||
module: k8s
|
||||
|
||||
short_description: Manage OpenShift objects
|
||||
|
||||
author:
|
||||
- "Chris Houseknecht (@chouseknecht)"
|
||||
- "Fabian von Feilitzsch (@fabianvf)"
|
||||
|
||||
description:
|
||||
- Use the OpenShift Python client to perform CRUD operations on K8s objects.
|
||||
- Pass the object definition from a source file or inline. See examples for reading
|
||||
files and using Jinja templates or vault-encrypted files.
|
||||
- Access to the full range of K8s APIs.
|
||||
- Use the M(k8s_info) module to obtain a list of items about an object of type C(kind)
|
||||
- Authenticate using either a config file, certificates, password or token.
|
||||
- Supports check mode.
|
||||
- Optimized for OKD/OpenShift Kubernetes flavors
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.kubernetes.k8s_state_options
|
||||
- community.kubernetes.k8s_name_options
|
||||
- community.kubernetes.k8s_resource_options
|
||||
- community.kubernetes.k8s_auth_options
|
||||
|
||||
notes:
|
||||
- If your OpenShift Python library is not 0.9.0 or newer and you are trying to
|
||||
remove an item from an associative array/dictionary, for example a label or
|
||||
an annotation, you will need to explicitly set the value of the item to be
|
||||
removed to `null`. Simply deleting the entry in the dictionary will not
|
||||
remove it from openshift or kubernetes.
|
||||
|
||||
options:
|
||||
merge_type:
|
||||
description:
|
||||
- Whether to override the default patch merge approach with a specific type. By default, the strategic
|
||||
merge will typically be used.
|
||||
- For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may
|
||||
want to use C(merge) if you see "strategic merge patch format is not supported"
|
||||
- See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)
|
||||
- Requires openshift >= 0.6.2
|
||||
- If more than one merge_type is given, the merge_types will be tried in order
|
||||
- If openshift >= 0.6.2, this defaults to C(['strategic-merge', 'merge']), which is ideal for using the same parameters
|
||||
on resource kinds that combine Custom Resources and built-in resources. For openshift < 0.6.2, the default
|
||||
is simply C(strategic-merge).
|
||||
- mutually exclusive with C(apply)
|
||||
choices:
|
||||
- json
|
||||
- merge
|
||||
- strategic-merge
|
||||
type: list
|
||||
elements: str
|
||||
wait:
|
||||
description:
|
||||
- Whether to wait for certain resource kinds to end up in the desired state. By default the module exits once Kubernetes has
|
||||
received the request
|
||||
- Implemented for C(state=present) for C(Deployment), C(DaemonSet) and C(Pod), and for C(state=absent) for all resource kinds.
|
||||
- For resource kinds without an implementation, C(wait) returns immediately unless C(wait_condition) is set.
|
||||
default: no
|
||||
type: bool
|
||||
wait_sleep:
|
||||
description:
|
||||
- Number of seconds to sleep between checks.
|
||||
default: 5
|
||||
type: int
|
||||
wait_timeout:
|
||||
description:
|
||||
- How long in seconds to wait for the resource to end up in the desired state. Ignored if C(wait) is not set.
|
||||
default: 120
|
||||
type: int
|
||||
wait_condition:
|
||||
description:
|
||||
- Specifies a custom condition on the status to wait for. Ignored if C(wait) is not set or is set to False.
|
||||
suboptions:
|
||||
type:
|
||||
type: str
|
||||
description:
|
||||
- The type of condition to wait for. For example, the C(Pod) resource will set the C(Ready) condition (among others)
|
||||
- Required if you are specifying a C(wait_condition). If left empty, the C(wait_condition) field will be ignored.
|
||||
- The possible types for a condition are specific to each resource type in Kubernetes. See the API documentation of the status field
|
||||
for a given resource to see possible choices.
|
||||
status:
|
||||
type: str
|
||||
description:
|
||||
- The value of the status field in your desired condition.
|
||||
- For example, if a C(Deployment) is paused, the C(Progressing) C(type) will have the C(Unknown) status.
|
||||
choices:
|
||||
- True
|
||||
- False
|
||||
- Unknown
|
||||
default: "True"
|
||||
reason:
|
||||
type: str
|
||||
description:
|
||||
- The value of the reason field in your desired condition
|
||||
- For example, if a C(Deployment) is paused, The C(Progressing) C(type) will have the C(DeploymentPaused) reason.
|
||||
- The possible reasons in a condition are specific to each resource type in Kubernetes. See the API documentation of the status field
|
||||
for a given resource to see possible choices.
|
||||
type: dict
|
||||
validate:
|
||||
description:
|
||||
- how (if at all) to validate the resource definition against the kubernetes schema.
|
||||
Requires the kubernetes-validate python module
|
||||
suboptions:
|
||||
fail_on_error:
|
||||
description: whether to fail on validation errors.
|
||||
type: bool
|
||||
version:
|
||||
description: version of Kubernetes to validate against. defaults to Kubernetes server version
|
||||
type: str
|
||||
strict:
|
||||
description: whether to fail when passing unexpected properties
|
||||
default: True
|
||||
type: bool
|
||||
type: dict
|
||||
append_hash:
|
||||
description:
|
||||
- Whether to append a hash to a resource name for immutability purposes
|
||||
- Applies only to ConfigMap and Secret resources
|
||||
- The parameter will be silently ignored for other resource kinds
|
||||
- The full definition of an object is needed to generate the hash - this means that deleting an object created with append_hash
|
||||
will only work if the same object is passed with state=absent (alternatively, just use state=absent with the name including
|
||||
the generated hash and append_hash=no)
|
||||
type: bool
|
||||
apply:
|
||||
description:
|
||||
- C(apply) compares the desired resource definition with the previously supplied resource definition,
|
||||
ignoring properties that are automatically generated
|
||||
- C(apply) works better with Services than 'force=yes'
|
||||
- mutually exclusive with C(merge_type)
|
||||
type: bool
|
||||
|
||||
requirements:
|
||||
- "python >= 2.7"
|
||||
- "openshift >= 0.6"
|
||||
- "PyYAML >= 3.11"
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create a k8s namespace
|
||||
community.okd.k8s:
|
||||
name: testing
|
||||
api_version: v1
|
||||
kind: Namespace
|
||||
state: present
|
||||
|
||||
- name: Create a Service object from an inline definition
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web
|
||||
namespace: testing
|
||||
labels:
|
||||
app: galaxy
|
||||
service: web
|
||||
spec:
|
||||
selector:
|
||||
app: galaxy
|
||||
service: web
|
||||
ports:
|
||||
- protocol: TCP
|
||||
targetPort: 8000
|
||||
name: port-8000-tcp
|
||||
port: 8000
|
||||
|
||||
- name: Remove an existing Service object
|
||||
community.okd.k8s:
|
||||
state: absent
|
||||
api_version: v1
|
||||
kind: Service
|
||||
namespace: testing
|
||||
name: web
|
||||
|
||||
# Passing the object definition from a file
|
||||
|
||||
- name: Create a Deployment by reading the definition from a local file
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
src: /testing/deployment.yml
|
||||
|
||||
- name: >-
|
||||
Read definition file from the Ansible controller file system.
|
||||
If the definition file has been encrypted with Ansible Vault it will automatically be decrypted.
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
definition: "{{ lookup('file', '/testing/deployment.yml') | from_yaml }}"
|
||||
|
||||
- name: Read definition file from the Ansible controller file system after Jinja templating
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
definition: "{{ lookup('template', '/testing/deployment.yml') | from_yaml }}"
|
||||
|
||||
- name: fail on validation errors
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
definition: "{{ lookup('template', '/testing/deployment.yml') | from_yaml }}"
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
|
||||
- name: warn on validation errors, check for unexpected properties
|
||||
community.okd.k8s:
|
||||
state: present
|
||||
definition: "{{ lookup('template', '/testing/deployment.yml') | from_yaml }}"
|
||||
validate:
|
||||
fail_on_error: no
|
||||
strict: yes
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
result:
|
||||
description:
|
||||
- The created, patched, or otherwise present object. Will be empty in the case of a deletion.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
api_version:
|
||||
description: The versioned schema of this representation of an object.
|
||||
returned: success
|
||||
type: str
|
||||
kind:
|
||||
description: Represents the REST resource this object represents.
|
||||
returned: success
|
||||
type: str
|
||||
metadata:
|
||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
||||
returned: success
|
||||
type: complex
|
||||
spec:
|
||||
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
|
||||
returned: success
|
||||
type: complex
|
||||
status:
|
||||
description: Current status details for the object.
|
||||
returned: success
|
||||
type: complex
|
||||
items:
|
||||
description: Returned only when multiple yaml documents are passed to src or resource_definition
|
||||
returned: when resource_definition or src contains list of objects
|
||||
type: list
|
||||
duration:
|
||||
description: elapsed time of task in seconds
|
||||
returned: when C(wait) is true
|
||||
type: int
|
||||
sample: 48
|
||||
'''
|
||||
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.raw import KubernetesRawModule
|
||||
HAS_KUBERNETES_COLLECTION = True
|
||||
except ImportError as e:
|
||||
HAS_KUBERNETES_COLLECTION = False
|
||||
k8s_collection_import_exception = e
|
||||
K8S_COLLECTION_ERROR = traceback.format_exc()
|
||||
from ansible.module_utils.basic import AnsibleModule as KubernetesRawModule
|
||||
|
||||
try:
|
||||
from openshift.dynamic.exceptions import DynamicApiError, NotFoundError, ForbiddenError
|
||||
except ImportError:
|
||||
# Exceptions handled in common
|
||||
pass
|
||||
|
||||
|
||||
class OKDRawModule(KubernetesRawModule):
|
||||
|
||||
def __init__(self):
|
||||
if not HAS_KUBERNETES_COLLECTION:
|
||||
self.fail_json(
|
||||
msg="The community.kubernetes collection must be installed",
|
||||
exception=K8S_COLLECTION_ERROR,
|
||||
error=to_native(k8s_collection_import_exception)
|
||||
)
|
||||
super(OKDRawModule, self).__init__()
|
||||
|
||||
def perform_action(self, resource, definition):
|
||||
state = self.params.get('state', None)
|
||||
name = definition['metadata'].get('name')
|
||||
namespace = definition['metadata'].get('namespace')
|
||||
|
||||
if definition['kind'] in ['Project', 'ProjectRequest'] and state != 'absent':
|
||||
try:
|
||||
resource.get(name, namespace)
|
||||
except (NotFoundError, ForbiddenError):
|
||||
return self.create_project_request(definition)
|
||||
except DynamicApiError as exc:
|
||||
self.fail_json(msg='Failed to retrieve requested object: {0}'.format(exc.body),
|
||||
error=exc.status, status=exc.status, reason=exc.reason)
|
||||
|
||||
return super(OKDRawModule, self).perform_action(resource, definition)
|
||||
|
||||
def create_project_request(self, definition):
|
||||
definition['kind'] = 'ProjectRequest'
|
||||
result = {'changed': False, 'result': {}}
|
||||
resource = self.find_resource('ProjectRequest', definition['apiVersion'], fail=True)
|
||||
if not self.check_mode:
|
||||
try:
|
||||
k8s_obj = resource.create(definition)
|
||||
result['result'] = k8s_obj.to_dict()
|
||||
except DynamicApiError as exc:
|
||||
self.fail_json(msg="Failed to create object: {0}".format(exc.body),
|
||||
error=exc.status, status=exc.status, reason=exc.reason)
|
||||
result['changed'] = True
|
||||
result['method'] = 'create'
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
OKDRawModule().execute_module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,2 +0,0 @@
|
||||
---
|
||||
k8s_openshift: true
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: delete temporary directory
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
no_log: yes
|
||||
@@ -1,3 +0,0 @@
|
||||
# README
|
||||
|
||||
The `test_tempfile.py` module added here is only used for the `setup_remote_tmp_dir.yml` temporary directory setup task. It is a clone of the `tempfile.py` community-supported Ansible module, and has to be included with the tests here because it is not available in the `ansible-base` distribution against which this collection is tested.
|
||||
@@ -1,121 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2016, Krzysztof Magosa <krzysztof@magosa.pl>
|
||||
# Copyright: (c) 2017, Ansible Project
|
||||
# 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 = '''
|
||||
---
|
||||
module: test_tempfile
|
||||
|
||||
short_description: Creates temporary files and directories
|
||||
|
||||
description:
|
||||
- The C(test_tempfile) module creates temporary files and directories. C(mktemp) command takes different parameters on various systems, this module helps
|
||||
to avoid troubles related to that. Files/directories created by module are accessible only by creator. In case you need to make them world-accessible
|
||||
you need to use M(ansible.builtin.file) module.
|
||||
- For Windows targets, use the M(ansible.builtin.win_tempfile) module instead.
|
||||
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Whether to create file or directory.
|
||||
type: str
|
||||
choices: [ directory, file ]
|
||||
default: file
|
||||
path:
|
||||
description:
|
||||
- Location where temporary file or directory should be created.
|
||||
- If path is not specified, the default system temporary directory will be used.
|
||||
type: path
|
||||
prefix:
|
||||
description:
|
||||
- Prefix of file/directory name created by module.
|
||||
type: str
|
||||
default: ansible.
|
||||
suffix:
|
||||
description:
|
||||
- Suffix of file/directory name created by module.
|
||||
type: str
|
||||
default: ""
|
||||
|
||||
seealso:
|
||||
- module: file
|
||||
- module: win_tempfile
|
||||
|
||||
author:
|
||||
- Krzysztof Magosa (@krzysztof-magosa)
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: create temporary build directory
|
||||
test_tempfile:
|
||||
state: directory
|
||||
suffix: build
|
||||
|
||||
- name: create temporary file
|
||||
test_tempfile:
|
||||
state: file
|
||||
suffix: temp
|
||||
register: tempfile_1
|
||||
|
||||
- name: use the registered var and the file module to remove the temporary file
|
||||
file:
|
||||
path: "{{ tempfile_1.path }}"
|
||||
state: absent
|
||||
when: tempfile_1.path is defined
|
||||
"""
|
||||
|
||||
RETURN = '''
|
||||
path:
|
||||
description: Path to created file or directory
|
||||
returned: success
|
||||
type: str
|
||||
sample: "/tmp/ansible.bMlvdk"
|
||||
'''
|
||||
|
||||
from os import close
|
||||
from tempfile import mkstemp, mkdtemp
|
||||
from traceback import format_exc
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type='str', default='file', choices=['file', 'directory']),
|
||||
path=dict(type='path'),
|
||||
prefix=dict(type='str', default='ansible.'),
|
||||
suffix=dict(type='str', default=''),
|
||||
),
|
||||
)
|
||||
|
||||
try:
|
||||
if module.params['state'] == 'file':
|
||||
handle, path = mkstemp(
|
||||
prefix=module.params['prefix'],
|
||||
suffix=module.params['suffix'],
|
||||
dir=module.params['path'],
|
||||
)
|
||||
close(handle)
|
||||
elif module.params['state'] == 'directory':
|
||||
path = mkdtemp(
|
||||
prefix=module.params['prefix'],
|
||||
suffix=module.params['suffix'],
|
||||
dir=module.params['path'],
|
||||
)
|
||||
|
||||
module.exit_json(changed=True, path=path)
|
||||
except Exception as e:
|
||||
module.fail_json(msg=to_native(e), exception=format_exc())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,2 +0,0 @@
|
||||
---
|
||||
dependencies: []
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
- include_tasks: setup_remote_tmp_dir.yml
|
||||
|
||||
- set_fact:
|
||||
virtualenv: "{{ remote_tmp_dir }}/virtualenv"
|
||||
virtualenv_command: "{{ ansible_python_interpreter }} -m virtualenv"
|
||||
|
||||
- set_fact:
|
||||
virtualenv_interpreter: "{{ virtualenv }}/bin/python"
|
||||
|
||||
- pip:
|
||||
name: virtualenv
|
||||
|
||||
# Test graceful failure for older versions of openshift
|
||||
|
||||
- pip:
|
||||
name:
|
||||
- openshift==0.6.0
|
||||
- kubernetes==6.0.0
|
||||
- coverage
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
virtualenv_command: "{{ virtualenv_command }}"
|
||||
virtualenv_site_packages: no
|
||||
|
||||
- include_tasks: older_openshift_fail.yml
|
||||
vars:
|
||||
ansible_python_interpreter: "{{ virtualenv_interpreter }}"
|
||||
playbook_namespace: ansible-test-k8s-older-openshift
|
||||
|
||||
- file:
|
||||
path: "{{ virtualenv }}"
|
||||
state: absent
|
||||
no_log: yes
|
||||
|
||||
# Test openshift
|
||||
|
||||
- debug:
|
||||
var: k8s_openshift
|
||||
|
||||
- pip:
|
||||
name:
|
||||
- kubernetes-validate==1.12.0
|
||||
- openshift>=0.9.2
|
||||
- coverage
|
||||
virtualenv: "{{ virtualenv }}"
|
||||
virtualenv_command: "{{ virtualenv_command }}"
|
||||
virtualenv_site_packages: no
|
||||
|
||||
- include: openshift.yml
|
||||
when: k8s_openshift | bool
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
# TODO: Not available in ansible-base
|
||||
# - python_requirements_info:
|
||||
# dependencies:
|
||||
# - openshift==0.6.0
|
||||
# - kubernetes==6.0.0
|
||||
|
||||
# append_hash
|
||||
- name: use append_hash with ConfigMap
|
||||
community.kubernetes.k8s:
|
||||
definition:
|
||||
metadata:
|
||||
name: config-map-test
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
data:
|
||||
hello: world
|
||||
append_hash: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_append_hash
|
||||
|
||||
- name: assert that append_hash fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_append_hash is failed
|
||||
- "'Failed to import the required Python library (openshift >= 0.7.2)' in k8s_append_hash.msg"
|
||||
- "'. This is required for append_hash.' in k8s_append_hash.msg"
|
||||
|
||||
# validate
|
||||
- name: attempt to use validate with older openshift
|
||||
community.kubernetes.k8s:
|
||||
definition:
|
||||
metadata:
|
||||
name: config-map-test
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
data:
|
||||
hello: world
|
||||
validate:
|
||||
fail_on_error: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_validate
|
||||
|
||||
- name: assert that validate fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_validate is failed
|
||||
- "k8s_validate.msg == 'openshift >= 0.8.0 is required for validate'"
|
||||
|
||||
# apply
|
||||
- name: attempt to use apply with older openshift
|
||||
community.kubernetes.k8s:
|
||||
definition:
|
||||
metadata:
|
||||
name: config-map-test
|
||||
namespace: "{{ playbook_namespace }}"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
data:
|
||||
hello: world
|
||||
apply: yes
|
||||
ignore_errors: yes
|
||||
register: k8s_apply
|
||||
|
||||
- name: assert that apply fails gracefully
|
||||
assert:
|
||||
that:
|
||||
- k8s_apply is failed
|
||||
- "k8s_apply.msg.startswith('Failed to import the required Python library (openshift >= 0.9.2)')"
|
||||
@@ -1,62 +0,0 @@
|
||||
---
|
||||
# OpenShift Resources
|
||||
- name: Create a project
|
||||
community.kubernetes.k8s:
|
||||
name: testing
|
||||
kind: Project
|
||||
api_version: v1
|
||||
apply: no
|
||||
register: output
|
||||
|
||||
- name: show output
|
||||
debug:
|
||||
var: output
|
||||
|
||||
- name: Create deployment config
|
||||
community.kubernetes.k8s:
|
||||
state: present
|
||||
inline: &dc
|
||||
apiVersion: v1
|
||||
kind: DeploymentConfig
|
||||
metadata:
|
||||
name: elastic
|
||||
labels:
|
||||
app: galaxy
|
||||
service: elastic
|
||||
namespace: testing
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: galaxy
|
||||
service: elastic
|
||||
spec:
|
||||
containers:
|
||||
- name: elastic
|
||||
volumeMounts:
|
||||
- mountPath: /usr/share/elasticsearch/data
|
||||
name: elastic-volume
|
||||
command: ['elasticsearch']
|
||||
image: 'ansible/galaxy-elasticsearch:2.4.6'
|
||||
volumes:
|
||||
- name: elastic-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: elastic-volume
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Rolling
|
||||
register: output
|
||||
|
||||
- name: Show output
|
||||
debug:
|
||||
var: output
|
||||
|
||||
- name: Create deployment config again
|
||||
community.kubernetes.k8s:
|
||||
state: present
|
||||
inline: *dc
|
||||
register: output
|
||||
|
||||
- name: DC creation should be idempotent
|
||||
assert:
|
||||
that: not output.changed
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
- name: create temporary directory
|
||||
test_tempfile:
|
||||
state: directory
|
||||
suffix: .test
|
||||
register: remote_tmp_dir
|
||||
notify:
|
||||
- delete temporary directory
|
||||
|
||||
- name: record temporary directory
|
||||
set_fact:
|
||||
remote_tmp_dir: "{{ remote_tmp_dir.path }}"
|
||||
2
tests/sanity/ignore-2.10.txt
Normal file
2
tests/sanity/ignore-2.10.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
2
tests/sanity/ignore-2.11.txt
Normal file
2
tests/sanity/ignore-2.11.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
1
tests/sanity/ignore-2.9.txt
Normal file
1
tests/sanity/ignore-2.9.txt
Normal file
@@ -0,0 +1 @@
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
Reference in New Issue
Block a user