mirror of
https://github.com/openshift/community.okd.git
synced 2026-03-26 19:03:14 +00:00
Add openshift_route module for route creation (#40)
* first draft of interface * Add basic implementation * Add validation * rename to openshift_route and add some test tasks * Fix sanity checks * Add checks for missing dependencies * Add port processing like the oc command * Add real tests * Fix waiting * add some more waiting to test * add state parameters and fix RETURN docs * try to fix odd sanity issue * import tests passing * Fix all sanity tests * Do less work when state is absent, and add explicit removal values * insecure_policy disable -> disallow * add proper default for insecure_policy
This commit is contained in:
committed by
GitHub
parent
6942cd6756
commit
e7c3351309
240
molecule/default/tasks/openshift_route.yml
Normal file
240
molecule/default/tasks/openshift_route.yml
Normal file
@@ -0,0 +1,240 @@
|
||||
---
|
||||
- name: Create Deployment
|
||||
community.okd.k8s:
|
||||
wait: yes
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hello-kubernetes
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hello-kubernetes
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hello-kubernetes
|
||||
spec:
|
||||
containers:
|
||||
- name: hello-kubernetes
|
||||
image: docker.io/openshift/hello-openshift
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
- name: Create Service
|
||||
community.okd.k8s:
|
||||
wait: yes
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hello-kubernetes
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: hello-kubernetes
|
||||
|
||||
- name: Create Route with fewest possible arguments
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
register: route
|
||||
|
||||
- name: Attempt to hit http URL
|
||||
uri:
|
||||
url: 'http://{{ route.result.spec.host }}'
|
||||
return_content: yes
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Delete route
|
||||
community.okd.openshift_route:
|
||||
name: '{{ route.result.metadata.name }}'
|
||||
namespace: default
|
||||
state: absent
|
||||
wait: yes
|
||||
|
||||
- name: Create Route with custom name and wait
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
name: test1
|
||||
wait: yes
|
||||
register: route
|
||||
|
||||
- name: Assert that the condition is properly set
|
||||
assert:
|
||||
that:
|
||||
- route.duration is defined
|
||||
- route.result.status.ingress.0.conditions.0.type == 'Admitted'
|
||||
- route.result.status.ingress.0.conditions.0.status == 'True'
|
||||
|
||||
- name: Attempt to hit http URL
|
||||
uri:
|
||||
url: 'http://{{ route.result.spec.host }}'
|
||||
return_content: yes
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Delete route
|
||||
community.okd.openshift_route:
|
||||
name: '{{ route.result.metadata.name }}'
|
||||
namespace: default
|
||||
state: absent
|
||||
wait: yes
|
||||
|
||||
- name: Create edge-terminated route that allows insecure traffic
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
name: hello-kubernetes-https
|
||||
tls:
|
||||
insecure_policy: allow
|
||||
termination: edge
|
||||
register: route
|
||||
|
||||
- name: Attempt to hit http URL
|
||||
uri:
|
||||
url: 'http://{{ route.result.spec.host }}'
|
||||
return_content: yes
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Attempt to hit https URL
|
||||
uri:
|
||||
url: 'https://{{ route.result.spec.host }}'
|
||||
validate_certs: no
|
||||
return_content: yes
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Alter edge-terminated route to redirect insecure traffic
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
name: hello-kubernetes-https
|
||||
tls:
|
||||
insecure_policy: redirect
|
||||
termination: edge
|
||||
register: route
|
||||
|
||||
- name: Attempt to hit http URL
|
||||
uri:
|
||||
url: 'http://{{ route.result.spec.host }}'
|
||||
return_content: yes
|
||||
validate_certs: no
|
||||
until:
|
||||
- result is successful
|
||||
- result.redirected
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Attempt to hit https URL
|
||||
uri:
|
||||
url: 'https://{{ route.result.spec.host }}'
|
||||
validate_certs: no
|
||||
return_content: yes
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Alter edge-terminated route with insecure traffic disabled
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
name: hello-kubernetes-https
|
||||
tls:
|
||||
insecure_policy: disallow
|
||||
termination: edge
|
||||
register: route
|
||||
|
||||
- debug: var=route
|
||||
|
||||
- name: Attempt to hit https URL
|
||||
uri:
|
||||
url: 'https://{{ route.result.spec.host }}'
|
||||
validate_certs: no
|
||||
return_content: yes
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 200
|
||||
- result.content == 'Hello OpenShift!\n'
|
||||
|
||||
- name: Attempt to hit http URL
|
||||
uri:
|
||||
url: 'http://{{ route.result.spec.host }}'
|
||||
status_code: 503
|
||||
until: result is successful
|
||||
retries: 10
|
||||
register: result
|
||||
|
||||
- debug: var=result
|
||||
|
||||
- name: Assert the page content is as expected
|
||||
assert:
|
||||
that:
|
||||
- not result.redirected
|
||||
- result.status == 503
|
||||
|
||||
- name: Delete route
|
||||
community.okd.openshift_route:
|
||||
name: '{{ route.result.metadata.name }}'
|
||||
namespace: default
|
||||
state: absent
|
||||
wait: yes
|
||||
@@ -61,3 +61,4 @@
|
||||
- import_tasks: tasks/validate_not_installed.yml
|
||||
|
||||
- import_tasks: tasks/openshift_auth.yml
|
||||
- import_tasks: tasks/openshift_route.yml
|
||||
|
||||
544
plugins/modules/openshift_route.py
Normal file
544
plugins/modules/openshift_route.py
Normal file
@@ -0,0 +1,544 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020, Red Hat
|
||||
# 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: openshift_route
|
||||
|
||||
short_description: Expose a Service as an OpenShift Route.
|
||||
|
||||
version_added: "1.1.0"
|
||||
|
||||
author: "Fabian von Feilitzsch (@fabianvf)"
|
||||
|
||||
description:
|
||||
- Looks up a Service and creates a new Route based on it.
|
||||
- Analogous to `oc expose` and `oc create route` for creating Routes, but does not support creating Services.
|
||||
- For creating Services from other resources, see community.kubernetes.k8s_expose
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.kubernetes.k8s_auth_options
|
||||
- community.kubernetes.k8s_wait_options
|
||||
- community.kubernetes.k8s_state_options
|
||||
|
||||
requirements:
|
||||
- "python >= 2.7"
|
||||
- "openshift >= 0.11.0"
|
||||
- "PyYAML >= 3.11"
|
||||
|
||||
options:
|
||||
service:
|
||||
description:
|
||||
- The name of the service to expose.
|
||||
- Required when I(state) is not absent.
|
||||
type: str
|
||||
aliases: ['svc']
|
||||
namespace:
|
||||
description:
|
||||
- The namespace of the resource being targeted.
|
||||
- The Route will be created in this namespace as well.
|
||||
required: yes
|
||||
type: str
|
||||
labels:
|
||||
description:
|
||||
- Specify the labels to apply to the created Route.
|
||||
- 'A set of key: value pairs.'
|
||||
type: dict
|
||||
name:
|
||||
description:
|
||||
- The desired name of the Route to be created.
|
||||
- Defaults to the value of I(service)
|
||||
type: str
|
||||
hostname:
|
||||
description:
|
||||
- The hostname for the Route.
|
||||
type: str
|
||||
path:
|
||||
description:
|
||||
- The path for the Route
|
||||
type: str
|
||||
wildcard_policy:
|
||||
description:
|
||||
- The wildcard policy for the hostname.
|
||||
- Currently only Subdomain is supported.
|
||||
- If not provided, the default of None will be used.
|
||||
choices:
|
||||
- Subdomain
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
- Name or number of the port the Route will route traffic to.
|
||||
type: str
|
||||
tls:
|
||||
description:
|
||||
- TLS configuration for the newly created route.
|
||||
- Only used when I(termination) is set.
|
||||
type: dict
|
||||
suboptions:
|
||||
ca_certificate:
|
||||
description:
|
||||
- Path to a CA certificate file on the target host.
|
||||
- Not supported when I(termination) is set to passthrough.
|
||||
type: str
|
||||
certificate:
|
||||
description:
|
||||
- Path to a certificate file on the target host.
|
||||
- Not supported when I(termination) is set to passthrough.
|
||||
type: str
|
||||
destination_ca_certificate:
|
||||
description:
|
||||
- Path to a CA certificate file used for securing the connection.
|
||||
- Only used when I(termination) is set to reencrypt.
|
||||
- Defaults to the Service CA.
|
||||
type: str
|
||||
key:
|
||||
description:
|
||||
- Path to a key file on the target host.
|
||||
- Not supported when I(termination) is set to passthrough.
|
||||
type: str
|
||||
insecure_policy:
|
||||
description:
|
||||
- Sets the InsecureEdgeTerminationPolicy for the Route.
|
||||
- Not supported when I(termination) is set to reencrypt.
|
||||
- When I(termination) is set to passthrough, only redirect is supported.
|
||||
- If not provided, insecure traffic will be disallowed.
|
||||
type: str
|
||||
choices:
|
||||
- allow
|
||||
- redirect
|
||||
- disallow
|
||||
default: disallow
|
||||
termination:
|
||||
description:
|
||||
- The termination type of the Route.
|
||||
- If left empty no termination type will be set, and the route will be insecure.
|
||||
- When set to insecure I(tls) will be ignored.
|
||||
choices:
|
||||
- edge
|
||||
- passthrough
|
||||
- reencrypt
|
||||
- insecure
|
||||
default: insecure
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Create hello-world deployment
|
||||
community.okd.k8s:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hello-kubernetes
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hello-kubernetes
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hello-kubernetes
|
||||
spec:
|
||||
containers:
|
||||
- name: hello-kubernetes
|
||||
image: paulbouwer/hello-kubernetes:1.8
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
- name: Create Service for the hello-world deployment
|
||||
community.okd.k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hello-kubernetes
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: hello-kubernetes
|
||||
|
||||
- name: Expose the insecure hello-world service externally
|
||||
community.okd.openshift_route:
|
||||
service: hello-kubernetes
|
||||
namespace: default
|
||||
insecure_policy: allow
|
||||
register: route
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
result:
|
||||
description:
|
||||
- The Route object that was created or updated. Will be empty in the case of deletion.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
apiVersion:
|
||||
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
|
||||
contains:
|
||||
name:
|
||||
description: The name of the created Route
|
||||
type: str
|
||||
namespace:
|
||||
description: The namespace of the create Route
|
||||
type: str
|
||||
spec:
|
||||
description: Specification for the Route
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
host:
|
||||
description: Host is an alias/DNS that points to the service.
|
||||
type: str
|
||||
path:
|
||||
description: Path that the router watches for, to route traffic for to the service.
|
||||
type: str
|
||||
port:
|
||||
description: Defines a port mapping from a router to an endpoint in the service endpoints.
|
||||
type: complex
|
||||
contains:
|
||||
targetPort:
|
||||
description: The target port on pods selected by the service this route points to.
|
||||
type: str
|
||||
tls:
|
||||
description: Defines config used to secure a route and provide termination.
|
||||
type: complex
|
||||
contains:
|
||||
caCertificate:
|
||||
description: Provides the cert authority certificate contents.
|
||||
type: str
|
||||
certificate:
|
||||
description: Provides certificate contents.
|
||||
type: str
|
||||
destinationCACertificate:
|
||||
description: Provides the contents of the ca certificate of the final destination.
|
||||
type: str
|
||||
insecureEdgeTerminationPolicy:
|
||||
description: Indicates the desired behavior for insecure connections to a route.
|
||||
type: str
|
||||
key:
|
||||
description: Provides key file contents.
|
||||
type: str
|
||||
termination:
|
||||
description: Indicates termination type.
|
||||
type: str
|
||||
to:
|
||||
description: Specifies the target that resolve into endpoints.
|
||||
type: complex
|
||||
contains:
|
||||
kind:
|
||||
description: The kind of target that the route is referring to. Currently, only 'Service' is allowed.
|
||||
type: str
|
||||
name:
|
||||
description: Name of the service/target that is being referred to. e.g. name of the service.
|
||||
type: str
|
||||
weight:
|
||||
description: Specifies the target's relative weight against other target reference objects.
|
||||
type: int
|
||||
wildcardPolicy:
|
||||
description: Wildcard policy if any for the route.
|
||||
type: str
|
||||
status:
|
||||
description: Current status details for the Route
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
ingress:
|
||||
description: List of places where the route may be exposed.
|
||||
type: complex
|
||||
contains:
|
||||
conditions:
|
||||
description: Array of status conditions for the Route ingress.
|
||||
type: complex
|
||||
contains:
|
||||
type:
|
||||
description: The type of the condition. Currently only 'Ready'.
|
||||
type: str
|
||||
status:
|
||||
description: The status of the condition. Can be True, False, Unknown.
|
||||
type: str
|
||||
host:
|
||||
description: The host string under which the route is exposed.
|
||||
type: str
|
||||
routerCanonicalHostname:
|
||||
description: The external host name for the router that can be used as a CNAME for the host requested for this route. May not be set.
|
||||
type: str
|
||||
routerName:
|
||||
description: A name chosen by the router to identify itself.
|
||||
type: str
|
||||
wildcardPolicy:
|
||||
description: The wildcard policy that was allowed where this route is exposed.
|
||||
type: str
|
||||
duration:
|
||||
description: elapsed time of task in seconds
|
||||
returned: when C(wait) is true
|
||||
type: int
|
||||
sample: 48
|
||||
'''
|
||||
|
||||
import copy
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC, WAIT_ARG_SPEC, COMMON_ARG_SPEC
|
||||
)
|
||||
HAS_KUBERNETES_COLLECTION = True
|
||||
except ImportError as e:
|
||||
HAS_KUBERNETES_COLLECTION = False
|
||||
k8s_collection_import_exception = e
|
||||
K8S_COLLECTION_ERROR = traceback.format_exc()
|
||||
K8sAnsibleMixin = object
|
||||
AUTH_ARG_SPEC = WAIT_ARG_SPEC = COMMON_ARG_SPEC = {}
|
||||
|
||||
try:
|
||||
from openshift.dynamic.exceptions import DynamicApiError, NotFoundError
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class OpenShiftRoute(K8sAnsibleMixin):
|
||||
|
||||
def __init__(self):
|
||||
self.module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
self.fail_json = self.module.fail_json
|
||||
|
||||
if not HAS_KUBERNETES_COLLECTION:
|
||||
self.module.fail_json(
|
||||
msg="The community.kubernetes collection must be installed",
|
||||
exception=K8S_COLLECTION_ERROR,
|
||||
error=to_native(k8s_collection_import_exception)
|
||||
)
|
||||
|
||||
super(OpenShiftRoute, self).__init__()
|
||||
|
||||
self.params = self.module.params
|
||||
# TODO: should probably make it so that at least some of these aren't required for perform_action to work
|
||||
# Or at least explicitly pass them in
|
||||
self.append_hash = False
|
||||
self.apply = False
|
||||
self.check_mode = self.module.check_mode
|
||||
self.warnings = []
|
||||
self.params['merge_type'] = None
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
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'),
|
||||
insecure_policy=dict(type='str', choices=['allow', 'redirect', 'disallow'], default='disallow'),
|
||||
))
|
||||
spec['termination'] = dict(choices=['edge', 'passthrough', 'reencrypt', 'insecure'], default='insecure')
|
||||
|
||||
return spec
|
||||
|
||||
def execute_module(self):
|
||||
self.client = self.get_api_client()
|
||||
v1_routes = self.find_resource('Route', 'route.openshift.io/v1', fail=True)
|
||||
|
||||
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')
|
||||
|
||||
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'
|
||||
if custom_wait:
|
||||
# Don't use default wait logic in perform_action
|
||||
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')
|
||||
|
||||
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
|
||||
|
||||
route = {
|
||||
'apiVersion': 'route.openshift.io/v1',
|
||||
'kind': 'Route',
|
||||
'metadata': {
|
||||
'name': route_name,
|
||||
'namespace': namespace,
|
||||
'labels': labels,
|
||||
},
|
||||
'spec': {}
|
||||
}
|
||||
|
||||
if state != 'absent':
|
||||
route['spec'] = self.build_route_spec(
|
||||
service_name, namespace,
|
||||
port=port,
|
||||
wildcard_policy=wildcard_policy,
|
||||
hostname=hostname,
|
||||
path=path,
|
||||
termination_type=termination_type,
|
||||
tls_insecure_policy=tls_insecure_policy,
|
||||
tls_ca_cert=tls_ca_cert,
|
||||
tls_cert=tls_cert,
|
||||
tls_key=tls_key,
|
||||
tls_dest_ca_cert=tls_dest_ca_cert,
|
||||
)
|
||||
|
||||
result = self.perform_action(v1_routes, route)
|
||||
timeout = self.params.get('wait_timeout')
|
||||
sleep = self.params.get('wait_sleep')
|
||||
if custom_wait:
|
||||
success, result['result'], result['duration'] = self._wait_for(v1_routes, route_name, namespace, wait_predicate, sleep, timeout, state)
|
||||
|
||||
self.module.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)
|
||||
try:
|
||||
target_service = v1_services.get(name=service_name, namespace=namespace)
|
||||
except NotFoundError:
|
||||
if not port:
|
||||
self.module.fail_json(msg="You need to provide the 'port' argument when exposing a non-existent service")
|
||||
target_service = None
|
||||
except DynamicApiError as exc:
|
||||
self.module.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.module.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,
|
||||
},
|
||||
'port': {
|
||||
'targetPort': self.set_port(target_service, port),
|
||||
},
|
||||
'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())
|
||||
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.module.fail_json("'redirect' is the only supported insecureEdgeTerminationPolicy for passthrough routes")
|
||||
route_spec['tls']['insecureEdgeTerminationPolicy'] = tls_insecure_policy.capitalize()
|
||||
elif termination_type == 'reencrypt':
|
||||
self.module.fail_json("'tls.insecure_policy' is not supported with reencrypt routes")
|
||||
else:
|
||||
route_spec['tls']['insecureEdgeTerminationPolicy'] = None
|
||||
if tls_ca_cert:
|
||||
if termination_type == 'passthrough':
|
||||
self.module.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.module.fail_json("'tls.certificate' is not supported with passthrough routes")
|
||||
route_spec['tls']['certificate'] = tls_cert
|
||||
if tls_key:
|
||||
if termination_type == 'passthrough':
|
||||
self.module.fail_json("'tls.key' is not supported with passthrough routes")
|
||||
route_spec['tls']['key'] = tls_key
|
||||
if tls_dest_ca_cert:
|
||||
if termination_type != 'reencrypt':
|
||||
self.module.fail_json("'destination_certificate' is only valid for reencrypt routes")
|
||||
route_spec['tls']['destinationCACertificate'] = tls_dest_ca_cert
|
||||
else:
|
||||
route_spec['tls'] = None
|
||||
if hostname:
|
||||
route_spec['host'] = hostname
|
||||
if path:
|
||||
route_spec['path'] = path
|
||||
|
||||
return route_spec
|
||||
|
||||
def set_port(self, service, port_arg):
|
||||
if port_arg:
|
||||
return port_arg
|
||||
for p in service.spec.ports:
|
||||
if p.protocol == 'TCP':
|
||||
if p.name is not None:
|
||||
return p.name
|
||||
return p.targetPort
|
||||
return None
|
||||
|
||||
|
||||
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']
|
||||
if not match:
|
||||
return False
|
||||
match = match[0]
|
||||
if match.status != "True":
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
OpenShiftRoute().execute_module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user