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

Issue #219: added PreRunChain and PostRunChain hooks #220

Closed
wants to merge 3 commits into from

Conversation

algrebe
Copy link

@algrebe algrebe commented Jan 8, 2016

PreRunChain functions run in the order of root to child.
PostRunChain functions run in the order of child to root.

The overall exection order for a command is
PreRunChain
PersistentPreRun
PreRun
Run
PostRun
PersistentPostRun
PostRunChain

The following gist describes the usage and functionality
https://gist.github.com/algrebe/23cc8bf4739a129a6d0d

PreRunChain functions run in the order of root to child.
PostRunChain functions run in the order of child to root.

The overall exection order for a command is
PreRunChain
PersistentPreRun
PreRun
Run
PostRun
PersistentPostRun
PostRunChain

The following gist describes the usage and functionality
https://gist.github.com/algrebe/23cc8bf4739a129a6d0d
@mitake
Copy link

mitake commented Jan 12, 2016

Hi @algrebe , @spf13 , nice to meet you.

I'm using cobra and I really want this feature! @spf13 do you have a plan to merge this PR?

mitake added a commit to mitake/etcd that referenced this pull request Jan 12, 2016
ToDo: use this spf13/cobra#220
@algrebe
Copy link
Author

algrebe commented Jan 12, 2016

@mitake Hi there. Yes, I'm waiting for it to be pulled too after a review - I think they might want a better name for it.
@eparis was actively following up with me regarding #216
so I guess its just a matter of time.

@mitake
Copy link

mitake commented Jan 12, 2016

@algrebe thanks for your reply, I'm looking forward to seeing next news!

@spf13
Copy link
Owner

spf13 commented Jan 12, 2016

I'm fine with the functionality in general. I'm a bit worried this is a bit of an overcomplicated solution, but I must admit I don't really understand the use cases that would require all of this. This totals up to 7 different Run actions per command. It seems like overkill.

Not a criticism, but more of a request to help me understand why we need all of these. It seems like a simpler approach could exist that would give us all the functionality we need.

@algrebe
Copy link
Author

algrebe commented Jan 12, 2016

@spf13 thanks for your reply
@spf13 good point. Before taking any new functionality, you should decide whether this is required, and whether we can make do with what is there.

  1. Run function is needed to run the command.
  2. Pre and Post are needed as hooks just before/after the command.
  3. Persistent functions (existing logic) that are inherited and can be overridden.

For me, I just need something that always runs - irrespective of whether the child has its own hooks or not. I had always assumed Peristent* did this, but turns out they can be overridden. Hence, I would need
4. Functions that cannot be overridden and run whenever any of its children / self is executed.

As for the usecase - this was the issue I was facing #219 ( setting log levels and profiler at the root, and stopping it at the root - where I have access to the object that starts it )
Also, I feel a parent should have the option of running something irrespective of the child.

I have a suggestion, which may / may not be acceptable but just throwing it out here -
Can the *Chain functions take the place of Persistent* functions ? Since Persistent actually means always run.

@spf13
Copy link
Owner

spf13 commented Jan 12, 2016

Chain without persistent makes sense to me.

Should the default behavior of pre and post just be behavior described as
chain here? I feel like we can probably cover all these use cases with just
that.

On Tue, Jan 12, 2016 at 2:02 PM Anthony [email protected] wrote:

@spf13 https://github.com/spf13 thanks for your reply
@spf13 https://github.com/spf13 good point. Before taking any new
functionality, you should decide whether this is required, and whether we
can make do with what is there.

  1. Run function is needed to run the command.
  2. Pre and Post are needed as hooks just before the command.
  3. Persistent functions (existing logic ) that are inherited and can
    be overridden.

For me, I just need something that always runs - irrespective of whether
the child has its own hooks or not. I had always assumed Peristent* did
this, but turns out they can be overridden. Hence, I would need
4. Functions that cannot be overridden and run whenever any of its
children / self is executed.

As for the usecase - this was the issue I was facing #219
#219 .
Also, I feel a parent should have the option of running something
irrespective of the child.

I have a suggestion, which may / may not be acceptable but just throwing
it out here -
Can the Chain functions take the place of Persistent functions ? Since
Persistent actually means always run.


Reply to this email directly or view it on GitHub
#220 (comment).

@algrebe
Copy link
Author

algrebe commented Jan 12, 2016

Chain without persistent makes sense to me.
I'm not sure what you meant by this - chain should exist, persistent shouldnt ?

Should the default behavior of pre and post just be behavior described as
chain here

@spf13 Yes - makes sense to me
Shall I modify this pull request to remove the chains and put that behavior in Pre and Post ?

This is a change in the existing functionality though, so previous users will have to be aware that Pre and Post have changed right ?

@spf13
Copy link
Owner

spf13 commented Jan 12, 2016

Let's have @eparis weigh in first.
On Tue, Jan 12, 2016 at 2:59 PM Anthony [email protected] wrote:

@spf13 https://github.com/spf13 Yes - makes sense to me.
Shall I modify this pull request to remove the chains and put that
behavior in Pre and Post ?

This is a change in the existing functionality though, so previous users
will have to be aware that Pre and Post have changed right ?


Reply to this email directly or view it on GitHub
#220 (comment).

@eparis
Copy link
Collaborator

eparis commented Jan 12, 2016

I'll start with that fact that I think chaining makes more sense than what we have now. What we have now is copying the Flags()/PersistentFlags() where 'chaining' just doesn't make sense.

We have what we have so I'm all over the place on what to do. Imagine I have a subcommand pre/post that is calling the parent command pre/post. With a change to make 'persistent' 'chained' my parent command is going to get called twice.

Imagine the same case where the parent pre/post isn't called today and shouldn't be, now it will be and the user of cobra won't have a reasonable way to know of this change in behavior.

2.0 API should ONLY have chained....

@spf13
Copy link
Owner

spf13 commented Jan 12, 2016

I agree. There's a good solution here thought that doesn't break compatibility and doesn't introduce a more complicated mechanism.

We add a flag to Cobra that defaults to the current behavior, but can be flipped to the chain behavior. Cobra 2.0 we keep the flag, but change the default. Cobra 3.0 we remove the flag.

That way new implementations can immediately take advantage of this cleaner approach while existing implementations can have time to migrate.

Does that make sense?

I recognize it's a big change, but I'm super weary of adding complexity to the interface and would much prefer to refine and simplify what we have now instead. If we can do that without introducing breaking changes that I think it's a win/win.

@eparis
Copy link
Collaborator

eparis commented Jan 12, 2016

@spf13 +1

@bep
Copy link
Collaborator

bep commented Jan 12, 2016

+1

@spf13
Copy link
Owner

spf13 commented Jan 12, 2016

@algrebe can you update the PR accordingly? I'd gladly merge.

@algrebe
Copy link
Author

algrebe commented Jan 13, 2016

@spf13 yes, this sounds good.

Just to confirm

  1. Add a flag to cobra ( --use-chain-hooks ) that is false by default
  2. PreRun and PostRun examine the --use-chained-hooks to decide whether to chain or not.

I'm confused about the order:
Currently PersistentPreRun is called before PreRun, and PersistentPostRun after PostRun.
If there is chaining, where would you want it ? Before PersistentPreRun / After PostRun or like how it is right now? Or depending on the flag ?

mitake added a commit to mitake/etcd that referenced this pull request Jan 13, 2016
This commit adds flags for profiling with runtime/pprof to storage
put:
- --cpuprof-path: specify a path of CPU profiling result, if it is not
    empty, profiling is activated
- --memprof-path: specify a path of heap profiling result, if it is not
    empty, profiling is activated

Of course, the flags should be added to RootCmd ideally. However,
adding common flags that shared by children command requires the
ongoing PR: spf13/cobra#220 . Therefore this
commit adds the flags to storage put only.
@spf13
Copy link
Owner

spf13 commented Jan 13, 2016

We don't need persistent anymore. Just chaining.

With chaining it should cascade down from the root to the run of the
executed command (pre) then back the other direction with the post.
On Wed, Jan 13, 2016 at 1:34 AM Anthony [email protected] wrote:

@spf13 https://github.com/spf13 yes, this sounds good.

Just to confirm

  1. Add a flag to cobra ( --use-chain-hooks ) that is false by default
  2. PreRun and PostRun examine the --use-chained-hooks to decide whether to
    call it or not.

I'm confused about the order:
Currently PersistentPreRun is called before PreRun, and PersistentPostRun
after PostRun.
If there is chaining, where would you want it ? Before PersistentPreRun /
After PostRun or like how it is right now? Or depending on the flag ?


Reply to this email directly or view it on GitHub
#220 (comment).

@eparis
Copy link
Collaborator

eparis commented Jan 13, 2016

Also I don't know about --use-chain-hooks. The end user shouldn't (need) to know about chaining, only the programmer. Which makes that seem like an external variable, UseChainHooks.

However I'm not sure what behavior we should get if the var is set on the root command but not on the subcommand being executed...

@spf13
Copy link
Owner

spf13 commented Jan 13, 2016

It should only be able to be set (or checked) on the root. It's effectively
global. This can be accomplished with private fields and functions. See how
Exec() is crafted.

On Wed, Jan 13, 2016 at 8:53 AM Eric Paris [email protected] wrote:

Also I don't know about --use-chain-hooks. The end user shouldn't (need)
to know about chaining, only the programmer. Which makes that that an
external variable UseChainHooks.

However I'm not sure what behavior we should get if the var is set on the
root command but not on the subcommand being executed...


Reply to this email directly or view it on GitHub
#220 (comment).

This reverts commit 3dbb5be.
As part of spf13#220
PreRunChain and PostRunChain aren't required - the PersistentRun functions
need to be modified
Added the functionality for persistent functions to chain
from root to child in the case of PersistentPreRun and
from child to root in the case of PersistentPostRun.

Added a global internal variable useChainHooks which decides
whether to use chain feature, or use the previous logic of nearest
defined ancestor.
This variable useChainHooks is disabled by default in this commit.
Developers importing the cobra package can enable it using the
function EnableChainHooks() or disable it using DisableChainHooks().
However, these functions may be called only once externally, preferably
in the init of the developers main program.
@algrebe
Copy link
Author

algrebe commented Jan 13, 2016

@spf13 Hey, I think I've got a neat solution based on all the feedback - here it is.
You can also check out this gist https://gist.github.com/algrebe/cae234e77dae809bfe18
to test out its functionality.

mitake added a commit to mitake/etcd that referenced this pull request Jan 13, 2016
This commit adds flags for profiling with runtime/pprof to storage
put:
- --cpuprof-path: specify a path of CPU profiling result, if it is not
    empty, profiling is activated
- --memprof-path: specify a path of heap profiling result, if it is not
    empty, profiling is activated

Of course, the flags should be added to RootCmd ideally. However,
adding common flags that shared by children command requires the
ongoing PR: spf13/cobra#220 . Therefore this
commit adds the flags to storage put only.
mitake added a commit to mitake/etcd that referenced this pull request Jan 14, 2016
This commit adds flags for profiling with runtime/pprof to storage
put:
- --cpuprofile: specify a path of CPU profiling result, if it is not
    empty, profiling is activated
- --memprofile: specify a path of heap profiling result, if it is not
    empty, profiling is activated

Of course, the flags should be added to RootCmd ideally. However,
adding common flags that shared by children command requires the
ongoing PR: spf13/cobra#220 . Therefore this
commit adds the flags to storage put only.
mitake added a commit to mitake/etcd that referenced this pull request Jan 14, 2016
This commit adds flags for profiling with runtime/pprof to storage
put:
- --cpuprofile: specify a path of CPU profiling result, if it is not
    empty, profiling is activated
- --memprofile: specify a path of heap profiling result, if it is not
    empty, profiling is activated

Of course, the flags should be added to RootCmd ideally. However,
adding common flags that shared by children command requires the
ongoing PR: spf13/cobra#220 . Therefore this
commit adds the flags to storage put only.
@spf13
Copy link
Owner

spf13 commented Jan 18, 2016

@algrebe I think we can do this without the persistent funcs at all... or at least I can't think of why we would need them. Just Pre & Post with a toggle option to make them universally chain-able or not.

Am I oversimplifying it?

@algrebe
Copy link
Author

algrebe commented Jan 18, 2016

@spf13 I cant find a reason where someone would want a hybrid of both chaining and running a hook just for that command in the same setup, so simplifying it makes sense to me.
Although, just in case we've missed a valid scenario - this means loss of a feature right ? Which can easily be introduced later if necessary I guess. Shall we wait for others to pitch on or should I go ahead with the changes mentioned ?

@spf13
Copy link
Owner

spf13 commented Jan 18, 2016

We should talk to @eparis. I'm not sure how much this existing feature is
in use. I don't use it, but I have far from the most complex usage of Cobra
out there. I'm ok with a breaking change if it doesn't affect many people.
If it does affect people then we should hold off on taking it out until we
make a breaking release.

@algrebe
Copy link
Author

algrebe commented May 21, 2016

@spf13 @eparis Hi there ! Long time. I was looking at the issues on the page and #252 seems related to this as well. Please let me know what else I can do to take this feature to completion.

@lukasmalkmus
Copy link
Contributor

@spf13 @eparis Hi. Don't want to bother you but I see a lot of open PRs and issues. Some are months old. Is this project still maintained?

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.

6 participants