-
Notifications
You must be signed in to change notification settings - Fork 38
Distrogen update #372
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
Distrogen update #372
Conversation
braydonk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran a manual test and most things I tried seemed to work. I encountered one bug, which is that both a distrogen and .distrogen folder were generated.
I think it would be a good idea to put together project generation golden test cases, similar to what we have in testdata/generator, which are defined in distribution_test.go. You could also add full project generation test cases to check those goldens. There is certainly more we could do for testing, but I think at least having that would be a good start (and would catch the bug I encountered).
After that, the scratch folder can be removed and we can formally move this to in review.
cmd/distrogen/distribution.go
Outdated
| } | ||
|
|
||
| for _, tmpl := range templates { | ||
| logger.Debug("context of template", "ctx", tmpl.Context) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably get rid of these debug logs.
|
Please add a motivation to the PR description. What problem is this solving? It doesn't look like a trivial change and the uninformed reader is not going to understand what's happening here. |
ridwanmsharif
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a motivation to the PR description. What problem is this solving? It doesn't look like a trivial change and the uninformed reader is not going to understand what's happening here.
+1 to Jeffs comment, I got pretty lost in this deep dark forest so consider this a partial review for now
|
|
||
| var ErrComponentNotFound = errors.New("component not found") | ||
|
|
||
| type ComponentType string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] Why does this have to be of type string and not an enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more convenient to use it as a key to the registry when we're editing it based on the component type we're trying to add.
| type ComponentType string | ||
|
|
||
| const ( | ||
| Receiver ComponentType = "receiver" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting that we are adding support for all these types. Receivers I do get, but do we have any examples of why we think the others are useful too?
I'm trying to convince myself of a use case where we would want to do this? Is this motivated by the processors that the Ops Agent uses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of this PR was designed for the general use case, not just for us. There's no logical reason to lock down what types of custom components are allowed in a registry that I can think of.
| ) | ||
|
|
||
| type ProjectGenerator struct { | ||
| Spec *DistributionSpec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are all these exported? They seem to only be used within this package?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have been keeping the door open for restructuring the project; right now it's still a flat folder but it's possible it might become a cmd folder and then a separate package for the whole distrogen API. I haven't had any time to make a sweeping change like that but don't want to close the door on it either (it would be more annoying if these were all unexported and then had to all be renamed when it gets moved).
|
|
||
| type ProjectGenerator struct { | ||
| Spec *DistributionSpec | ||
| FileMode fs.FileMode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When is this set to something other than 0777? If we don't set it anything else, we don't need to be part of this struct, or part of the Get.*TemplateSet signatures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a bit of dev history with this one. When developing on a system with a particular umask set (which it actually is on our internal development machines) the files could be generated with permissions that caused building in Dockerfiles to not work. As a result I had to add the filemode to any os API calls. At first I used a global default variable for that, and opted to make it part of the structs so that if stuff got split up we wouldn't have to add it later.
We could make a choice that we don't need to ever change it and always refer to the global default. At the time I was messing with a number of different values but gave up and ended on 0777 just to make it work and have since forgotten about it.
| if err := os.MkdirAll(filepath.Join(generatePath, "templates"), pg.FileMode); err != nil { | ||
| dirErrors = append(dirErrors, err) | ||
| } | ||
| if _, err := os.Create(filepath.Join(generatePath, "templates", EMPTY_FILE_NAME)); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering why we create this file here manually but below we rely on the templates to create .distrogen/VERSION
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had an issue with go:embed where it couldn't find nested hidden files so it couldn't find the .distrogen folder. Now that I have fixed that will multiple go:embed this is no longer needed. I removed the manual creation of the .distrogen folder.
| Name: componentName, | ||
| } | ||
|
|
||
| switch componentType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
making this an enum like I suggested above should get rid of this switch statement with all fallthroughs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it was an enum we'd just move the switch case from here to where we use it to index the registry instead, idk which one is better seems like the same level of complexity
| @@ -0,0 +1,4 @@ | |||
| module {{ .Spec.Module }} | |||
|
|
|||
| go {{ .Spec.RenderGoMajorVersion }} | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels weird that we let people specify the go version but then only use the major version here.
I think typically in the go.mod file you can use the patch version too. And failing that you can also use the toolchain of the patch version you want. Like https://github.com/jaegertracing/jaeger/blob/fa9a5e7d31fcc1163b6bbed741dc288146871959/go.mod#L3-L5
Not saying we need to do this, but was wondering why we do what we do now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my research go.mod for the collector don't include the patch version
https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/go.mod
https://github.com/open-telemetry/opentelemetry-collector/blob/main/go.mod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether you include the patch or not is orthogonal to whether it's a collector or not. Sometimes in Go you need to specify a patch version if your code relies on some quirk of the language/toolchain that's only available after a certain patch level.
You can choose to outright disallow patch levels if you really think it's a pitfall, but if that's the case, do it loudly by raising an error instead of silently truncating it.
(Unfortunate that Go itself doesn't follow semver here... I would've said that RenderGoMajorVersion should actually be named RenderGoMajorAndMinorVersion, but no, that's actually what Go refers to as a major version...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a convention of the project (and in fact we got ourselves into trouble in the Collector for specifying the patch version of Go in our operations-go modules). If you specify the version it makes Go's automatic toolchain resolution do some automatic downloading of the version that some random module asked for. It might be fine for our case but I was just thinking we should follow the convention of upstream on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(doesn't need to block this PR, this is more of a general wondering)
Are there any docs explaining the need for a component registry?
If I'm wearing my component author hat, what kind of indexing does the registry provide that the built-in module/package management system in Go doesn't provide already? I'm already able to broadcast my component to the world with the tooling already available.
If I'm wearing my distro author hat, I can already identify components directly by their URI. What is the registry's indirection providing me?
We talked a bit offline about the challenges of working with components that aren't available from a proper GOPROXY or aren't available publicly, but the toolchain has e.g. GOPRIVATE for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be part of the more general distrogen breakdown doc I am working on, but I'll answer briefly here.
Registry gives us the following things currently:
- Allows us to use a logical name for a component rather than the whole URL in the
spec.yaml - Allows redirecting a module to a local package or import path, basically propagating the options available in OCB
It will enable the following unreleased things:
- Declaring a supported OTel Collector version. This looks fine right now cause we only refer to upstream, who tag the components based on the Collector release, but if anyone decides to tag things in ways that don't match upstream, this becomes confusing. We want distrogen to reconcile and complain about components it resolved that don't match the requested collector version.
- Propagating necessary Go replaces. Rather than needing to go out to a component's source repo and checking if they have any replaces that they need to function properly, distrogen will be able to recognize that it's pulled a component from a registry that is requiring certain module replacements and replicate them in the OCB manifest.
Deeper explanation will be part of the design document I'm working on for the latter two.
ridwanmsharif
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll let the two of you resolve the open threads, I think I'm okay with most of the answers given as is - we can iterate on the rest in follow up changes
# Conflicts: # cmd/distrogen/distribution.go # cmd/distrogen/testdata/generator/distribution/build_container/golden/spec.yaml
Updating distrogen to add full project generation. It assumes that there will always be one distribution per project.