Skip to content

Commit

Permalink
Merge pull request #1 from mmiller1/master
Browse files Browse the repository at this point in the history
Support configuring the target namespaces for the sync via annotations
  • Loading branch information
TheYkk authored Aug 25, 2020
2 parents 60b15ba + 20d8c63 commit b7f874b
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ RUN pip install kopf kubernetes

ADD . /src

CMD kopf run /src/handlers.py
CMD kopf run /src/handlers.py
12 changes: 8 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# Synator Kubernetes Secret and ConfigMap synchronizer

Synator synchronize your Secrets and ConfigMaps with your all namespaces
Synator synchronize your Secrets and ConfigMaps with your desired namespaces

# Usage
Add label `synator/sync=yes` to Secret or ConfigMap.
Add annotation `synator/sync=yes` to Secret or ConfigMap.
Optionally add one of these annotations in include specific destination
namespaces, or exclude the namespaces from the sync.
`synator/include-namespaces='namespace1,namespace2'`
`synator/exclude-namespaces='kube-system,kube-node-lease'`

# Triggers
- When update config or secret
- When create config or secret

# Build and deeploy
# Build and deploy
Build docker image

```
Expand All @@ -20,4 +24,4 @@ Edit deploy.yml with your image name

```
kubectl apply -f deploy.yml
```
```
2 changes: 1 addition & 1 deletion deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ spec:
serviceAccountName: synator
containers:
- name: synator
image: theykk/synator:v0.10
image: theykk/synator:v0.10
3 changes: 2 additions & 1 deletion example-secret.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ apiVersion: v1
metadata:
name: selam
namespace: default
labels:
annotations:
synator/sync: 'yes'
synator/exclude-namespaces: "kube-system,kube-node-lease"
data:
tt: dHQ0NTExMjM0NTU=
type: Opaque
73 changes: 53 additions & 20 deletions handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,76 @@
import kubernetes


@kopf.on.create('', 'v1', 'secrets', labels={'synator/sync': 'yes'})
@kopf.on.update('', 'v1', 'secrets', labels={'synator/sync': 'yes'})
@kopf.on.create('', 'v1', 'secrets', annotations={'synator/sync': 'yes'})
@kopf.on.update('', 'v1', 'secrets', annotations={'synator/sync': 'yes'})
def updateSecret(body, meta, spec, status, old, new, diff, **kwargs):
print("SYNC SECRET ", meta.name)
api = kubernetes.client.CoreV1Api()
namespace_response = api.list_namespace()
namespaces = [nsa.metadata.name for nsa in namespace_response.items]
namespaces.remove('kube-public')
namespaces.remove('kube-node-lease')
namespaces.remove(meta.namespace)

secret = api.read_namespaced_secret(meta.name, meta.namespace)
secret.metadata.labels.pop('synator/sync')
secret.metadata.annotations.pop('synator/sync')
secret.metadata.resource_version = None
for ns in namespaces:
secret.metadata.uid = None
for ns in parseTargetNamespaces(meta, namespaces):
secret.metadata.namespace = ns
api.create_namespaced_secret(
ns, secret
)
# try to pull the Secret object then patch it, try creating it if we can't
try:
cm = api.read_namespaced_secret(meta.name, ns)
api.patch_namespaced_secret(meta.name, ns, secret)
except kubernetes.client.rest.ApiException as e:
print(e.args)
api.create_namespaced_secret(ns, secret)


@kopf.on.create('', 'v1', 'configmaps', labels={'synator/sync': 'yes'})
@kopf.on.update('', 'v1', 'configmaps', labels={'synator/sync': 'yes'})
@kopf.on.create('', 'v1', 'configmaps', annotations={'synator/sync': 'yes'})
@kopf.on.update('', 'v1', 'configmaps', annotations={'synator/sync': 'yes'})
def updateConfigMap(body, meta, spec, status, old, new, diff, **kwargs):
print("SYNC CFG ", meta.name)
# kopf.info(f"SYNC CFG {meta.name}", reason='event')
api = kubernetes.client.CoreV1Api()
namespace_response = api.list_namespace()
namespaces = [nsa.metadata.name for nsa in namespace_response.items]
namespaces.remove('kube-public')
namespaces.remove('kube-node-lease')
namespaces.remove(meta.namespace)

cfg = api.read_namespaced_config_map(meta.name, meta.namespace)
cfg.metadata.labels.pop('synator/sync')
cfg.metadata.annotations.pop('synator/sync')
cfg.metadata.resource_version = None
for ns in namespaces:
cfg.metadata.uid = None
for ns in parseTargetNamespaces(meta, namespaces):
cfg.metadata.namespace = ns
api.create_namespaced_config_map(
ns, cfg
)
# try to pull the ConfigMap object then patch it, try to create it if we can't
try:
cm = api.read_namespaced_config_map(meta.name, ns)
api.patch_namespaced_config_map(meta.name, ns, cfg)
except kubernetes.client.rest.ApiException as e:
print(e.args)
api.create_namespaced_config_map(ns, cfg)

def parseTargetNamespaces(meta, namespaces):
namespace_list = []
# look for a namespace inclusion label first, if we don't find that, assume all namespaces are the target
if 'synator/include-namespaces' in meta.annotations:
value = meta.annotations['synator/include-namespaces']
namespaces_to_include = value.replace(' ', '').split(',')
for ns in namespaces_to_include:
if ns in namespaces:
namespace_list.append(ns)
else:
print(f"WARNING: include-namespaces requested I add this resource to a non-existing namespace: {ns}")
else:
# we didn't find a namespace inclusion label, so let's see if we were told to exclude any
namespace_list = namespaces
if 'synator/exclude-namespaces' in meta.annotations:
value = meta.annotations['synator/exclude-namespaces']
namespaces_to_exclude = value.replace(' ', '').split(',')
if len(namespaces_to_exclude) < 1:
print("WARNING: exclude-namespaces was specified, but no values were parsed")

for ns in namespaces_to_exclude:
if ns in namespace_list:
namespace_list.remove(ns)
else:
print(f"WARNING: I was told to exclude namespace {ns}, but it doesn't exist on the cluster")

return namespace_list

0 comments on commit b7f874b

Please sign in to comment.