Skip to content

Allow running helm against a subsets of charts in a file#30

Merged
mumoshu merged 5 commits into
roboll:masterfrom
awwithro:chart_filter
Mar 23, 2018
Merged

Allow running helm against a subsets of charts in a file#30
mumoshu merged 5 commits into
roboll:masterfrom
awwithro:chart_filter

Conversation

@awwithro
Copy link
Copy Markdown
Contributor

Similar to what's described in #8

Globbing isn't useful for my particular workflow but I do have a large helmfile where its useful to run just one or two charts out of the entire file.

Comment thread state/state.go Outdated

"github.com/roboll/helmfile/helmexec"

yaml "gopkg.in/yaml.v1"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My IDE runs go fmt so there are a few formatting changes not directly related to the PR. Not sure if you have strong feelings on that.

@awwithro
Copy link
Copy Markdown
Contributor Author

awwithro commented Feb 6, 2018

@roboll ping! Any feedback on this PR?

@sstarcher
Copy link
Copy Markdown
Contributor

Anything needed to get this merged

@roboll
Copy link
Copy Markdown
Owner

roboll commented Feb 26, 2018

@sstarcher I haven't been using the tool lately, so just time to review and test.

If you (or anyone else) are actively using the tool and can confirm it works as expected, I'll accept the PR.

@sstarcher
Copy link
Copy Markdown
Contributor

I'll make some time to test it out. Thanks

@sstarcher
Copy link
Copy Markdown
Contributor

@roboll are you using something else to accomplish similar functionality to helmfile?

@roboll
Copy link
Copy Markdown
Owner

roboll commented Feb 26, 2018

@sstarcher nope, tool is still relevant, just not doing anything with helm at the moment.

@mumoshu
Copy link
Copy Markdown
Collaborator

mumoshu commented Feb 27, 2018

I like this feature!

However, I'm afraid if merging this prevents a similar but a more high-level filtering feature like @xeor proposed in #28?
Can I contribute the impl for #28 in addition to this?

@sstarcher
Copy link
Copy Markdown
Contributor

I would not see this as mutually exclusive with #28

@awwithro
Copy link
Copy Markdown
Contributor Author

awwithro commented Feb 27, 2018 via email

Comment thread state/state.go Outdated
for _, name := range chartNames {
missingName := true
for _, chart := range state.Charts {
if chart.Name == name {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly a nit but I wanted to confirm if, probably you're confusing release name vs chart name?
ChartSpec.Name stands for release name, whereas ChartSpec.Chart is the name of chart used to create the release.
Also see #25 for more context.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to fix the terminology issue starting #35. So I'd fix it on my side if necessary.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your intention is to filter releases by release names rather than to filter charts by chart names, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, I see you've made things more consistent across the board (and more precise) in your PR. I'll rebase and fix my terminology.

@mumoshu mumoshu mentioned this pull request Mar 1, 2018
@awwithro
Copy link
Copy Markdown
Contributor Author

awwithro commented Mar 3, 2018

@mumoshu PTAL, I've switched the terminology to reference release instead of chart which looks consistent with your rewrite.

Comment thread state/state.go
}

func (state *HelmState) DiffReleases(helm helmexec.Interface, additonalValues []string) []error {
func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []string) []error {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch 👍

Comment thread main.go Outdated
Usage: "Set namespace. Uses the namespace set in the context by default",
},
cli.StringSliceFlag{
Name: "release-name, r",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry but honestly saying, I'm not yet sure if this is the right name(if there's one) which describes the feature.
More concretely, I imagine that one would misunderstand this as a flag used for somehow overriding release names, which isn't true of course.

Instead, could this be any of the followings?

  1. helmfile sync --only myrelease1,myrelease2
    • not very intuitive as it isn't clear that what we can filter & by what we can filter releases
  2. helmfile sync --only-releases myrelease1,myrelease2
    • it isn't clear that by what we can filter releases
  3. helmfile sync --filter-releases myrelease1,myrelease2
    • same as 3
  4. helmfile sync --filter-releases-by-names myrelease1,myrelease2
    • imho, too verbose
  5. helmfile sync --filter-releases name=myrelease1,myrelease2
    • what if we wanted to support Tags? #28? --filter-releases tag=tier1:frontend? not sure i could correctly differentiate = and : :)
  6. helmfile sync myrelease1,myrelease2
  7. helmfile sync myrelease1 myrelease2

I slightly prefer 7 as it straightly maps to my mental model that helmfile is working against releases in the first place. It would also look familiar to ones used to kubectl. kubectl get po works against all the pods, whereas kubectl get po foo filters the target to a single pod.

A nice side-effect of it is that we now have a natural integration with shell brace expansion e.g. helmfile sync myrelease{1,2} 😃

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would either recommend 7 or helmfile sync --filter name=myrelease Where in the future we could support more filters

Copy link
Copy Markdown
Contributor Author

@awwithro awwithro Mar 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helmfile sync --filter name=myrelease seems the most natural to me as well considering the proposed feature to use tags as a filter.

  1. is nice and clean but I don't think would be extended with a tag structure as cleanly. It would be less obvious what the behavior would be with names and tags. helmfile sync --tags tier:frontend myrelease1 myrelease2 would that apply the intersection or union of the two filters? This question stands either way but I think its more clear using a --filter flag that either tags or names should be used.

I suppose 7 could lead to helmfile sync tag:tier=frontend or similar but that doesn't seem as clean to me

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awwithro for supporting and/or something like
helmfile sync --filter name=bob,tier=frontend --filter name=sam
Any release that makes name=bob and tier=frontend AND any chart that has the name sam.

That would allow us to support and/or logic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that makes sense to me, intersection within a filter and a union of all filters. I'll start work on the implementation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awwithro thanks that work will help toward the full tag/filter implementation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awwithro Thanks for your efforts! Please let us know if there's anything we can help. Probably questions regarding implementation, design, testing, etc?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @mumoshu I've been a bit busy at work and haven't had a chance to circle back on this quite yet. I did have some questions though. I believe you're on the kubernetes slack? I can find you there

Comment thread state/state_test.go Outdated
}
}

func TestReleaseFilter(t *testing.T) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@mumoshu
Copy link
Copy Markdown
Collaborator

mumoshu commented Mar 4, 2018

@awwithro Wow, thanks for your efforts! The implementation looks awesome. I really appreciate you adding a test, too!

My final point is about how we should name the flag. WDYT?

@mumoshu
Copy link
Copy Markdown
Collaborator

mumoshu commented Mar 13, 2018 via email

@mumoshu
Copy link
Copy Markdown
Collaborator

mumoshu commented Mar 16, 2018

Started talking with @awwithro towards finishing this

Comment thread README.md Outdated
# Published chart example
- name: vault # name of this release
namespace: vault # target namespace
tags: # Arbitrary key value pairs for filtering releases
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using labels instead of tags? would be consistent with k8s.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good in general.

One thing I'm wondering on top of that though is - Would it also be reasonable to rename the --tags flag to --selector for more consistency with k8s'?

And in that case, I can't help expecting that labels could be somehow propagated as values to helm charts, so that we can use the same set of labels to filter both releases(helmfile --selector ...) and resulting k8s objects(kubectl get --selector ...). What do you think about that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the -l,--selector standardization. I'll switch to that. As far as propagating labels to the resulting k8s objects. I like the idea. I'm not sure how the implementation would work exactly since the objects would be managed via helm but is out of scope for this PR

@awwithro
Copy link
Copy Markdown
Contributor Author

awwithro commented Mar 21, 2018

@mumoshu PTAL, I refactored things similar to what we discussed with tags/names. What do you think? Anything missing or in need of changing?

@sstarcher
Copy link
Copy Markdown
Contributor

I tested running a single example and was initially confused that the globals don't get passed down to the sub functions

Works
helmfile --tags name=filebeat diff

Does not work
helmfile diff --tags name=filebeat

@sstarcher
Copy link
Copy Markdown
Contributor

Also verified != works

Comment thread state/state_test.go
- name: myrelease3
chart: mychart3
tags:
tier: backend
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for writing an effective test 👍

Copy link
Copy Markdown
Collaborator

@mumoshu mumoshu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one thing! Otherwise LGTM.

Comment thread state/state.go Outdated
}
release.Tags["name"] = release.Name
if filter.Match(release) {
// Only add a release once
Copy link
Copy Markdown
Collaborator

@mumoshu mumoshu Mar 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality is awesome!
If I could ask more, probably you can change the nesting so that there would be less code, plus and a bit more efficiency?

var filters := []ReleaseFilter{}
for _, tag := range tags {
    f, err := ParseTags(tag)
    // snip - error handling
    filters = append(filters, f)
}
for _, r := range state.Releases {
    for _, f := range filters {
        if f.Match(releases) {
            filteredReleases = append(filteredReleases, release)
            continue
        }
    }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Copy Markdown
Collaborator

@mumoshu mumoshu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self for later follow-up

Comment thread README.md Outdated
# Published chart example
- name: vault # name of this release
namespace: vault # target namespace
tags: # Arbitrary key value pairs for filtering releases
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: change the remaining tags: to labels:

Comment thread README.md Outdated
--file FILE, -f FILE load config from FILE (default: "helmfile.yaml")
--quiet, -q silence output
--namespace value, -n value Set namespace. Uses the namespace set in the context by default
--tags value Only run using the releases that match tags. Tags can take the form of foo=bar or foo!=bar.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: change the remaining tags: to labels:

Comment thread README.md Outdated
- Relative paths referenced on the command line are relative to the current working directory the user is in

For additional context, take a look at [paths examples](PATHS.md)
## Tags Overview
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Tags -> Labels

Comment thread README.md Outdated
The `tags` parameter can be specified multiple times. Each parameter is resolved independently so a release that matches any parameter will be used. No newline at end of file
The `labels` parameter can be specified multiple times. Each parameter is resolved independently so a release that matches any parameter will be used.

`--selector tier=frontend --selector tier=backend` will select all the charts No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be --labels right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--selector,-l is consistent with kubectl and how it selects objects using labels. I'd used -l myself previously but I think having a common operation across tools is desirable.

Comment thread main.go
Name: "selector, l",
Usage: `Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar.
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
--selector tier=frontend,tier!=proxy --selector tier=backend. Will match all frontend, non-proxy releases AND all backend releases.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should all references to selector be changed to labels?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to k8s, the idea is that labels are on objects, and a selector selects based on labels

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh if that's the case the docs that are calling out --label should be changed right?

--labels tier=frontend,tier!=proxy --labels tier=backend. Will match all frontend, non-proxy releases AND all backend releases.

to

--selector tier=frontend,tier!=proxy --selector tier=backend. Will match all frontend, non-proxy releases AND all backend releases.```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed we should use --selector and -l, but we just need to make sure all the docs align.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be consistent across the docs now

Copy link
Copy Markdown
Contributor

@sstarcher sstarcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent work thanks for this

@sstarcher
Copy link
Copy Markdown
Contributor

After this is merged could we cut a release for secrets and this.

@mumoshu mumoshu merged commit 4b08ea9 into roboll:master Mar 23, 2018
@mumoshu
Copy link
Copy Markdown
Collaborator

mumoshu commented Mar 23, 2018

@awwithro @sstarcher Thank you very much for your efforts and supports!

@awwithro
Copy link
Copy Markdown
Contributor Author

thanks @mumoshu @sstarcher for the ideas and feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants