diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index c01444cb8..ecb5dda7d 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -2,6 +2,7 @@ package kubernetes import ( "fmt" + "regexp" "strings" "github.com/Masterminds/semver" @@ -72,7 +73,7 @@ func New(c v1alpha1.Config) (*Kubernetes, error) { // ApplyOpts allow set additional parameters for the apply operation type ApplyOpts struct { - PruneOpts + *PruneOpts // force allows to ignore checks and force the operation Force bool @@ -114,7 +115,7 @@ func (k *Kubernetes) Apply(state manifest.List, opts ApplyOpts) error { return nil } - if err := k.prune(state, opts.PruneOpts); err != nil { + if err := k.prune(state, *opts.PruneOpts); err != nil { return errors.Wrap(err, "removing orphaned resources") } return nil @@ -122,7 +123,7 @@ func (k *Kubernetes) Apply(state manifest.List, opts ApplyOpts) error { // DiffOpts allow to specify additional parameters for diff operations type DiffOpts struct { - PruneOpts + *PruneOpts // Use `diffstat(1)` to create a histogram of the changes instead Summarize bool @@ -140,7 +141,7 @@ func (k *Kubernetes) Diff(state manifest.List, opts DiffOpts) (*string, error) { differs := []Differ{k.differs[strategy]} if opts.PruneOpts.Prune { - differs = append(differs, k.diffOrphaned(opts.PruneOpts.AllKinds)) + differs = append(differs, k.diffOrphaned(opts.PruneOpts.AllKinds, opts.PruneOpts.Targets)) } diff, err := multiDiff(state, differs) @@ -198,9 +199,9 @@ func diffParallel(diff Differ, state manifest.List, results chan (*string), errs results <- r } -func (k *Kubernetes) diffOrphaned(all bool) Differ { +func (k *Kubernetes) diffOrphaned(all bool, targets []*regexp.Regexp) Differ { return func(state manifest.List) (*string, error) { - orphan, err := k.listOrphaned(state, all) + orphan, err := k.listOrphaned(state, all, targets) if err != nil { return nil, err } @@ -231,10 +232,3 @@ func (k *Kubernetes) diffOrphaned(all bool) Differ { func (k *Kubernetes) Info() client.Info { return k.info } - -func objectspec(m manifest.Manifest) string { - return fmt.Sprintf("%s/%s", - m.Kind(), - m.Metadata().Name(), - ) -} diff --git a/pkg/kubernetes/prune.go b/pkg/kubernetes/prune.go index ae658d3a2..aa92c5554 100644 --- a/pkg/kubernetes/prune.go +++ b/pkg/kubernetes/prune.go @@ -1,8 +1,11 @@ package kubernetes import ( + "regexp" + "github.com/grafana/tanka/pkg/kubernetes/client" "github.com/grafana/tanka/pkg/kubernetes/manifest" + "github.com/grafana/tanka/pkg/kubernetes/util" "github.com/pkg/errors" ) @@ -48,10 +51,13 @@ type PruneOpts struct { // Skip verification and force deleting Force bool + + // Limit the working set to these objects + Targets []*regexp.Regexp } func (k *Kubernetes) prune(state manifest.List, opts PruneOpts) error { - orphan, err := k.listOrphaned(state, opts.AllKinds) + orphan, err := k.listOrphaned(state, opts.AllKinds, opts.Targets) if err != nil { return errors.Wrap(err, "listing orphaned objects") } @@ -66,7 +72,7 @@ func (k *Kubernetes) prune(state manifest.List, opts PruneOpts) error { // listOrphaned returns all resources known to the cluster not present in // Jsonnet -func (k *Kubernetes) listOrphaned(state manifest.List, all bool) (orphaned manifest.List, err error) { +func (k *Kubernetes) listOrphaned(state manifest.List, all bool, targets []*regexp.Regexp) (orphaned manifest.List, err error) { if k.orphaned != nil { return k.orphaned, nil } @@ -116,6 +122,7 @@ func (k *Kubernetes) listOrphaned(state manifest.List, all bool) (orphaned manif return nil, lastErr } + orphaned = util.FilterTargets(orphaned, targets) return orphaned, nil } diff --git a/pkg/kubernetes/reconcile.go b/pkg/kubernetes/reconcile.go index 1c2e103e4..ddd1fe7b6 100644 --- a/pkg/kubernetes/reconcile.go +++ b/pkg/kubernetes/reconcile.go @@ -8,9 +8,9 @@ import ( "github.com/pkg/errors" "github.com/stretchr/objx" - funk "github.com/thoas/go-funk" "github.com/grafana/tanka/pkg/kubernetes/manifest" + "github.com/grafana/tanka/pkg/kubernetes/util" "github.com/grafana/tanka/pkg/spec/v1alpha1" ) @@ -48,18 +48,7 @@ func Reconcile(raw map[string]interface{}, config v1alpha1.Config, targets []*re } // optionally filter the working set of objects - if len(targets) > 0 { - tmp := funk.Filter(out, func(i interface{}) bool { - p := objectspec(i.(manifest.Manifest)) - for _, t := range targets { - if t.MatchString(p) { - return true - } - } - return false - }).([]manifest.Manifest) - out = manifest.List(tmp) - } + out = util.FilterTargets(out, targets) // Stable output order sort.SliceStable(out, func(i int, j int) bool { diff --git a/pkg/kubernetes/util/targetexp.go b/pkg/kubernetes/util/targetexp.go index 79f1d5c9e..23b027dd0 100644 --- a/pkg/kubernetes/util/targetexp.go +++ b/pkg/kubernetes/util/targetexp.go @@ -4,6 +4,9 @@ import ( "fmt" "regexp" "strings" + + "github.com/grafana/tanka/pkg/kubernetes/manifest" + funk "github.com/thoas/go-funk" ) type ErrBadTargetExp struct { @@ -38,3 +41,29 @@ func MustCompileTargetExps(strs ...string) (exps []*regexp.Regexp) { } return exps } + +// FilterTargets filters list to only include those matched by targets +func FilterTargets(list manifest.List, targets []*regexp.Regexp) manifest.List { + if len(targets) == 0 { + return list + } + + tmp := funk.Filter(list, func(i interface{}) bool { + p := objectspec(i.(manifest.Manifest)) + for _, t := range targets { + if t.MatchString(p) { + return true + } + } + return false + }).([]manifest.Manifest) + + return manifest.List(tmp) +} + +func objectspec(m manifest.Manifest) string { + return fmt.Sprintf("%s/%s", + m.Kind(), + m.Metadata().Name(), + ) +} diff --git a/pkg/tanka/tanka.go b/pkg/tanka/tanka.go index ae23f8d8d..bbf411c1e 100644 --- a/pkg/tanka/tanka.go +++ b/pkg/tanka/tanka.go @@ -24,9 +24,13 @@ func parseModifiers(mods []Modifier) *options { mod(o) } + // finish prune object + o.prune.Targets = o.targets o.prune.Force = o.apply.Force - o.apply.PruneOpts = o.prune - o.diff.PruneOpts = o.prune + + // add finished object to apply and diff (they need this info as well) + o.apply.PruneOpts = &o.prune + o.diff.PruneOpts = &o.prune return o } diff --git a/pkg/tanka/workflow.go b/pkg/tanka/workflow.go index 5ef45fce3..6f541ac8b 100644 --- a/pkg/tanka/workflow.go +++ b/pkg/tanka/workflow.go @@ -27,9 +27,7 @@ func Apply(baseDir string, mods ...Modifier) error { return err } - diff, err := kube.Diff(p.Resources, kubernetes.DiffOpts{ - PruneOpts: opts.prune, - }) + diff, err := kube.Diff(p.Resources, kubernetes.DiffOpts{}) if err != nil { return errors.Wrap(err, "diffing") }