9 changed files with 428 additions and 59 deletions
Split View
Diff Options
-
6.travis.yml
-
5cluster.yml
-
3inventory/group_vars/all.yml
-
318roles/dnsmasq/library/kube.py
-
27roles/dnsmasq/tasks/main.yml
-
4roles/dnsmasq/templates/01-kube-dns.conf.j2
-
52roles/dnsmasq/templates/dnsmasq-ds.yml
-
49roles/dnsmasq/templates/dnsmasq-pod.yml
-
23roles/dnsmasq/templates/dnsmasq-svc.yml
@ -0,0 +1,318 @@ |
|||
#!/usr/bin/python |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
DOCUMENTATION = """ |
|||
--- |
|||
module: kube |
|||
short_description: Manage Kubernetes Cluster |
|||
description: |
|||
- Create, replace, remove, and stop resources within a Kubernetes Cluster |
|||
version_added: "2.0" |
|||
options: |
|||
name: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The name associated with resource |
|||
filename: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The path and filename of the resource(s) definition file. |
|||
kubectl: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The path to the kubectl bin |
|||
namespace: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The namespace associated with the resource(s) |
|||
resource: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The resource to perform an action on. pods (po), replicationControllers (rc), services (svc) |
|||
label: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The labels used to filter specific resources. |
|||
server: |
|||
required: false |
|||
default: null |
|||
description: |
|||
- The url for the API server that commands are executed against. |
|||
api_version: |
|||
required: false |
|||
choices: ['v1', 'v1beta3'] |
|||
default: v1 |
|||
description: |
|||
- The API version associated with cluster. |
|||
force: |
|||
required: false |
|||
default: false |
|||
description: |
|||
- A flag to indicate to force delete, replace, or stop. |
|||
all: |
|||
required: false |
|||
default: false |
|||
description: |
|||
- A flag to indicate delete all, stop all, or all namespaces when checking exists. |
|||
log_level: |
|||
required: false |
|||
default: 0 |
|||
description: |
|||
- Indicates the level of verbosity of logging by kubectl. |
|||
state: |
|||
required: false |
|||
choices: ['present', 'absent', 'latest', 'reloaded', 'stopped'] |
|||
default: present |
|||
description: |
|||
- present handles checking existence or creating if definition file provided, |
|||
absent handles deleting resource(s) based on other options, |
|||
latest handles creating ore updating based on existence, |
|||
reloaded handles updating resource(s) definition using definition file, |
|||
stopped handles stopping resource(s) based on other options. |
|||
requirements: |
|||
- kubectl |
|||
author: "Kenny Jones (@kenjones-cisco)" |
|||
""" |
|||
|
|||
EXAMPLES = """ |
|||
- name: test nginx is present |
|||
kube: name=nginx resource=rc state=present |
|||
|
|||
- name: test nginx is stopped |
|||
kube: name=nginx resource=rc state=stopped |
|||
|
|||
- name: test nginx is absent |
|||
kube: name=nginx resource=rc state=absent |
|||
|
|||
- name: test nginx is present |
|||
kube: filename=/tmp/nginx.yml |
|||
""" |
|||
|
|||
|
|||
class KubeManager(object): |
|||
|
|||
def __init__(self, module): |
|||
|
|||
self.module = module |
|||
|
|||
self.kubectl = module.params.get('kubectl') |
|||
if self.kubectl is None: |
|||
self.kubectl = module.get_bin_path('kubectl', True) |
|||
self.base_cmd = [self.kubectl] |
|||
self.api_version = module.params.get('api_version') |
|||
|
|||
if self.api_version: |
|||
self.base_cmd.append('--api-version=' + self.api_version) |
|||
|
|||
if module.params.get('server'): |
|||
self.base_cmd.append('--server=' + module.params.get('server')) |
|||
|
|||
if module.params.get('log_level'): |
|||
self.base_cmd.append('--v=' + str(module.params.get('log_level'))) |
|||
|
|||
if module.params.get('namespace'): |
|||
self.base_cmd.append('--namespace=' + module.params.get('namespace')) |
|||
|
|||
self.all = module.params.get('all') |
|||
self.force = module.params.get('force') |
|||
self.name = module.params.get('name') |
|||
self.filename = module.params.get('filename') |
|||
self.resource = module.params.get('resource') |
|||
self.label = module.params.get('label') |
|||
|
|||
def _execute(self, cmd): |
|||
args = self.base_cmd + cmd |
|||
try: |
|||
rc, out, err = self.module.run_command(args) |
|||
if rc != 0: |
|||
self.module.fail_json( |
|||
msg='error running kubectl (%s) command (rc=%d): %s' % (' '.join(args), rc, out or err)) |
|||
except Exception as exc: |
|||
self.module.fail_json( |
|||
msg='error running kubectl (%s) command: %s' % (' '.join(args), str(exc))) |
|||
return out.splitlines() |
|||
|
|||
def _execute_nofail(self, cmd): |
|||
args = self.base_cmd + cmd |
|||
rc, out, err = self.module.run_command(args) |
|||
if rc != 0: |
|||
return None |
|||
return out.splitlines() |
|||
|
|||
def create(self, check=True): |
|||
if check and self.exists(): |
|||
return [] |
|||
|
|||
cmd = ['create'] |
|||
|
|||
if not self.filename: |
|||
self.module.fail_json(msg='filename required to create') |
|||
|
|||
cmd.append('--filename=' + self.filename) |
|||
|
|||
return self._execute(cmd) |
|||
|
|||
def replace(self): |
|||
|
|||
if not self.force and not self.exists(): |
|||
return [] |
|||
|
|||
cmd = ['replace'] |
|||
if self.api_version != 'v1': |
|||
cmd = ['update'] |
|||
|
|||
if self.force: |
|||
cmd.append('--force') |
|||
|
|||
if not self.filename: |
|||
self.module.fail_json(msg='filename required to reload') |
|||
|
|||
cmd.append('--filename=' + self.filename) |
|||
|
|||
return self._execute(cmd) |
|||
|
|||
def delete(self): |
|||
|
|||
if not self.force and not self.exists(): |
|||
return [] |
|||
|
|||
cmd = ['delete'] |
|||
|
|||
if self.filename: |
|||
cmd.append('--filename=' + self.filename) |
|||
else: |
|||
if not self.resource: |
|||
self.module.fail_json(msg='resource required to delete without filename') |
|||
|
|||
cmd.append(self.resource) |
|||
|
|||
if self.name: |
|||
cmd.append(self.name) |
|||
|
|||
if self.label: |
|||
cmd.append('--selector=' + self.label) |
|||
|
|||
if self.all: |
|||
cmd.append('--all') |
|||
|
|||
if self.force: |
|||
cmd.append('--ignore-not-found') |
|||
|
|||
return self._execute(cmd) |
|||
|
|||
def exists(self): |
|||
cmd = ['get'] |
|||
|
|||
if not self.resource: |
|||
return False |
|||
|
|||
cmd.append(self.resource) |
|||
|
|||
if self.name: |
|||
cmd.append(self.name) |
|||
|
|||
cmd.append('--no-headers') |
|||
|
|||
if self.label: |
|||
cmd.append('--selector=' + self.label) |
|||
|
|||
if self.all: |
|||
cmd.append('--all-namespaces') |
|||
|
|||
result = self._execute_nofail(cmd) |
|||
if not result: |
|||
return False |
|||
return True |
|||
|
|||
def stop(self): |
|||
|
|||
if not self.force and not self.exists(): |
|||
return [] |
|||
|
|||
cmd = ['stop'] |
|||
|
|||
if self.filename: |
|||
cmd.append('--filename=' + self.filename) |
|||
else: |
|||
if not self.resource: |
|||
self.module.fail_json(msg='resource required to stop without filename') |
|||
|
|||
cmd.append(self.resource) |
|||
|
|||
if self.name: |
|||
cmd.append(self.name) |
|||
|
|||
if self.label: |
|||
cmd.append('--selector=' + self.label) |
|||
|
|||
if self.all: |
|||
cmd.append('--all') |
|||
|
|||
if self.force: |
|||
cmd.append('--ignore-not-found') |
|||
|
|||
return self._execute(cmd) |
|||
|
|||
|
|||
def main(): |
|||
|
|||
module = AnsibleModule( |
|||
argument_spec=dict( |
|||
name=dict(), |
|||
filename=dict(), |
|||
namespace=dict(), |
|||
resource=dict(), |
|||
label=dict(), |
|||
server=dict(), |
|||
kubectl=dict(), |
|||
api_version=dict(default='v1', choices=['v1', 'v1beta3']), |
|||
force=dict(default=False, type='bool'), |
|||
all=dict(default=False, type='bool'), |
|||
log_level=dict(default=0, type='int'), |
|||
state=dict(default='present', choices=['present', 'absent', 'latest', 'reloaded', 'stopped']), |
|||
) |
|||
) |
|||
|
|||
changed = False |
|||
|
|||
manager = KubeManager(module) |
|||
state = module.params.get('state') |
|||
|
|||
if state == 'present': |
|||
result = manager.create() |
|||
|
|||
elif state == 'absent': |
|||
result = manager.delete() |
|||
|
|||
elif state == 'reloaded': |
|||
result = manager.replace() |
|||
|
|||
elif state == 'stopped': |
|||
result = manager.stop() |
|||
|
|||
elif state == 'latest': |
|||
if manager.exists(): |
|||
manager.force = True |
|||
result = manager.replace() |
|||
else: |
|||
result = manager.create(check=False) |
|||
|
|||
else: |
|||
module.fail_json(msg='Unrecognized state %s.' % state) |
|||
|
|||
if result: |
|||
changed = True |
|||
module.exit_json(changed=changed, |
|||
msg='success: %s' % (' '.join(result)) |
|||
) |
|||
|
|||
|
|||
from ansible.module_utils.basic import * # noqa |
|||
if __name__ == '__main__': |
|||
main() |
@ -0,0 +1,52 @@ |
|||
--- |
|||
apiVersion: extensions/v1beta1 |
|||
kind: DaemonSet |
|||
metadata: |
|||
name: dnsmasq |
|||
namespace: kube-system |
|||
labels: |
|||
k8s-app: dnsmasq |
|||
spec: |
|||
template: |
|||
metadata: |
|||
labels: |
|||
k8s-app: dnsmasq |
|||
spec: |
|||
containers: |
|||
- name: dnsmasq |
|||
image: andyshinn/dnsmasq:2.72 |
|||
command: |
|||
- dnsmasq |
|||
args: |
|||
- -k |
|||
- "-7" |
|||
- /etc/dnsmasq.d |
|||
securityContext: |
|||
capabilities: |
|||
add: |
|||
- NET_ADMIN |
|||
imagePullPolicy: Always |
|||
resources: |
|||
limits: |
|||
cpu: 100m |
|||
memory: 256M |
|||
ports: |
|||
- name: dns |
|||
containerPort: 53 |
|||
protocol: UDP |
|||
- name: dns-tcp |
|||
containerPort: 53 |
|||
protocol: TCP |
|||
volumeMounts: |
|||
- name: etcdnsmasqd |
|||
mountPath: /etc/dnsmasq.d |
|||
- name: etcdnsmasqdavailable |
|||
mountPath: /etc/dnsmasq.d-available |
|||
|
|||
volumes: |
|||
- name: etcdnsmasqd |
|||
hostPath: |
|||
path: /etc/dnsmasq.d |
|||
- name: etcdnsmasqdavailable |
|||
hostPath: |
|||
path: /etc/dnsmasq.d-available |
@ -1,49 +0,0 @@ |
|||
--- |
|||
apiVersion: v1 |
|||
kind: Pod |
|||
metadata: |
|||
name: dnsmasq |
|||
namespace: kube-system |
|||
spec: |
|||
hostNetwork: true |
|||
containers: |
|||
- name: dnsmasq |
|||
image: andyshinn/dnsmasq:2.72 |
|||
command: |
|||
- dnsmasq |
|||
args: |
|||
- -k |
|||
- "-7" |
|||
- /etc/dnsmasq.d |
|||
- --local-service |
|||
securityContext: |
|||
capabilities: |
|||
add: |
|||
- NET_ADMIN |
|||
imagePullPolicy: Always |
|||
resources: |
|||
limits: |
|||
cpu: 100m |
|||
memory: 256M |
|||
ports: |
|||
- name: dns |
|||
containerPort: 53 |
|||
hostPort: 53 |
|||
protocol: UDP |
|||
- name: dns-tcp |
|||
containerPort: 53 |
|||
hostPort: 53 |
|||
protocol: TCP |
|||
volumeMounts: |
|||
- name: etcdnsmasqd |
|||
mountPath: /etc/dnsmasq.d |
|||
- name: etcdnsmasqdavailable |
|||
mountPath: /etc/dnsmasq.d-available |
|||
|
|||
volumes: |
|||
- name: etcdnsmasqd |
|||
hostPath: |
|||
path: /etc/dnsmasq.d |
|||
- name: etcdnsmasqdavailable |
|||
hostPath: |
|||
path: /etc/dnsmasq.d-available |
@ -0,0 +1,23 @@ |
|||
--- |
|||
apiVersion: v1 |
|||
kind: Service |
|||
metadata: |
|||
labels: |
|||
kubernetes.io/cluster-service: 'true' |
|||
k8s-app: dnsmasq |
|||
name: dnsmasq |
|||
namespace: kube-system |
|||
spec: |
|||
ports: |
|||
- port: 53 |
|||
name: dns-tcp |
|||
targetPort: 53 |
|||
protocol: TCP |
|||
- port: 53 |
|||
name: dns |
|||
targetPort: 53 |
|||
protocol: UDP |
|||
type: ClusterIP |
|||
clusterIP: {{dns_server}} |
|||
selector: |
|||
k8s-app: dnsmasq |
Write
Preview
Loading…
Cancel
Save