Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

Commit

Permalink
feat: restart watcher if no events seen for specified period
Browse files Browse the repository at this point in the history
  • Loading branch information
Flydiverny committed Nov 12, 2020
1 parent 95e4819 commit 1133871
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 10 deletions.
6 changes: 4 additions & 2 deletions bin/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const {
pollingDisabled,
rolePermittedAnnotation,
namingPermittedAnnotation,
enforceNamespaceAnnotation
enforceNamespaceAnnotation,
watchTimeout
} = require('../config')

async function main () {
Expand All @@ -37,7 +38,8 @@ async function main () {
const externalSecretEvents = getExternalSecretEvents({
kubeClient,
customResourceManifest,
logger
logger,
watchTimeout
})

const registry = Prometheus.register
Expand Down
1 change: 1 addition & 0 deletions charts/kubernetes-external-secrets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ The following table lists the configurable parameters of the `kubernetes-externa
| `env.POLLER_INTERVAL_MILLISECONDS` | Set POLLER_INTERVAL_MILLISECONDS in Deployment Pod | `10000` |
| `env.VAULT_ADDR` | Endpoint for the Vault backend, if using Vault | `http://127.0.0.1:8200` |
| `env.DISABLE_POLLING` | Disables backend polling and only updates secrets when ExternalSecret is modified, setting this to any value will disable polling | `nil` |
| `env.WATCH_TIMEOUT` | Restarts the external secrets resource watcher if no events have been seen in this time period (miliseconds) | `60000` |
| `envVarsFromSecret.AWS_ACCESS_KEY_ID` | Set AWS_ACCESS_KEY_ID (from a secret) in Deployment Pod | |
| `envVarsFromSecret.AWS_SECRET_ACCESS_KEY` | Set AWS_SECRET_ACCESS_KEY (from a secret) in Deployment Pod | |
| `envVarsFromSecret.AZURE_TENANT_ID` | Set AZURE_TENANT_ID (from a secret) in Deployment Pod | |
Expand Down
1 change: 1 addition & 0 deletions charts/kubernetes-external-secrets/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ env:
AWS_REGION: us-west-2
AWS_DEFAULT_REGION: us-west-2
POLLER_INTERVAL_MILLISECONDS: 10000 # Caution, setting this frequency may incur additional charges on some platforms
WATCH_TIMEOUT: 60000
LOG_LEVEL: info
LOG_MESSAGE_KEY: 'msg'
# Print logs level as string ("info") rather than integer (30)
Expand Down
4 changes: 3 additions & 1 deletion config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const enforceNamespaceAnnotation = 'ENFORCE_NAMESPACE_ANNOTATIONS' in process.en
const metricsPort = process.env.METRICS_PORT || 3001

const customResourceManagerDisabled = 'DISABLE_CUSTOM_RESOURCE_MANAGER' in process.env
const watchTimeout = process.env.WATCH_TIMEOUT ? parseInt(process.env.WATCH_TIMEOUT) : 60000

module.exports = {
vaultEndpoint,
Expand All @@ -52,5 +53,6 @@ module.exports = {
logLevel,
customResourceManagerDisabled,
useHumanReadableLogLevels,
logMessageKey
logMessageKey,
watchTimeout
}
34 changes: 28 additions & 6 deletions lib/external-secret.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ async function startWatcher ({
kubeClient,
customResourceManifest,
logger,
eventQueue
eventQueue,
watchTimeout
}) {
const deathQueue = createEventQueue()

Expand All @@ -42,20 +43,39 @@ async function startWatcher ({
const jsonStream = new JSONStream()
stream.pipe(jsonStream)

jsonStream.on('data', eventQueue.put)
let timeout
const restartTimeout = () => {
if (timeout) {
clearTimeout(timeout)
}

const timeMs = watchTimeout
timeout = setTimeout(() => {
logger.info(`No watch event for ${timeMs} ms, restarting watcher`)
stream.abort()
}, timeMs)
timeout.unref()
}

jsonStream.on('data', (evt) => {
eventQueue.put(evt)
restartTimeout()
})

jsonStream.on('error', (err) => {
logger.warn(err, 'Got error on stream')
deathQueue.put('ERROR')
clearTimeout(timeout)
})

jsonStream.on('end', () => {
deathQueue.put('END')
clearTimeout(timeout)
})

await deathQueue.take()
const deathEvent = await deathQueue.take()

logger.debug('Stopping watch stream')
logger.info('Stopping watch stream due to event: %s', deathEvent)
eventQueue.put({ type: 'DELETED_ALL' })

stream.abort()
Expand All @@ -75,7 +95,8 @@ async function startWatcher ({
function getExternalSecretEvents ({
kubeClient,
customResourceManifest,
logger
logger,
watchTimeout
}) {
return (async function * () {
const eventQueue = createEventQueue()
Expand All @@ -84,7 +105,8 @@ function getExternalSecretEvents ({
kubeClient,
customResourceManifest,
logger,
eventQueue
eventQueue,
watchTimeout
})

while (true) {
Expand Down
4 changes: 3 additions & 1 deletion lib/external-secret.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('getExternalSecretEvents', () => {

mockedStream = new Readable()
mockedStream._read = () => {}
mockedStream.abort = () => {}

externalSecretsApiMock.get = sinon.stub()
kubeClientMock = sinon.mock()
Expand Down Expand Up @@ -60,7 +61,8 @@ describe('getExternalSecretEvents', () => {
const events = getExternalSecretEvents({
kubeClient: kubeClientMock,
customResourceManifest: fakeCustomResourceManifest,
logger: loggerMock
logger: loggerMock,
watchTimeout: 5000
})

mockedStream.push(`${JSON.stringify({
Expand Down

0 comments on commit 1133871

Please sign in to comment.