-
Notifications
You must be signed in to change notification settings - Fork 15
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
Add new build options (#7) #13
Conversation
pkg/gornir/gornir.go
Outdated
} | ||
|
||
// InventoryPlugin is an Inventory Source | ||
type InventoryPlugin interface { |
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.
Do we need this interface with this pattern? To me it feels that it's not needed as the creation is independent from Gornir, like the Logger.
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.
Yeah, probably not right now. I'm just trying to put a stake in the ground for all new Inventory sources, that they should provide a Create function that returns an Inventory
.
Also for testing, I want to create a couple of hosts manually and pass that as a list to a Create function, so you end up with an Inventory
.
Having said that, I agree with you and is not necessary at this point in time.
pkg/gornir/gornir.go
Outdated
} | ||
|
||
// WithFilter creates a new Gornir with a filtered Inventory. | ||
func (gr *Gornir) WithFilter(f FilterFunc) *Gornir { |
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'd prefer calling this just Filter
, mostly for consistency; WithSomething
attaches that Something
to the returned object while Filter
applies a transformation (the inventory is still the same, it just changed due to the filter function).
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 want with WithFilter
for a couple of reasons:
-
Filter
takes a context right now, which I would prefer to avoid until deemed necessary. -
original.WithFilter(filter)
returns a completely newGornir
with a filter applied over the contents oforiginal
.original
remains unmodified, so we didn't filter it. -
Consistency across options; if starts with With, it's an option :-)
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 am good removing the context for now (I'd remove it in Inventory.Filter and FilterFunc too for consistency) but I am not sure WithFilter
is still a consistent name here as it does something different. The other With
methods receive attributes that are set in the new object (or options as you say). On the other hand, WithFilter
doesn't set an attribute, it applies a transformation on an existing attribute.
Another way of looking at this is that WithInventory
and WithLogger
(I also want to add WithRunner
so it doesn't have to be passed to Gornir.Run
each time but no need to do it in this PR) can be called in any order, that's not true for WithFilter
, again, because it doesn't set an attribute, it applies a transformation on an attribute.
And if that wasn't enough you can basically realize that WithFilter
is just a shorthand for gr.WithInventory(gr.Inventory.Filter(filterFunc))
. Filter
is also consistent with Inventory.Filter
.
Anyway, don't want to block this PR on this discussion so if you are still not convinced we can merge it anyway after removing the context everywhere and rehash it on a different PR :)
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 remove context from Filter
(and Inventory.Filter
, FilterFunc
), plus get rid of WithFilter
, then merge.
I'll add WithRunner
in another PR.
@@ -22,25 +22,24 @@ import ( | |||
) | |||
|
|||
func main() { |
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 need to update doc.go
as well
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.
Good catch, will address this.
Inventory: inventory, | ||
Logger: logger, | ||
} | ||
gr := gornir.New().WithInventory(inv).WithLogger(log) |
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 am thinking that maybe New
should require inv
and log
as parameters as they are both mandatory.
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.
What I thinking is New
should provide safe defaults instead. Something like an Empty Inventory
and logging from the standard library log
package (which doesn't satisfy the Logger
interface right now). I can address this in a different PR so it's clearly documented.
This way we keep the syntax clean.
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.
Ok, I have a different view here, I don't want defaults because I think everything should be a plugin. Also, creating as default an empty inventory has no value as it renders Gornir unusable.
Re using the standard log
package, it shouldn't be hard adding a plugin that wraps it.
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.
Yeah, let's keep it simple for now: gornir.New()
with no defaults. Let's have a separate discussion on what we want New
to become.
} | ||
|
||
// define a function we will use to filter the hosts | ||
filter := func(ctx context.Context, h *gornir.Host) bool { | ||
return h.Hostname == "dev1.group_1" || h.Hostname == "dev4.group_2" | ||
} | ||
|
||
gr := gornir.New().WithInventory(inv).WithLogger(log).WithFilter(filter) |
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.
WithFilter(filter)
is redundant here as it's called a couple of lines below.
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'd prefer to keep it there, and remove it in the other call, so we end up with:
gr := gornir.New().WithInventory(inv).WithLogger(log).WithFilter(filter)
results, err := gr.RunSync(
"What's my ip?",
runner.Parallel(),
&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
)
Which in my view, separate the two actions (building the inventory and running the task). But this is just my personal preference.
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 want to keep the old pattern to illustrate the builder pattern, people is free to use whatever pattern they prefer in their code but I want to make sure people sees something like this is possible:
gr := gornir.New()
...
results, err := gr.Filter(giveMeSpines).Run(...)
...
results, err = gr.Filter(giveMeLeaves).Run(...)
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.
Ok, I'll keep that example with this alternative and let the user choose which one they prefer in their code. Thanks.
This is awesome, it's what I was thinking of. Just a couple of minor comments but other than that this is great. |
Ok.
|
Ok, I believe this is closer to what @dbarrosop had in mind :-)
Logger creation doesn't return any error right now, we can look into in it the future if necessary.
I will add the runner next.