Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: labelling resources #250

Closed
wants to merge 6 commits into from
Closed

WIP: labelling resources #250

wants to merge 6 commits into from

Conversation

captncraig
Copy link
Contributor

This is my attempt at implementing just resource labeling, independently of any pruning proposals.

Implements #249

pkg/spec/spec.go Outdated
// set the name field
config.Metadata.Name = name
// set the name field if not given in spec
if config.Metadata.Name == "" {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was unsure about this change. The spec files have a name in them, but it was being overwritten with the directory path which is an invalid label. I need to understand the context here better on why we were overwriting it in the first place.

Copy link
Member

Choose a reason for hiding this comment

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

Don't do it this way. The filepath is Tanka's source of truth. Instead, just sanitize the filepath, by substituting all / with -, as my original PR did:

func (m Metadata) NameLabel() string {
return strings.Replace(m.Name, "/", ".", -1)
}

The fact we have names in the spec.json is just a bad side-effect from json marshalling, because we need the field to be included when marshalling for passing to Jsonnet, we can't omitempty or - it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, makes sense... sort of. I guess it does root the file system at the ksonnet folder somehow, so that helps it be deterministic I suppose. tanka.dev/environment: environments.dns.eu-west2.kube-system is a little bit of a verbose env name, but that's ok.

Copy link
Member

@sh0rez sh0rez left a comment

Choose a reason for hiding this comment

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

This is cool! Some comments :)

pkg/spec/spec.go Outdated
// set the name field
config.Metadata.Name = name
// set the name field if not given in spec
if config.Metadata.Name == "" {
Copy link
Member

Choose a reason for hiding this comment

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

Don't do it this way. The filepath is Tanka's source of truth. Instead, just sanitize the filepath, by substituting all / with -, as my original PR did:

func (m Metadata) NameLabel() string {
return strings.Replace(m.Name, "/", ".", -1)
}

The fact we have names in the spec.json is just a bad side-effect from json marshalling, because we need the field to be included when marshalling for passing to Jsonnet, we can't omitempty or - it.

for _, manifest := range state {
labels := manifest.Metadata().Labels()
labels["app.kubernetes.io/managed-by"] = "tanka"
labels["tanka.dev/environment"] = env.Metadata.Name
Copy link
Member

Choose a reason for hiding this comment

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

These should be constants:

const (
   LabelPrefix = "tanka.dev"
   LabelEnvironment = LabelPrefix+"/environment"
)

}

func workflowFlags(fs *pflag.FlagSet) *workflowFlagVars {
v := workflowFlagVars{}
fs.StringSliceVarP(&v.targets, "target", "t", nil, "only use the specified objects (Format: <type>/<name>)")
v.applyLabels = fs.BoolP("label", "l", false, "Apply tanka metadata labels to all resources")
Copy link
Member

Choose a reason for hiding this comment

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

having this as a feature flag sounds dangerous – people will forget to pass it, resulting in unset labels for subsets of resources. I see two options here:

  1. Just do it. While it will cause changes for every environment, these are purely informative.
  2. Feature-flag it in spec.json. See my original pruning PR for that:
    InjectLabels InjectLabels `json:"injectLabels,omitempty"`

Copy link
Contributor Author

@captncraig captncraig Apr 3, 2020

Choose a reason for hiding this comment

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

I'm gonna go with 1. I did intend to switch from opt-in to opt-out at some point in the future, but honestly this is either something that should be done or it isn't.

return &ParseResult{
Resources: rec,
Env: env,
}, nil
}

func applyLabels(state manifest.List, env *v1alpha1.Config) {
Copy link
Member

Choose a reason for hiding this comment

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

This does not belong here, it should be part of Reconcile() which is meant to transform resources

Copy link
Member

Choose a reason for hiding this comment

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

Also I'd prefer not to have functions that modify their input variables. Given this is fairly short, just put it into Reconcile

@@ -145,6 +145,13 @@ func (m Metadata) Labels() map[string]interface{} {
return m["labels"].(map[string]interface{})
}

func (m Metadata) SetLabel(key, value string) {
Copy link
Member

Choose a reason for hiding this comment

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

You don't need that, m.Labels() already makes sure it returns a valid map[string]interface{}. Again for modifying maps, I prefer to do it using the Go bracket syntax, because it makes clear that you modify the pointer map there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

m.Labels() does return a new map, but it does not assign it back into m["labels"], so changes don't stick.
At first I just changed Labels() to do m["labels"] = make...., but I didn't want it to create an empty map simply because something wanted to read the collection.

But if we are going toward the "just do it" approach to labelling, that is not a concern.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I mixed up code in my head, I changed it in my PR so it creates AND returns if nil. I'd go forward like so

Copy link
Member

Choose a reason for hiding this comment

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

Basically nil labels is a thing related to the Go type system, but logically equivalent to an empty map. So it's fine to initiate and return one in case

@captncraig
Copy link
Contributor Author

Superceded by #251

@captncraig captncraig closed this Apr 7, 2020
@sh0rez sh0rez deleted the labels branch April 8, 2020 08:58
@captncraig captncraig restored the labels branch April 16, 2020 15:26
@captncraig captncraig reopened this Apr 16, 2020
@sh0rez
Copy link
Member

sh0rez commented Apr 16, 2020

See 347c057 for how to fix the unit tests

@captncraig captncraig closed this Apr 30, 2020
@sh0rez sh0rez deleted the labels branch July 1, 2020 13:40
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.

2 participants