mirror of
https://github.com/openshift/community.okd.git
synced 2026-05-07 21:52:37 +00:00
* Upgrade Ansible and OKD versions for CI * Use ubi9 and fix sanity * Use correct pip install * Try using quotes * Ensure python3.9 * Upgrade ansible and molecule versions * Remove DeploymentConfig DeploymentConfigs are deprecated and seem to now be causing idempotence problems. Replacing them with Deployments fixes it. * Attempt to fix ldap integration tests Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Move sanity and unit tests to GH actions Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Firt round of sanity fixes Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add kubernetes.core collection as sanity requirement Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add ignore-2.16.txt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Attempt to fix units Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add ignore-2.17 Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Attempt to fix unit tests Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add pytest-ansible to test-requirements.txt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add changelog fragment Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add workflow for ansible-lint Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Apply black Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Fix linters Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Add # fmt: skip Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Yet another round of linting Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Yet another round of linting Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Remove setup.cfg Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Revert #fmt Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Use ansible-core 2.14 Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Cleanup ansible-lint ignores Signed-off-by: Alina Buzachis <abuzachis@redhat.com> * Try using service instead of pod IP * Fix typo * Actually use the correct port * See if NetworkPolicy is preventing connection * using Pod internal IP * fix adm prune auth roles syntax * adding some retry steps * fix: openshift_builds target * add flag --force-with-deps when building downstream collection * Remove yamllint from tox linters, bump minimum python supported version to 3.9, Remove support for ansible-core < 2.14 --------- Signed-off-by: Alina Buzachis <abuzachis@redhat.com> Co-authored-by: Mike Graves <mgraves@redhat.com> Co-authored-by: Alina Buzachis <abuzachis@redhat.com>
This commit is contained in:
@@ -9,7 +9,7 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
# STARTREMOVE (downstream)
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
module: openshift_route
|
||||
|
||||
short_description: Expose a Service as an OpenShift Route.
|
||||
@@ -133,9 +133,9 @@ options:
|
||||
- insecure
|
||||
default: insecure
|
||||
type: str
|
||||
'''
|
||||
"""
|
||||
|
||||
EXAMPLES = r'''
|
||||
EXAMPLES = r"""
|
||||
- name: Create hello-world deployment
|
||||
community.okd.k8s:
|
||||
definition:
|
||||
@@ -155,10 +155,10 @@ EXAMPLES = r'''
|
||||
app: hello-kubernetes
|
||||
spec:
|
||||
containers:
|
||||
- name: hello-kubernetes
|
||||
image: paulbouwer/hello-kubernetes:1.8
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
- name: hello-kubernetes
|
||||
image: paulbouwer/hello-kubernetes:1.8
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
- name: Create Service for the hello-world deployment
|
||||
community.okd.k8s:
|
||||
@@ -170,8 +170,8 @@ EXAMPLES = r'''
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: hello-kubernetes
|
||||
|
||||
@@ -183,9 +183,9 @@ EXAMPLES = r'''
|
||||
annotations:
|
||||
haproxy.router.openshift.io/balance: roundrobin
|
||||
register: route
|
||||
'''
|
||||
"""
|
||||
|
||||
RETURN = r'''
|
||||
RETURN = r"""
|
||||
result:
|
||||
description:
|
||||
- The Route object that was created or updated. Will be empty in the case of deletion.
|
||||
@@ -303,20 +303,28 @@ duration:
|
||||
returned: when C(wait) is true
|
||||
type: int
|
||||
sample: 48
|
||||
'''
|
||||
"""
|
||||
# ENDREMOVE (downstream)
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
|
||||
from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
|
||||
AnsibleOpenshiftModule,
|
||||
)
|
||||
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import perform_action
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import Waiter
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import (
|
||||
perform_action,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
Waiter,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, WAIT_ARG_SPEC, COMMON_ARG_SPEC
|
||||
AUTH_ARG_SPEC,
|
||||
WAIT_ARG_SPEC,
|
||||
COMMON_ARG_SPEC,
|
||||
)
|
||||
except ImportError as e:
|
||||
pass
|
||||
@@ -329,7 +337,6 @@ except ImportError:
|
||||
|
||||
|
||||
class OpenShiftRoute(AnsibleOpenshiftModule):
|
||||
|
||||
def __init__(self):
|
||||
super(OpenShiftRoute, self).__init__(
|
||||
argument_spec=self.argspec,
|
||||
@@ -339,7 +346,7 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
|
||||
self.append_hash = False
|
||||
self.apply = False
|
||||
self.warnings = []
|
||||
self.params['merge_type'] = None
|
||||
self.params["merge_type"] = None
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
@@ -347,80 +354,95 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
|
||||
spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||
spec.update(copy.deepcopy(COMMON_ARG_SPEC))
|
||||
|
||||
spec['service'] = dict(type='str', aliases=['svc'])
|
||||
spec['namespace'] = dict(required=True, type='str')
|
||||
spec['labels'] = dict(type='dict')
|
||||
spec['name'] = dict(type='str')
|
||||
spec['hostname'] = dict(type='str')
|
||||
spec['path'] = dict(type='str')
|
||||
spec['wildcard_policy'] = dict(choices=['Subdomain'], type='str')
|
||||
spec['port'] = dict(type='str')
|
||||
spec['tls'] = dict(type='dict', options=dict(
|
||||
ca_certificate=dict(type='str'),
|
||||
certificate=dict(type='str'),
|
||||
destination_ca_certificate=dict(type='str'),
|
||||
key=dict(type='str', no_log=False),
|
||||
insecure_policy=dict(type='str', choices=['allow', 'redirect', 'disallow'], default='disallow'),
|
||||
))
|
||||
spec['termination'] = dict(choices=['edge', 'passthrough', 'reencrypt', 'insecure'], default='insecure')
|
||||
spec['annotations'] = dict(type='dict')
|
||||
spec["service"] = dict(type="str", aliases=["svc"])
|
||||
spec["namespace"] = dict(required=True, type="str")
|
||||
spec["labels"] = dict(type="dict")
|
||||
spec["name"] = dict(type="str")
|
||||
spec["hostname"] = dict(type="str")
|
||||
spec["path"] = dict(type="str")
|
||||
spec["wildcard_policy"] = dict(choices=["Subdomain"], type="str")
|
||||
spec["port"] = dict(type="str")
|
||||
spec["tls"] = dict(
|
||||
type="dict",
|
||||
options=dict(
|
||||
ca_certificate=dict(type="str"),
|
||||
certificate=dict(type="str"),
|
||||
destination_ca_certificate=dict(type="str"),
|
||||
key=dict(type="str", no_log=False),
|
||||
insecure_policy=dict(
|
||||
type="str",
|
||||
choices=["allow", "redirect", "disallow"],
|
||||
default="disallow",
|
||||
),
|
||||
),
|
||||
)
|
||||
spec["termination"] = dict(
|
||||
choices=["edge", "passthrough", "reencrypt", "insecure"], default="insecure"
|
||||
)
|
||||
spec["annotations"] = dict(type="dict")
|
||||
|
||||
return spec
|
||||
|
||||
def execute_module(self):
|
||||
|
||||
service_name = self.params.get('service')
|
||||
namespace = self.params['namespace']
|
||||
termination_type = self.params.get('termination')
|
||||
if termination_type == 'insecure':
|
||||
service_name = self.params.get("service")
|
||||
namespace = self.params["namespace"]
|
||||
termination_type = self.params.get("termination")
|
||||
if termination_type == "insecure":
|
||||
termination_type = None
|
||||
state = self.params.get('state')
|
||||
state = self.params.get("state")
|
||||
|
||||
if state != 'absent' and not service_name:
|
||||
if state != "absent" and not service_name:
|
||||
self.fail_json("If 'state' is not 'absent' then 'service' must be provided")
|
||||
|
||||
# We need to do something a little wonky to wait if the user doesn't supply a custom condition
|
||||
custom_wait = self.params.get('wait') and not self.params.get('wait_condition') and state != 'absent'
|
||||
custom_wait = (
|
||||
self.params.get("wait")
|
||||
and not self.params.get("wait_condition")
|
||||
and state != "absent"
|
||||
)
|
||||
if custom_wait:
|
||||
# Don't use default wait logic in perform_action
|
||||
self.params['wait'] = False
|
||||
self.params["wait"] = False
|
||||
|
||||
route_name = self.params.get('name') or service_name
|
||||
labels = self.params.get('labels')
|
||||
hostname = self.params.get('hostname')
|
||||
path = self.params.get('path')
|
||||
wildcard_policy = self.params.get('wildcard_policy')
|
||||
port = self.params.get('port')
|
||||
annotations = self.params.get('annotations')
|
||||
route_name = self.params.get("name") or service_name
|
||||
labels = self.params.get("labels")
|
||||
hostname = self.params.get("hostname")
|
||||
path = self.params.get("path")
|
||||
wildcard_policy = self.params.get("wildcard_policy")
|
||||
port = self.params.get("port")
|
||||
annotations = self.params.get("annotations")
|
||||
|
||||
if termination_type and self.params.get('tls'):
|
||||
tls_ca_cert = self.params['tls'].get('ca_certificate')
|
||||
tls_cert = self.params['tls'].get('certificate')
|
||||
tls_dest_ca_cert = self.params['tls'].get('destination_ca_certificate')
|
||||
tls_key = self.params['tls'].get('key')
|
||||
tls_insecure_policy = self.params['tls'].get('insecure_policy')
|
||||
if tls_insecure_policy == 'disallow':
|
||||
if termination_type and self.params.get("tls"):
|
||||
tls_ca_cert = self.params["tls"].get("ca_certificate")
|
||||
tls_cert = self.params["tls"].get("certificate")
|
||||
tls_dest_ca_cert = self.params["tls"].get("destination_ca_certificate")
|
||||
tls_key = self.params["tls"].get("key")
|
||||
tls_insecure_policy = self.params["tls"].get("insecure_policy")
|
||||
if tls_insecure_policy == "disallow":
|
||||
tls_insecure_policy = None
|
||||
else:
|
||||
tls_ca_cert = tls_cert = tls_dest_ca_cert = tls_key = tls_insecure_policy = None
|
||||
tls_ca_cert = (
|
||||
tls_cert
|
||||
) = tls_dest_ca_cert = tls_key = tls_insecure_policy = None
|
||||
|
||||
route = {
|
||||
'apiVersion': 'route.openshift.io/v1',
|
||||
'kind': 'Route',
|
||||
'metadata': {
|
||||
'name': route_name,
|
||||
'namespace': namespace,
|
||||
'labels': labels,
|
||||
"apiVersion": "route.openshift.io/v1",
|
||||
"kind": "Route",
|
||||
"metadata": {
|
||||
"name": route_name,
|
||||
"namespace": namespace,
|
||||
"labels": labels,
|
||||
},
|
||||
'spec': {}
|
||||
"spec": {},
|
||||
}
|
||||
|
||||
if annotations:
|
||||
route['metadata']['annotations'] = annotations
|
||||
route["metadata"]["annotations"] = annotations
|
||||
|
||||
if state != 'absent':
|
||||
route['spec'] = self.build_route_spec(
|
||||
service_name, namespace,
|
||||
if state != "absent":
|
||||
route["spec"] = self.build_route_spec(
|
||||
service_name,
|
||||
namespace,
|
||||
port=port,
|
||||
wildcard_policy=wildcard_policy,
|
||||
hostname=hostname,
|
||||
@@ -434,79 +456,120 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
|
||||
)
|
||||
|
||||
result = perform_action(self.svc, route, self.params)
|
||||
timeout = self.params.get('wait_timeout')
|
||||
sleep = self.params.get('wait_sleep')
|
||||
timeout = self.params.get("wait_timeout")
|
||||
sleep = self.params.get("wait_sleep")
|
||||
if custom_wait:
|
||||
v1_routes = self.find_resource('Route', 'route.openshift.io/v1', fail=True)
|
||||
v1_routes = self.find_resource("Route", "route.openshift.io/v1", fail=True)
|
||||
waiter = Waiter(self.client, v1_routes, wait_predicate)
|
||||
success, result['result'], result['duration'] = waiter.wait(timeout=timeout, sleep=sleep, name=route_name, namespace=namespace)
|
||||
success, result["result"], result["duration"] = waiter.wait(
|
||||
timeout=timeout, sleep=sleep, name=route_name, namespace=namespace
|
||||
)
|
||||
|
||||
self.exit_json(**result)
|
||||
|
||||
def build_route_spec(self, service_name, namespace, port=None, wildcard_policy=None, hostname=None, path=None, termination_type=None,
|
||||
tls_insecure_policy=None, tls_ca_cert=None, tls_cert=None, tls_key=None, tls_dest_ca_cert=None):
|
||||
v1_services = self.find_resource('Service', 'v1', fail=True)
|
||||
def build_route_spec(
|
||||
self,
|
||||
service_name,
|
||||
namespace,
|
||||
port=None,
|
||||
wildcard_policy=None,
|
||||
hostname=None,
|
||||
path=None,
|
||||
termination_type=None,
|
||||
tls_insecure_policy=None,
|
||||
tls_ca_cert=None,
|
||||
tls_cert=None,
|
||||
tls_key=None,
|
||||
tls_dest_ca_cert=None,
|
||||
):
|
||||
v1_services = self.find_resource("Service", "v1", fail=True)
|
||||
try:
|
||||
target_service = v1_services.get(name=service_name, namespace=namespace)
|
||||
except NotFoundError:
|
||||
if not port:
|
||||
self.fail_json(msg="You need to provide the 'port' argument when exposing a non-existent service")
|
||||
self.fail_json(
|
||||
msg="You need to provide the 'port' argument when exposing a non-existent service"
|
||||
)
|
||||
target_service = None
|
||||
except DynamicApiError as exc:
|
||||
self.fail_json(msg='Failed to retrieve service to be exposed: {0}'.format(exc.body),
|
||||
error=exc.status, status=exc.status, reason=exc.reason)
|
||||
self.fail_json(
|
||||
msg="Failed to retrieve service to be exposed: {0}".format(exc.body),
|
||||
error=exc.status,
|
||||
status=exc.status,
|
||||
reason=exc.reason,
|
||||
)
|
||||
except Exception as exc:
|
||||
self.fail_json(msg='Failed to retrieve service to be exposed: {0}'.format(to_native(exc)),
|
||||
error='', status='', reason='')
|
||||
self.fail_json(
|
||||
msg="Failed to retrieve service to be exposed: {0}".format(
|
||||
to_native(exc)
|
||||
),
|
||||
error="",
|
||||
status="",
|
||||
reason="",
|
||||
)
|
||||
|
||||
route_spec = {
|
||||
'tls': {},
|
||||
'to': {
|
||||
'kind': 'Service',
|
||||
'name': service_name,
|
||||
"tls": {},
|
||||
"to": {
|
||||
"kind": "Service",
|
||||
"name": service_name,
|
||||
},
|
||||
'port': {
|
||||
'targetPort': self.set_port(target_service, port),
|
||||
"port": {
|
||||
"targetPort": self.set_port(target_service, port),
|
||||
},
|
||||
'wildcardPolicy': wildcard_policy
|
||||
"wildcardPolicy": wildcard_policy,
|
||||
}
|
||||
|
||||
# Want to conditionally add these so we don't overwrite what is automically added when nothing is provided
|
||||
if termination_type:
|
||||
route_spec['tls'] = dict(termination=termination_type.capitalize())
|
||||
route_spec["tls"] = dict(termination=termination_type.capitalize())
|
||||
if tls_insecure_policy:
|
||||
if termination_type == 'edge':
|
||||
route_spec['tls']['insecureEdgeTerminationPolicy'] = tls_insecure_policy.capitalize()
|
||||
elif termination_type == 'passthrough':
|
||||
if tls_insecure_policy != 'redirect':
|
||||
self.fail_json("'redirect' is the only supported insecureEdgeTerminationPolicy for passthrough routes")
|
||||
route_spec['tls']['insecureEdgeTerminationPolicy'] = tls_insecure_policy.capitalize()
|
||||
elif termination_type == 'reencrypt':
|
||||
self.fail_json("'tls.insecure_policy' is not supported with reencrypt routes")
|
||||
if termination_type == "edge":
|
||||
route_spec["tls"][
|
||||
"insecureEdgeTerminationPolicy"
|
||||
] = tls_insecure_policy.capitalize()
|
||||
elif termination_type == "passthrough":
|
||||
if tls_insecure_policy != "redirect":
|
||||
self.fail_json(
|
||||
"'redirect' is the only supported insecureEdgeTerminationPolicy for passthrough routes"
|
||||
)
|
||||
route_spec["tls"][
|
||||
"insecureEdgeTerminationPolicy"
|
||||
] = tls_insecure_policy.capitalize()
|
||||
elif termination_type == "reencrypt":
|
||||
self.fail_json(
|
||||
"'tls.insecure_policy' is not supported with reencrypt routes"
|
||||
)
|
||||
else:
|
||||
route_spec['tls']['insecureEdgeTerminationPolicy'] = None
|
||||
route_spec["tls"]["insecureEdgeTerminationPolicy"] = None
|
||||
if tls_ca_cert:
|
||||
if termination_type == 'passthrough':
|
||||
self.fail_json("'tls.ca_certificate' is not supported with passthrough routes")
|
||||
route_spec['tls']['caCertificate'] = tls_ca_cert
|
||||
if termination_type == "passthrough":
|
||||
self.fail_json(
|
||||
"'tls.ca_certificate' is not supported with passthrough routes"
|
||||
)
|
||||
route_spec["tls"]["caCertificate"] = tls_ca_cert
|
||||
if tls_cert:
|
||||
if termination_type == 'passthrough':
|
||||
self.fail_json("'tls.certificate' is not supported with passthrough routes")
|
||||
route_spec['tls']['certificate'] = tls_cert
|
||||
if termination_type == "passthrough":
|
||||
self.fail_json(
|
||||
"'tls.certificate' is not supported with passthrough routes"
|
||||
)
|
||||
route_spec["tls"]["certificate"] = tls_cert
|
||||
if tls_key:
|
||||
if termination_type == 'passthrough':
|
||||
if termination_type == "passthrough":
|
||||
self.fail_json("'tls.key' is not supported with passthrough routes")
|
||||
route_spec['tls']['key'] = tls_key
|
||||
route_spec["tls"]["key"] = tls_key
|
||||
if tls_dest_ca_cert:
|
||||
if termination_type != 'reencrypt':
|
||||
self.fail_json("'destination_certificate' is only valid for reencrypt routes")
|
||||
route_spec['tls']['destinationCACertificate'] = tls_dest_ca_cert
|
||||
if termination_type != "reencrypt":
|
||||
self.fail_json(
|
||||
"'destination_certificate' is only valid for reencrypt routes"
|
||||
)
|
||||
route_spec["tls"]["destinationCACertificate"] = tls_dest_ca_cert
|
||||
else:
|
||||
route_spec['tls'] = None
|
||||
route_spec["tls"] = None
|
||||
if hostname:
|
||||
route_spec['host'] = hostname
|
||||
route_spec["host"] = hostname
|
||||
if path:
|
||||
route_spec['path'] = path
|
||||
route_spec["path"] = path
|
||||
|
||||
return route_spec
|
||||
|
||||
@@ -514,7 +577,7 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
|
||||
if port_arg:
|
||||
return port_arg
|
||||
for p in service.spec.ports:
|
||||
if p.protocol == 'TCP':
|
||||
if p.protocol == "TCP":
|
||||
if p.name is not None:
|
||||
return p.name
|
||||
return p.targetPort
|
||||
@@ -525,7 +588,7 @@ def wait_predicate(route):
|
||||
if not (route.status and route.status.ingress):
|
||||
return False
|
||||
for ingress in route.status.ingress:
|
||||
match = [x for x in ingress.conditions if x.type == 'Admitted']
|
||||
match = [x for x in ingress.conditions if x.type == "Admitted"]
|
||||
if not match:
|
||||
return False
|
||||
match = match[0]
|
||||
@@ -538,5 +601,5 @@ def main():
|
||||
OpenShiftRoute().run_module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user