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

Commit

Permalink
Garbage collection dry run
Browse files Browse the repository at this point in the history
Before this change there was no ability to run the garbage collection
process in a dry run, without touching any resources.

After this change you can enable the option sync-garbage-collection-dry
to only log what would be garbage collected, rather than deleting.
  • Loading branch information
Jan Schumacher committed May 24, 2019
1 parent 5e17cd5 commit e3a28e4
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 17 deletions.
1 change: 1 addition & 0 deletions chart/flux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ The following tables lists the configurable parameters of the Weave Flux chart a
| `kube.config` | [See values.yaml](/chart/flux/values.yaml#L151-L165) | Override for kubectl default config in the Flux pod(s).
| `prometheus.enabled` | `false` | If enabled, adds prometheus annotations to Flux and helmOperator pod(s)
| `syncGarbageCollection.enabled` | `false` | If enabled, fluxd will delete resources that it created, but are no longer present in git (experimental, see [garbage collection](/site/garbagecollection.md))
| `syncGarbageCollection.dry` | `false` | If enabled, fluxd won't delete any resources, but log the garbage collection output (experimental, see [garbage collection](/site/garbagecollection.md))

Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example:

Expand Down
4 changes: 3 additions & 1 deletion chart/flux/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ spec:
- --connect=wss://cloud.weave.works/api/flux
- --token={{ .Values.token }}
{{- end }}
{{- if .Values.syncGarbageCollection.enabled }}
{{- if and .Values.syncGarbageCollection.enabled (not .Values.syncGarbageCollection.dry) }}
- --sync-garbage-collection={{ .Values.syncGarbageCollection.enabled }}
{{- else if .Values.syncGarbageCollection.dry }}
- --sync-garbage-collection-dry={{ .Values.syncGarbageCollection.dry }}
{{- end }}
{{- if .Values.additionalArgs }}
{{ toYaml .Values.additionalArgs | indent 10 }}
Expand Down
1 change: 1 addition & 0 deletions chart/flux/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ prometheus:

syncGarbageCollection:
enabled: false
dry: false

# Add your own init container or uncomment and modify the given example.
initContainers: {}
Expand Down
2 changes: 2 additions & 0 deletions cluster/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func isAddon(obj k8sObject) bool {
type Cluster struct {
// Do garbage collection when syncing resources
GC bool
// dry run garbage collection without syncing
DryGC bool

client ExtendedClient
applier Applier
Expand Down
20 changes: 13 additions & 7 deletions cluster/kubernetes/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ func (c *Cluster) Sync(syncSet cluster.SyncSet) error {
}
c.muSyncErrors.RUnlock()

if c.GC {
deleteErrs, gcFailure := c.collectGarbage(syncSet, checksums, logger)
if c.GC || c.DryGC {
deleteErrs, gcFailure := c.collectGarbage(syncSet, checksums, logger, c.DryGC)
if gcFailure != nil {
return gcFailure
}
Expand All @@ -129,7 +129,8 @@ func (c *Cluster) Sync(syncSet cluster.SyncSet) error {
func (c *Cluster) collectGarbage(
syncSet cluster.SyncSet,
checksums map[string]string,
logger log.Logger) (cluster.SyncError, error) {
logger log.Logger,
dryRun bool) (cluster.SyncError, error) {

orphanedResources := makeChangeSet()

Expand All @@ -142,12 +143,17 @@ func (c *Cluster) collectGarbage(
actual := res.GetChecksum()
expected, ok := checksums[resourceID]

collectGarbage := !ok && !dryRun
onlyLogging := !ok && dryRun
skipResource := actual != expected
switch {
case !ok: // was not recorded as having been staged for application
c.logger.Log("info", "cluster resource not in resources to be synced; deleting", "resource", resourceID)
case collectGarbage:
c.logger.Log("info", "Garbage-Collection: deleting resources; cluster resource not in resources to be synced", "resource", resourceID)
orphanedResources.stage("delete", res.ResourceID(), "<cluster>", res.IdentifyingBytes())
case actual != expected:
c.logger.Log("warning", "resource to be synced has not been updated; skipping", "resource", resourceID)
case onlyLogging: // was not recorded as having been staged for application
c.logger.Log("info", "Garbage-Collection: dry-run, no deletion; cluster resource not in resources to be synced", "resource", resourceID)
case skipResource:
c.logger.Log("warning", "Garbage-Collection: resource to be synced has not been updated; skipping", "resource", resourceID)
continue
default:
// The checksum is the same, indicating that it was
Expand Down
17 changes: 17 additions & 0 deletions cluster/kubernetes/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,23 @@ metadata:
test(t, kube, "", "", false)
})

t.Run("sync adds and GCs dry run", func(t *testing.T) {
kube, _, cancel := setup(t)
defer cancel()

// without GC on, resources persist if they are not mentioned in subsequent syncs.
test(t, kube, "", "", false)
test(t, kube, ns1+defs1, ns1+defs1, false)
test(t, kube, ns1+defs1+defs2, ns1+defs1+defs2, false)
test(t, kube, ns3+defs3, ns1+defs1+defs2+ns3+defs3, false)

// with GC dry run the collect garbage routine is running but only logging results with out collecting any resources
kube.DryGC = true
test(t, kube, ns1+defs2+ns3+defs3, ns1+defs1+defs2+ns3+defs3, false)
test(t, kube, ns1+defs1+defs2, ns1+defs1+defs2+ns3+defs3, false)
test(t, kube, "", ns1+defs1+defs2+ns3+defs3, false)
})

t.Run("sync won't incorrectly delete non-namespaced resources", func(t *testing.T) {
kube, _, cancel := setup(t)
defer cancel()
Expand Down
20 changes: 11 additions & 9 deletions cmd/fluxd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func main() {
// syncing
syncInterval = fs.Duration("sync-interval", 5*time.Minute, "apply config in git to cluster at least this often, even if there are no new commits")
syncGC = fs.Bool("sync-garbage-collection", false, "experimental; delete resources that were created by fluxd, but are no longer in the git repo")
dryGC = fs.Bool("sync-garbage-collection-dry", false, "experimental; only log what would be garbage collected, rather than deleting. Implies --sync-garbage-collection")

// registry
memcachedHostname = fs.String("memcached-hostname", "memcached", "hostname for memcached service.")
Expand Down Expand Up @@ -370,6 +371,7 @@ func main() {
allowedNamespaces := append(*k8sNamespaceWhitelist, *k8sAllowNamespace...)
k8sInst := kubernetes.NewCluster(client, kubectlApplier, sshKeyRing, logger, allowedNamespaces, *registryExcludeImage)
k8sInst.GC = *syncGC
k8sInst.DryGC = *dryGC

if err := k8sInst.Ping(); err != nil {
logger.Log("ping", err)
Expand Down Expand Up @@ -485,15 +487,15 @@ func main() {

gitRemote := git.Remote{URL: *gitURL}
gitConfig := git.Config{
Paths: *gitPath,
Branch: *gitBranch,
SyncTag: *gitSyncTag,
NotesRef: *gitNotesRef,
UserName: *gitUser,
UserEmail: *gitEmail,
SigningKey: *gitSigningKey,
SetAuthor: *gitSetAuthor,
SkipMessage: *gitSkipMessage,
Paths: *gitPath,
Branch: *gitBranch,
SyncTag: *gitSyncTag,
NotesRef: *gitNotesRef,
UserName: *gitUser,
UserEmail: *gitEmail,
SigningKey: *gitSigningKey,
SetAuthor: *gitSetAuthor,
SkipMessage: *gitSkipMessage,
}

repo := git.NewRepo(gitRemote, git.PollInterval(*gitPollInterval), git.Timeout(*gitTimeout), git.Branch(*gitBranch))
Expand Down

0 comments on commit e3a28e4

Please sign in to comment.