Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-15 Thread Renat Akhmerov

> On 15 Mar 2017, at 15:32, Adriano Petrich  wrote:
> 
>I was talking to some friends that have more (and more recent) experience 
> with standalone zope.interfaces inside other projects (last time I used it 
> was inside zope and 10 years ago) and I think it might be just overcomplexity 
> for our task at hand.

Yes, that’s what I thought too when I read your message. :)

Renat Akhmerov
@Nokia



__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-15 Thread Adriano Petrich
Renat,

   I was talking to some friends that have more (and more recent)
experience with standalone zope.interfaces inside other projects (last time
I used it was inside zope and 10 years ago) and I think it might be just
overcomplexity for our task at hand.

   Cheers,
  Adriano

On Wed, Mar 15, 2017 at 7:05 AM, Renat Akhmerov 
wrote:

> Well, zope is a cool thing I believe. We can consider to use it. I just
> don’t see what real advantage it’ll give us now.
> Essentially, what we’re trying to do now is pretty simple. We’re just
> defining one base class for all actions w/o talking
> about various modifications of this class yet.
>
> So if you see a concrete idea about using zope interfaces please share.
> I’m interested in that.
>
> Renat Akhmerov
> @Nokia
>
> On 14 Mar 2017, at 22:14, Adriano Petrich  wrote:
>
> Sorry if I'm missing the point here, and for being late on the discussion.
> But what about zope interfaces?
>
> Would not that be clearer?
>
>
>
> On Tue, Mar 14, 2017 at 11:39 AM, Dougal Matthews 
> wrote:
>
>>
>>
>> On 14 March 2017 at 11:14, Renat Akhmerov 
>> wrote:
>>
>>> Yeah, I finally understood too what Thomas meant.
>>>
>>> Just to clarify, I think mixed two different discussions here:
>>>
>>>1. Base framework for all actions residing in mistral-lib (what I
>>>was trying to discuss)
>>>2. The new design for OpenStack actions
>>>
>>>
>>> On #2 I agree with you that NovaAction.get_client(context) should work.
>>> No problem with that.
>>> And I believe that it doesn’t make sense to use multiple inheritance in
>>> this particular case, it’s
>>> simply not worth it.
>>>
>>> Getting back to #1.. Of course, using mixins can be problematic (method
>>> and state conflicts etc.).
>>> I think mixins is just one of the options that’s possible to use if we
>>> want to. Regular class inheritance
>>> is also an option I think. At this point if we just agree on action base
>>> class I think nothing prevents
>>> us from choosing how to evolve in the future. So just agreeing on the
>>> base class design seems
>>> to be sufficient for now. It’s just a base contract that a runner needs
>>> to be aware of (sorry for
>>> repeating this thought but I think it’s important). The rest is related
>>> with action developer
>>> convenience.
>>>
>>> I think the outstanding questions are;
>>>
>>> - should the context be a mixin or should run() always accept context?
>>>
>>>
>>> I’m for run() having “context” argument. Not sure why mixin is needed
>>> here. If an action doesn’t
>>> need context it can be ignored.
>>>
>>> - should async be a mixin or should we continue with the is_sync()
>>> method and overwriting that in the sublcass?
>>>
>>>
>>> I’m for is_sync() method as it is now. It’s more flexible and less
>>> confusing (imagine an action inheriting
>>> AsyncAction but having is_async() returning False).
>>>
>>> - should the openstack actions in mistral-extra be mixins?
>>>
>>>
>>> No, not at all. They don’t have to be. This is a different discussion I
>>> think. We need to collect what’s bad about
>>> the current OpenStack actions and think how to rewrite them (extract the
>>> common infrastructure they use,
>>> make them more extensible, etc.)
>>>
>>
>> +1 to all of the above, I think we are in complete agreement and this
>> will give us both a flexible interface and one that is easy to use and
>> understand.
>>
>>
>>
>>>
>>>
>>> Renat Akhmerov
>>> @Nokia
>>>
>>>
>>> 
>>> __
>>> OpenStack Development Mailing List (not for usage questions)
>>> Unsubscribe: openstack-dev-requ...@lists.op
>>> enstack.org?subject:unsubscribe
>>> 
>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>>
>>>
>>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e 
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-15 Thread Renat Akhmerov
Well, zope is a cool thing I believe. We can consider to use it. I just don’t 
see what real advantage it’ll give us now.
Essentially, what we’re trying to do now is pretty simple. We’re just defining 
one base class for all actions w/o talking
about various modifications of this class yet.

So if you see a concrete idea about using zope interfaces please share. I’m 
interested in that.

Renat Akhmerov
@Nokia

> On 14 Mar 2017, at 22:14, Adriano Petrich  wrote:
> 
> Sorry if I'm missing the point here, and for being late on the discussion. 
> But what about zope interfaces?
> 
> Would not that be clearer?
> 
>  
> 
> On Tue, Mar 14, 2017 at 11:39 AM, Dougal Matthews  > wrote:
> 
> 
> On 14 March 2017 at 11:14, Renat Akhmerov  > wrote:
> Yeah, I finally understood too what Thomas meant.
> 
> Just to clarify, I think mixed two different discussions here:
> Base framework for all actions residing in mistral-lib (what I was trying to 
> discuss)
> The new design for OpenStack actions
> 
> On #2 I agree with you that NovaAction.get_client(context) should work. No 
> problem with that.
> And I believe that it doesn’t make sense to use multiple inheritance in this 
> particular case, it’s
> simply not worth it.
> 
> Getting back to #1.. Of course, using mixins can be problematic (method and 
> state conflicts etc.).
> I think mixins is just one of the options that’s possible to use if we want 
> to. Regular class inheritance
> is also an option I think. At this point if we just agree on action base 
> class I think nothing prevents
> us from choosing how to evolve in the future. So just agreeing on the base 
> class design seems
> to be sufficient for now. It’s just a base contract that a runner needs to be 
> aware of (sorry for
> repeating this thought but I think it’s important). The rest is related with 
> action developer
> convenience.
> 
>> I think the outstanding questions are;
>> 
>> - should the context be a mixin or should run() always accept context? 
> 
> I’m for run() having “context” argument. Not sure why mixin is needed here. 
> If an action doesn’t
> need context it can be ignored.
> 
>> - should async be a mixin or should we continue with the is_sync() method 
>> and overwriting that in the sublcass?
> 
> I’m for is_sync() method as it is now. It’s more flexible and less confusing 
> (imagine an action inheriting
> AsyncAction but having is_async() returning False).
> 
>> - should the openstack actions in mistral-extra be mixins?
> 
> 
> No, not at all. They don’t have to be. This is a different discussion I 
> think. We need to collect what’s bad about
> the current OpenStack actions and think how to rewrite them (extract the 
> common infrastructure they use,
> make them more extensible, etc.)
> 
> +1 to all of the above, I think we are in complete agreement and this will 
> give us both a flexible interface and one that is easy to use and understand.
> 
>  
> 
> 
> Renat Akhmerov
> @Nokia
> 
> 
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe 
> 
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev 
> 
> 
> 
> 
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe 
> 
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev 
> 
> 
> 
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Adriano Petrich
Sorry if I'm missing the point here, and for being late on the discussion.
But what about zope interfaces?

Would not that be clearer?



On Tue, Mar 14, 2017 at 11:39 AM, Dougal Matthews  wrote:

>
>
> On 14 March 2017 at 11:14, Renat Akhmerov 
> wrote:
>
>> Yeah, I finally understood too what Thomas meant.
>>
>> Just to clarify, I think mixed two different discussions here:
>>
>>1. Base framework for all actions residing in mistral-lib (what I was
>>trying to discuss)
>>2. The new design for OpenStack actions
>>
>>
>> On #2 I agree with you that NovaAction.get_client(context) should work.
>> No problem with that.
>> And I believe that it doesn’t make sense to use multiple inheritance in
>> this particular case, it’s
>> simply not worth it.
>>
>> Getting back to #1.. Of course, using mixins can be problematic (method
>> and state conflicts etc.).
>> I think mixins is just one of the options that’s possible to use if we
>> want to. Regular class inheritance
>> is also an option I think. At this point if we just agree on action base
>> class I think nothing prevents
>> us from choosing how to evolve in the future. So just agreeing on the
>> base class design seems
>> to be sufficient for now. It’s just a base contract that a runner needs
>> to be aware of (sorry for
>> repeating this thought but I think it’s important). The rest is related
>> with action developer
>> convenience.
>>
>> I think the outstanding questions are;
>>
>> - should the context be a mixin or should run() always accept context?
>>
>>
>> I’m for run() having “context” argument. Not sure why mixin is needed
>> here. If an action doesn’t
>> need context it can be ignored.
>>
>> - should async be a mixin or should we continue with the is_sync() method
>> and overwriting that in the sublcass?
>>
>>
>> I’m for is_sync() method as it is now. It’s more flexible and less
>> confusing (imagine an action inheriting
>> AsyncAction but having is_async() returning False).
>>
>> - should the openstack actions in mistral-extra be mixins?
>>
>>
>> No, not at all. They don’t have to be. This is a different discussion I
>> think. We need to collect what’s bad about
>> the current OpenStack actions and think how to rewrite them (extract the
>> common infrastructure they use,
>> make them more extensible, etc.)
>>
>
> +1 to all of the above, I think we are in complete agreement and this will
> give us both a flexible interface and one that is easy to use and
> understand.
>
>
>
>>
>>
>> Renat Akhmerov
>> @Nokia
>>
>>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Dougal Matthews
On 14 March 2017 at 11:14, Renat Akhmerov  wrote:

> Yeah, I finally understood too what Thomas meant.
>
> Just to clarify, I think mixed two different discussions here:
>
>1. Base framework for all actions residing in mistral-lib (what I was
>trying to discuss)
>2. The new design for OpenStack actions
>
>
> On #2 I agree with you that NovaAction.get_client(context) should work. No
> problem with that.
> And I believe that it doesn’t make sense to use multiple inheritance in
> this particular case, it’s
> simply not worth it.
>
> Getting back to #1.. Of course, using mixins can be problematic (method
> and state conflicts etc.).
> I think mixins is just one of the options that’s possible to use if we
> want to. Regular class inheritance
> is also an option I think. At this point if we just agree on action base
> class I think nothing prevents
> us from choosing how to evolve in the future. So just agreeing on the base
> class design seems
> to be sufficient for now. It’s just a base contract that a runner needs to
> be aware of (sorry for
> repeating this thought but I think it’s important). The rest is related
> with action developer
> convenience.
>
> I think the outstanding questions are;
>
> - should the context be a mixin or should run() always accept context?
>
>
> I’m for run() having “context” argument. Not sure why mixin is needed
> here. If an action doesn’t
> need context it can be ignored.
>
> - should async be a mixin or should we continue with the is_sync() method
> and overwriting that in the sublcass?
>
>
> I’m for is_sync() method as it is now. It’s more flexible and less
> confusing (imagine an action inheriting
> AsyncAction but having is_async() returning False).
>
> - should the openstack actions in mistral-extra be mixins?
>
>
> No, not at all. They don’t have to be. This is a different discussion I
> think. We need to collect what’s bad about
> the current OpenStack actions and think how to rewrite them (extract the
> common infrastructure they use,
> make them more extensible, etc.)
>

+1 to all of the above, I think we are in complete agreement and this will
give us both a flexible interface and one that is easy to use and
understand.



>
>
> Renat Akhmerov
> @Nokia
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread lương hữu tuấn
Oh, Thanks Dougal, i am now clear since it is your TripleO use case.

So yes, in this case, IMHO, we should keep the _get_client() as before but
change it to the classmethod. May be other methods too like
_create_client(), etc. We can think this change to be an alternative to the
solution of creating extra Minxin classes.

Br,

Tuan

On Tue, Mar 14, 2017 at 11:38 AM, Dougal Matthews  wrote:

>
>
> On 14 March 2017 at 10:21, lương hữu tuấn  wrote:
>
>>
>>
>> On Tue, Mar 14, 2017 at 10:28 AM, Dougal Matthews 
>> wrote:
>>
>>>
>>>
>>> On 13 March 2017 at 09:49, lương hữu tuấn  wrote:
>>>


 On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve 
 wrote:

> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
> >
> > One of the pain points for me as an action developer is the OpenStack
> > actions[1].  Since they all use the same method name to retrieve the
> > underlying client, you cannot simply inherit from more than one so
> you are
> > forced to rewrite the client access methods.  We saw this in creating
> > actions for TripleO[2].  In the base action in TripleO, we have
> actions that
> > make calls to more than one OpenStack client and so we end up
> re-writing and
> > maintaining code.  IMO the idea of using multiple inheritance there
> would be
> > helpful.  It may not require the mixin approach here, but rather a
> design
> > change in the generator to ensure the method names don't match.
>
> Is there any reason why those methods aren't functions? AFAICT they
> don't use the instance, they could live top level in the action module
> and be accessible by all actions. If you can avoid multiple
> inheritance (or inheritance!) you'll simplify the design. You could
> also do client = NovaAction().get_client() in your own action (if
> get_client was a public method).
>
> --
> Thomas
>
> If you want to do that, you need to change the whole structure of base
 action and the whole way of creating an action
 as you have described and IMHO, i myself do not like this idea:

 1. Mistral is working well (at the standpoint of creating action) and
 changing it is not a short term work.
 2. Using base class to create base action is actually a good idea in
 order to control and make easy to action developers.
 The base class will define the whole mechanism to execute an action,
 developers do not need to take care of it, just only
 providing OpenStack clients (the _create_client() method).
 3. From the #2 point of view, the alternative to
 NovaAction().get_client() does not make sense since the problem here is
 subclass mechanism,
 not the way to call get_client().

>>>
>> Hi,
>>
>> It is hard to me to understand what Thomas wants to say but i just
>> understood based on what he wrote:). Sorry for my misunderstanding.
>>
>>
>>> I might be wrong, but I think you read that Thomas wants to use
>>> functions for actions, not classes. I don't think that is the case. I think
>>> he is referring to the get_client method which is also what rbrady is
>>> referring to. At the moment multiple inheritance wont work if you want to
>>> inherit from NovaAction and KeyStone action because they both provide a
>>> "_get_client" method. If they has a unique name "get_keystone_client" and
>>> "get_nova_client" then the multiple inheritance wouldn't clash.
>>>
>>> Sorry Dougal but i do not get your point. Why the get_client could not
>> be used through instance since it has context?
>>
>
> In Mistral we have various OpenStack action classes. For example
> NovaAction[1] and GlanceAction[2] (and many others in that file). If I want
> to write an action that uses either Nova or Glance I can inherit from them,
> for example:
>
> class MyNovaAction(NovaAction):
>
> def run(self):
>
> client = self._create_client()
> # ... do something with the client and return
>
> However, if I wanted to use use two OpenStack clients, which I admit is a
> special case and I think one that only TripleO uses (that we know of).
>
> class MyNovaAndGlanceActioin(NovaAction, GlanceAction):
>
> def run(self):
>
> nova = self._create_client()
> glance = self._create_client() <- doesn't work because they both
> access the same method on NovaAction.
>
>
> If the method was called "create_nova_client" and "create_glance_client"
> then you could inherit from both without any conflict.
>
> However, based on the reply Thomas sent earlier, I think we should
> consider something like this when the OpenStack actions are moved to
> mistral-extra.
>
> nova = NovaAction.client(context)
>
> This is slight adaptation changes "_create_client" to "client" and makes
> it a class method that accepts the context. I think this would provide a
> 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Renat Akhmerov
Yeah, I finally understood too what Thomas meant.

Just to clarify, I think mixed two different discussions here:
Base framework for all actions residing in mistral-lib (what I was trying to 
discuss)
The new design for OpenStack actions

On #2 I agree with you that NovaAction.get_client(context) should work. No 
problem with that.
And I believe that it doesn’t make sense to use multiple inheritance in this 
particular case, it’s
simply not worth it.

Getting back to #1.. Of course, using mixins can be problematic (method and 
state conflicts etc.).
I think mixins is just one of the options that’s possible to use if we want to. 
Regular class inheritance
is also an option I think. At this point if we just agree on action base class 
I think nothing prevents
us from choosing how to evolve in the future. So just agreeing on the base 
class design seems
to be sufficient for now. It’s just a base contract that a runner needs to be 
aware of (sorry for
repeating this thought but I think it’s important). The rest is related with 
action developer
convenience.

> I think the outstanding questions are;
> 
> - should the context be a mixin or should run() always accept context? 

I’m for run() having “context” argument. Not sure why mixin is needed here. If 
an action doesn’t
need context it can be ignored.

> - should async be a mixin or should we continue with the is_sync() method and 
> overwriting that in the sublcass?

I’m for is_sync() method as it is now. It’s more flexible and less confusing 
(imagine an action inheriting
AsyncAction but having is_async() returning False).

> - should the openstack actions in mistral-extra be mixins?


No, not at all. They don’t have to be. This is a different discussion I think. 
We need to collect what’s bad about
the current OpenStack actions and think how to rewrite them (extract the common 
infrastructure they use,
make them more extensible, etc.)


Renat Akhmerov
@Nokia

__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Dougal Matthews
On 14 March 2017 at 10:21, lương hữu tuấn  wrote:

>
>
> On Tue, Mar 14, 2017 at 10:28 AM, Dougal Matthews 
> wrote:
>
>>
>>
>> On 13 March 2017 at 09:49, lương hữu tuấn  wrote:
>>
>>>
>>>
>>> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:
>>>
 On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
 >
 > One of the pain points for me as an action developer is the OpenStack
 > actions[1].  Since they all use the same method name to retrieve the
 > underlying client, you cannot simply inherit from more than one so
 you are
 > forced to rewrite the client access methods.  We saw this in creating
 > actions for TripleO[2].  In the base action in TripleO, we have
 actions that
 > make calls to more than one OpenStack client and so we end up
 re-writing and
 > maintaining code.  IMO the idea of using multiple inheritance there
 would be
 > helpful.  It may not require the mixin approach here, but rather a
 design
 > change in the generator to ensure the method names don't match.

 Is there any reason why those methods aren't functions? AFAICT they
 don't use the instance, they could live top level in the action module
 and be accessible by all actions. If you can avoid multiple
 inheritance (or inheritance!) you'll simplify the design. You could
 also do client = NovaAction().get_client() in your own action (if
 get_client was a public method).

 --
 Thomas

 If you want to do that, you need to change the whole structure of base
>>> action and the whole way of creating an action
>>> as you have described and IMHO, i myself do not like this idea:
>>>
>>> 1. Mistral is working well (at the standpoint of creating action) and
>>> changing it is not a short term work.
>>> 2. Using base class to create base action is actually a good idea in
>>> order to control and make easy to action developers.
>>> The base class will define the whole mechanism to execute an action,
>>> developers do not need to take care of it, just only
>>> providing OpenStack clients (the _create_client() method).
>>> 3. From the #2 point of view, the alternative to
>>> NovaAction().get_client() does not make sense since the problem here is
>>> subclass mechanism,
>>> not the way to call get_client().
>>>
>>
> Hi,
>
> It is hard to me to understand what Thomas wants to say but i just
> understood based on what he wrote:). Sorry for my misunderstanding.
>
>
>> I might be wrong, but I think you read that Thomas wants to use functions
>> for actions, not classes. I don't think that is the case. I think he is
>> referring to the get_client method which is also what rbrady is referring
>> to. At the moment multiple inheritance wont work if you want to inherit
>> from NovaAction and KeyStone action because they both provide a
>> "_get_client" method. If they has a unique name "get_keystone_client" and
>> "get_nova_client" then the multiple inheritance wouldn't clash.
>>
>> Sorry Dougal but i do not get your point. Why the get_client could not be
> used through instance since it has context?
>

In Mistral we have various OpenStack action classes. For example
NovaAction[1] and GlanceAction[2] (and many others in that file). If I want
to write an action that uses either Nova or Glance I can inherit from them,
for example:

class MyNovaAction(NovaAction):

def run(self):

client = self._create_client()
# ... do something with the client and return

However, if I wanted to use use two OpenStack clients, which I admit is a
special case and I think one that only TripleO uses (that we know of).

class MyNovaAndGlanceActioin(NovaAction, GlanceAction):

def run(self):

nova = self._create_client()
glance = self._create_client() <- doesn't work because they both
access the same method on NovaAction.


If the method was called "create_nova_client" and "create_glance_client"
then you could inherit from both without any conflict.

However, based on the reply Thomas sent earlier, I think we should consider
something like this when the OpenStack actions are moved to mistral-extra.

nova = NovaAction.client(context)

This is slight adaptation changes "_create_client" to "client" and makes it
a class method that accepts the context. I think this would provide a very
clear interface. I also can't think of any advantage of inheriting from
NovaAction, there is no state shared with it, so we only want it to create
the class for us.


[1]:
https://github.com/openstack/mistral/blob/master/mistral/actions/openstack/actions.py#L75
[2]:
https://github.com/openstack/mistral/blob/master/mistral/actions/openstack/actions.py#L109


>
>
>
>> Thomas - The difficulty with these methods is that they need to access
>> the context - the context is going to be added to the action class, and
>> thus while the get_client methods 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread lương hữu tuấn
On Tue, Mar 14, 2017 at 10:28 AM, Dougal Matthews  wrote:

>
>
> On 13 March 2017 at 09:49, lương hữu tuấn  wrote:
>
>>
>>
>> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:
>>
>>> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
>>> >
>>> > One of the pain points for me as an action developer is the OpenStack
>>> > actions[1].  Since they all use the same method name to retrieve the
>>> > underlying client, you cannot simply inherit from more than one so you
>>> are
>>> > forced to rewrite the client access methods.  We saw this in creating
>>> > actions for TripleO[2].  In the base action in TripleO, we have
>>> actions that
>>> > make calls to more than one OpenStack client and so we end up
>>> re-writing and
>>> > maintaining code.  IMO the idea of using multiple inheritance there
>>> would be
>>> > helpful.  It may not require the mixin approach here, but rather a
>>> design
>>> > change in the generator to ensure the method names don't match.
>>>
>>> Is there any reason why those methods aren't functions? AFAICT they
>>> don't use the instance, they could live top level in the action module
>>> and be accessible by all actions. If you can avoid multiple
>>> inheritance (or inheritance!) you'll simplify the design. You could
>>> also do client = NovaAction().get_client() in your own action (if
>>> get_client was a public method).
>>>
>>> --
>>> Thomas
>>>
>>> If you want to do that, you need to change the whole structure of base
>> action and the whole way of creating an action
>> as you have described and IMHO, i myself do not like this idea:
>>
>> 1. Mistral is working well (at the standpoint of creating action) and
>> changing it is not a short term work.
>> 2. Using base class to create base action is actually a good idea in
>> order to control and make easy to action developers.
>> The base class will define the whole mechanism to execute an action,
>> developers do not need to take care of it, just only
>> providing OpenStack clients (the _create_client() method).
>> 3. From the #2 point of view, the alternative to
>> NovaAction().get_client() does not make sense since the problem here is
>> subclass mechanism,
>> not the way to call get_client().
>>
>
Hi,

It is hard to me to understand what Thomas wants to say but i just
understood based on what he wrote:). Sorry for my misunderstanding.


> I might be wrong, but I think you read that Thomas wants to use functions
> for actions, not classes. I don't think that is the case. I think he is
> referring to the get_client method which is also what rbrady is referring
> to. At the moment multiple inheritance wont work if you want to inherit
> from NovaAction and KeyStone action because they both provide a
> "_get_client" method. If they has a unique name "get_keystone_client" and
> "get_nova_client" then the multiple inheritance wouldn't clash.
>
> Sorry Dougal but i do not get your point. Why the get_client could not be
used through instance since it has context?


> Thomas - The difficulty with these methods is that they need to access the
> context - the context is going to be added to the action class, and thus
> while the get_client methods don't use the instance now, they will soon -
> unless we change direction.
>
>
>
>> @Renat: I myself not against to multiple inheritance too, the only thing
>> is if we want to make it multiple inheritance, we should think about it
>> more thoroughly for the hierarchy of inheritance, what each inheritance
>> layer does, etc. These work will make the multiple inheritance easy to
>> understand and for action developers as well easy to develop. So, IMHO, i
>> vote for make it simple, easy to understand first (if you continue with
>> mistral-lib) and then do the next thing later.
>>
>> Br,
>>
>> Tuan/Nokia
>>
>>> 
>>> __
>>> OpenStack Development Mailing List (not for usage questions)
>>> Unsubscribe: openstack-dev-requ...@lists.op
>>> enstack.org?subject:unsubscribe
>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>>
>>
>>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Dougal Matthews
On 14 March 2017 at 05:25, Renat Akhmerov  wrote:

> So again, I’m for simplicity but that kind of simplicity that also allows
> flexibility in the future.
>
> There’s one principle that I usually follow in programming that says:
>
> “*Space around code (absence of code) has more potential than the code
> itself.*”
>
> That means that it’s better to get rid of any stuff that’s not currently
> needed and add things
> as requirements change. However, that doesn’t always work well in
> framework development
> because the cost of initial inflexibility may become too high in future,
> that comes from the
> need to stay backwards compatible. What I’m trying to say is that IMO it’s
> ok just to keep
> it as simple as just a base class with method run() for now and think how
> we can add more
> things in the future, if we need to, using mixin approach. So seems like
> it’s going to be:
>
> class Action(object):
>
>   def run(ctx):
> …
>
>
> class Mixin1(object):
>
>   def method11():
> …
>
>   def method12():
> …
>
>
> class Mixin2(object):
>
>   def method21():
> …
>
>   def method22():
> …
>
>
> Then my concrete action could use a combination of Action and any of the
> mixin:
>
> class MyAction(Action, Mixin1):
>   …
>
>
> class MyAction(Action, Mixin2):
>   …
>
> or just
>
>
> class MyAction(Action):
>   …
>
> Is this flexible enough or does it have any potential issues?
>

Sure, that is fine and it works but I think this is almost exactly what
rbrady has proposed earlier in this thread.

I think the outstanding questions are;

- should the context be a mixin or should run() always accept context?
- should async be a mixin or should we continue with the is_sync() method
and overwriting that in the sublcass?
- should the openstack actions in mistral-extra be mixins?


IMO, base class is still needed to define the contract that all actions
> should follow. So that
> a runner knew what’s possible to do with actions.
>

I agree but I don't think anyone is suggesting we don't have a base class.


>
> Renat Akhmerov
> @Nokia
>
> On 13 Mar 2017, at 16:49, lương hữu tuấn  wrote:
>
>
>
> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:
>
>> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
>> >
>> > One of the pain points for me as an action developer is the OpenStack
>> > actions[1].  Since they all use the same method name to retrieve the
>> > underlying client, you cannot simply inherit from more than one so you
>> are
>> > forced to rewrite the client access methods.  We saw this in creating
>> > actions for TripleO[2].  In the base action in TripleO, we have actions
>> that
>> > make calls to more than one OpenStack client and so we end up
>> re-writing and
>> > maintaining code.  IMO the idea of using multiple inheritance there
>> would be
>> > helpful.  It may not require the mixin approach here, but rather a
>> design
>> > change in the generator to ensure the method names don't match.
>>
>> Is there any reason why those methods aren't functions? AFAICT they
>> don't use the instance, they could live top level in the action module
>> and be accessible by all actions. If you can avoid multiple
>> inheritance (or inheritance!) you'll simplify the design. You could
>> also do client = NovaAction().get_client() in your own action (if
>> get_client was a public method).
>>
>> --
>> Thomas
>>
>> If you want to do that, you need to change the whole structure of base
> action and the whole way of creating an action
> as you have described and IMHO, i myself do not like this idea:
>
> 1. Mistral is working well (at the standpoint of creating action) and
> changing it is not a short term work.
> 2. Using base class to create base action is actually a good idea in order
> to control and make easy to action developers.
> The base class will define the whole mechanism to execute an action,
> developers do not need to take care of it, just only
> providing OpenStack clients (the _create_client() method).
> 3. From the #2 point of view, the alternative to NovaAction().get_client()
> does not make sense since the problem here is subclass mechanism,
> not the way to call get_client().
>
> @Renat: I myself not against to multiple inheritance too, the only thing
> is if we want to make it multiple inheritance, we should think about it
> more thoroughly for the hierarchy of inheritance, what each inheritance
> layer does, etc. These work will make the multiple inheritance easy to
> understand and for action developers as well easy to develop. So, IMHO, i
> vote for make it simple, easy to understand first (if you continue with
> mistral-lib) and then do the next thing later.
>
> Br,
>
> Tuan/Nokia
>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread Dougal Matthews
On 13 March 2017 at 09:49, lương hữu tuấn  wrote:

>
>
> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:
>
>> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
>> >
>> > One of the pain points for me as an action developer is the OpenStack
>> > actions[1].  Since they all use the same method name to retrieve the
>> > underlying client, you cannot simply inherit from more than one so you
>> are
>> > forced to rewrite the client access methods.  We saw this in creating
>> > actions for TripleO[2].  In the base action in TripleO, we have actions
>> that
>> > make calls to more than one OpenStack client and so we end up
>> re-writing and
>> > maintaining code.  IMO the idea of using multiple inheritance there
>> would be
>> > helpful.  It may not require the mixin approach here, but rather a
>> design
>> > change in the generator to ensure the method names don't match.
>>
>> Is there any reason why those methods aren't functions? AFAICT they
>> don't use the instance, they could live top level in the action module
>> and be accessible by all actions. If you can avoid multiple
>> inheritance (or inheritance!) you'll simplify the design. You could
>> also do client = NovaAction().get_client() in your own action (if
>> get_client was a public method).
>>
>> --
>> Thomas
>>
>> If you want to do that, you need to change the whole structure of base
> action and the whole way of creating an action
> as you have described and IMHO, i myself do not like this idea:
>
> 1. Mistral is working well (at the standpoint of creating action) and
> changing it is not a short term work.
> 2. Using base class to create base action is actually a good idea in order
> to control and make easy to action developers.
> The base class will define the whole mechanism to execute an action,
> developers do not need to take care of it, just only
> providing OpenStack clients (the _create_client() method).
> 3. From the #2 point of view, the alternative to NovaAction().get_client()
> does not make sense since the problem here is subclass mechanism,
> not the way to call get_client().
>

I might be wrong, but I think you read that Thomas wants to use functions
for actions, not classes. I don't think that is the case. I think he is
referring to the get_client method which is also what rbrady is referring
to. At the moment multiple inheritance wont work if you want to inherit
from NovaAction and KeyStone action because they both provide a
"_get_client" method. If they has a unique name "get_keystone_client" and
"get_nova_client" then the multiple inheritance wouldn't clash.

Thomas - The difficulty with these methods is that they need to access the
context - the context is going to be added to the action class, and thus
while the get_client methods don't use the instance now, they will soon -
unless we change direction.



> @Renat: I myself not against to multiple inheritance too, the only thing
> is if we want to make it multiple inheritance, we should think about it
> more thoroughly for the hierarchy of inheritance, what each inheritance
> layer does, etc. These work will make the multiple inheritance easy to
> understand and for action developers as well easy to develop. So, IMHO, i
> vote for make it simple, easy to understand first (if you continue with
> mistral-lib) and then do the next thing later.
>
> Br,
>
> Tuan/Nokia
>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-14 Thread lương hữu tuấn
Hi,

Agree with the simplicity that Renat has shown. I would not want to change
the base class as well as the way of mistral created up to now.

Br,

Tuan/Nokia

On Mar 14, 2017 6:29 AM, "Renat Akhmerov"  wrote:

> So again, I’m for simplicity but that kind of simplicity that also allows
> flexibility in the future.
>
> There’s one principle that I usually follow in programming that says:
>
> “*Space around code (absence of code) has more potential than the code
> itself.*”
>
> That means that it’s better to get rid of any stuff that’s not currently
> needed and add things
> as requirements change. However, that doesn’t always work well in
> framework development
> because the cost of initial inflexibility may become too high in future,
> that comes from the
> need to stay backwards compatible. What I’m trying to say is that IMO it’s
> ok just to keep
> it as simple as just a base class with method run() for now and think how
> we can add more
> things in the future, if we need to, using mixin approach. So seems like
> it’s going to be:
>
> class Action(object):
>
>   def run(ctx):
> …
>
>
> class Mixin1(object):
>
>   def method11():
> …
>
>   def method12():
> …
>
>
> class Mixin2(object):
>
>   def method21():
> …
>
>   def method22():
> …
>
>
> Then my concrete action could use a combination of Action and any of the
> mixin:
>
> class MyAction(Action, Mixin1):
>   …
>
>
> class MyAction(Action, Mixin2):
>   …
>
> or just
>
>
> class MyAction(Action):
>   …
>
> Is this flexible enough or does it have any potential issues?
>
> IMO, base class is still needed to define the contract that all actions
> should follow. So that
> a runner knew what’s possible to do with actions.
>
> Renat Akhmerov
> @Nokia
>
> On 13 Mar 2017, at 16:49, lương hữu tuấn  wrote:
>
>
>
> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:
>
>> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
>> >
>> > One of the pain points for me as an action developer is the OpenStack
>> > actions[1].  Since they all use the same method name to retrieve the
>> > underlying client, you cannot simply inherit from more than one so you
>> are
>> > forced to rewrite the client access methods.  We saw this in creating
>> > actions for TripleO[2].  In the base action in TripleO, we have actions
>> that
>> > make calls to more than one OpenStack client and so we end up
>> re-writing and
>> > maintaining code.  IMO the idea of using multiple inheritance there
>> would be
>> > helpful.  It may not require the mixin approach here, but rather a
>> design
>> > change in the generator to ensure the method names don't match.
>>
>> Is there any reason why those methods aren't functions? AFAICT they
>> don't use the instance, they could live top level in the action module
>> and be accessible by all actions. If you can avoid multiple
>> inheritance (or inheritance!) you'll simplify the design. You could
>> also do client = NovaAction().get_client() in your own action (if
>> get_client was a public method).
>>
>> --
>> Thomas
>>
>> If you want to do that, you need to change the whole structure of base
> action and the whole way of creating an action
> as you have described and IMHO, i myself do not like this idea:
>
> 1. Mistral is working well (at the standpoint of creating action) and
> changing it is not a short term work.
> 2. Using base class to create base action is actually a good idea in order
> to control and make easy to action developers.
> The base class will define the whole mechanism to execute an action,
> developers do not need to take care of it, just only
> providing OpenStack clients (the _create_client() method).
> 3. From the #2 point of view, the alternative to NovaAction().get_client()
> does not make sense since the problem here is subclass mechanism,
> not the way to call get_client().
>
> @Renat: I myself not against to multiple inheritance too, the only thing
> is if we want to make it multiple inheritance, we should think about it
> more thoroughly for the hierarchy of inheritance, what each inheritance
> layer does, etc. These work will make the multiple inheritance easy to
> understand and for action developers as well easy to develop. So, IMHO, i
> vote for make it simple, easy to understand first (if you continue with
> mistral-lib) and then do the next thing later.
>
> Br,
>
> Tuan/Nokia
>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e 
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-13 Thread Renat Akhmerov
So again, I’m for simplicity but that kind of simplicity that also allows 
flexibility in the future.

There’s one principle that I usually follow in programming that says:

“Space around code (absence of code) has more potential than the code itself.”

That means that it’s better to get rid of any stuff that’s not currently needed 
and add things
as requirements change. However, that doesn’t always work well in framework 
development
because the cost of initial inflexibility may become too high in future, that 
comes from the
need to stay backwards compatible. What I’m trying to say is that IMO it’s ok 
just to keep
it as simple as just a base class with method run() for now and think how we 
can add more
things in the future, if we need to, using mixin approach. So seems like it’s 
going to be:

class Action(object):

  def run(ctx):
…


class Mixin1(object):
  
  def method11():
…

  def method12():
…


class Mixin2(object):
  
  def method21():
…

  def method22():
…


Then my concrete action could use a combination of Action and any of the mixin:

class MyAction(Action, Mixin1):
  …


class MyAction(Action, Mixin2):
  …

or just


class MyAction(Action):
  …

Is this flexible enough or does it have any potential issues?

IMO, base class is still needed to define the contract that all actions should 
follow. So that
a runner knew what’s possible to do with actions.

Renat Akhmerov
@Nokia

> On 13 Mar 2017, at 16:49, lương hữu tuấn  wrote:
> 
> 
> 
> On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  > wrote:
> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  > wrote:
> >
> > One of the pain points for me as an action developer is the OpenStack
> > actions[1].  Since they all use the same method name to retrieve the
> > underlying client, you cannot simply inherit from more than one so you are
> > forced to rewrite the client access methods.  We saw this in creating
> > actions for TripleO[2].  In the base action in TripleO, we have actions that
> > make calls to more than one OpenStack client and so we end up re-writing and
> > maintaining code.  IMO the idea of using multiple inheritance there would be
> > helpful.  It may not require the mixin approach here, but rather a design
> > change in the generator to ensure the method names don't match.
> 
> Is there any reason why those methods aren't functions? AFAICT they
> don't use the instance, they could live top level in the action module
> and be accessible by all actions. If you can avoid multiple
> inheritance (or inheritance!) you'll simplify the design. You could
> also do client = NovaAction().get_client() in your own action (if
> get_client was a public method).
> 
> --
> Thomas
> 
> If you want to do that, you need to change the whole structure of base action 
> and the whole way of creating an action
> as you have described and IMHO, i myself do not like this idea:
> 
> 1. Mistral is working well (at the standpoint of creating action) and 
> changing it is not a short term work.
> 2. Using base class to create base action is actually a good idea in order to 
> control and make easy to action developers. 
> The base class will define the whole mechanism to execute an action, 
> developers do not need to take care of it, just only
> providing OpenStack clients (the _create_client() method).
> 3. From the #2 point of view, the alternative to NovaAction().get_client() 
> does not make sense since the problem here is subclass mechanism,
> not the way to call get_client().
> 
> @Renat: I myself not against to multiple inheritance too, the only thing is 
> if we want to make it multiple inheritance, we should think about it more 
> thoroughly for the hierarchy of inheritance, what each inheritance layer 
> does, etc. These work will make the multiple inheritance easy to understand 
> and for action developers as well easy to develop. So, IMHO, i vote for make 
> it simple, easy to understand first (if you continue with mistral-lib) and 
> then do the next thing later.
> 
> Br,
> 
> Tuan/Nokia
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe 
> 
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev 
> 
> 
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

__
OpenStack Development Mailing List (not for usage 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-13 Thread lương hữu tuấn
On Mon, Mar 13, 2017 at 9:34 AM, Thomas Herve  wrote:

> On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
> >
> > One of the pain points for me as an action developer is the OpenStack
> > actions[1].  Since they all use the same method name to retrieve the
> > underlying client, you cannot simply inherit from more than one so you
> are
> > forced to rewrite the client access methods.  We saw this in creating
> > actions for TripleO[2].  In the base action in TripleO, we have actions
> that
> > make calls to more than one OpenStack client and so we end up re-writing
> and
> > maintaining code.  IMO the idea of using multiple inheritance there
> would be
> > helpful.  It may not require the mixin approach here, but rather a design
> > change in the generator to ensure the method names don't match.
>
> Is there any reason why those methods aren't functions? AFAICT they
> don't use the instance, they could live top level in the action module
> and be accessible by all actions. If you can avoid multiple
> inheritance (or inheritance!) you'll simplify the design. You could
> also do client = NovaAction().get_client() in your own action (if
> get_client was a public method).
>
> --
> Thomas
>
> If you want to do that, you need to change the whole structure of base
action and the whole way of creating an action
as you have described and IMHO, i myself do not like this idea:

1. Mistral is working well (at the standpoint of creating action) and
changing it is not a short term work.
2. Using base class to create base action is actually a good idea in order
to control and make easy to action developers.
The base class will define the whole mechanism to execute an action,
developers do not need to take care of it, just only
providing OpenStack clients (the _create_client() method).
3. From the #2 point of view, the alternative to NovaAction().get_client()
does not make sense since the problem here is subclass mechanism,
not the way to call get_client().

@Renat: I myself not against to multiple inheritance too, the only thing is
if we want to make it multiple inheritance, we should think about it more
thoroughly for the hierarchy of inheritance, what each inheritance layer
does, etc. These work will make the multiple inheritance easy to understand
and for action developers as well easy to develop. So, IMHO, i vote for
make it simple, easy to understand first (if you continue with mistral-lib)
and then do the next thing later.

Br,

Tuan/Nokia

> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-13 Thread Thomas Herve
On Fri, Mar 10, 2017 at 9:52 PM, Ryan Brady  wrote:
>
> One of the pain points for me as an action developer is the OpenStack
> actions[1].  Since they all use the same method name to retrieve the
> underlying client, you cannot simply inherit from more than one so you are
> forced to rewrite the client access methods.  We saw this in creating
> actions for TripleO[2].  In the base action in TripleO, we have actions that
> make calls to more than one OpenStack client and so we end up re-writing and
> maintaining code.  IMO the idea of using multiple inheritance there would be
> helpful.  It may not require the mixin approach here, but rather a design
> change in the generator to ensure the method names don't match.

Is there any reason why those methods aren't functions? AFAICT they
don't use the instance, they could live top level in the action module
and be accessible by all actions. If you can avoid multiple
inheritance (or inheritance!) you'll simplify the design. You could
also do client = NovaAction().get_client() in your own action (if
get_client was a public method).

-- 
Thomas

__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-12 Thread Renat Akhmerov

> One of the pain points for me as an action developer is the OpenStack 
> actions[1].  Since they all use the same method name to retrieve the 
> underlying client, you cannot simply inherit from more than one so you are 
> forced to rewrite the client access methods.  We saw this in creating actions 
> for TripleO[2].  In the base action in TripleO, we have actions that make 
> calls to more than one OpenStack client and so we end up re-writing and 
> maintaining code.  IMO the idea of using multiple inheritance there would be 
> helpful.  It may not require the mixin approach here, but rather a design 
> change in the generator to ensure the method names don't match.
> 
> [1] 
> https://github.com/openstack/mistral/blob/master/mistral/actions/openstack/actions.py
>  
> 
> [2] 
> https://github.com/openstack/tripleo-common/blob/master/tripleo_common/actions/base.py#L27
>  
> 

I think I’m ok with multiple inheritance if we have a good reason. The question 
is: do we need to have some multiple inheritance in base classes? What you’re 
saying about OpenStack actions just looks like a slightly different discussion 
because they’ve never meant to be base classes, they were not designed with 
this goal in mind. Now, when we’re refactoring the whole subsystem and also 
OpenStack actions we need to revisit their design and think how to make it more 
flexible.

My suggestion here is to move iteratively. I am personally not going to be too 
opinionated about different ideas you’re suggesting. I’d rather merge the one 
that seems the best then reevaluate, change it etc. While mistral-lib is 
considered experimental we can try different options.

Renat Akhmerov
@Nokia


__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-10 Thread Ryan Brady
On Fri, Mar 10, 2017 at 5:16 AM, Renat Akhmerov 
wrote:

>
> On 10 Mar 2017, at 15:09, Dougal Matthews  wrote:
>
> On 10 March 2017 at 04:22, Renat Akhmerov 
> wrote:
>
>> Hi,
>>
>> I probably like the base class approach better too.
>>
>> However, I’m trying to understand if we need this variety of classes.
>>
>>- Do we need a separate class for asynchronous actions? IMO, since
>>is_sync() is just an instance method that can potentially return both True
>>and False based on the instance state shouldn’t be introduced by a special
>>class. Otherwise it’s confusing that a classes declared as AsyncAction can
>>actually be synchronous (if its is_sync() returns True). So maybe we 
>> should
>>just leave this method in the base class.
>>- I”m also wondering if we should just always pass “context” into
>>run() method. Those action implementations that don’t need it could just
>>ignore it. Not sure though.
>>
>> This is a good point. I had originally thought it would be backwards
> incompatible to make this change - however, users will need to update their
> actions to inherit from mistral-lib so they will need to opt in. Then in
> mistral we can do something like...
>
> if isinstance(action, mistral_lib.Action):
> action.run(ctx)
> else:
> # deprecation warning about action now inheriting from mistral_lib and
> taking a context etc.
> action.run()
>
>>
> Yes, right.
>

The example here by Dougal looks like the way to move forward.  Thanks for
all of the feedback.


>
> As far as mixin approach, I’d say I’d be ok with having mixing for
>> context-based actions. Although, like Dougal said, it may be a little
>> harder to read, this approach gives a huge flexibility for long term.
>> Imagine if we want to have a class of actions that some different kind of
>> information. Just making it up… For example, some of my actions need to be
>> aware of some policies (Congress-like) or information about metrics of the
>> current operating system (this is probably a bad example because it’s easy
>> to use standard Python modules but I’m just trying to illustrate the idea).
>> In this case we could have PolicyMixin and OperatingSystemMixin that would
>> set required info into the instance state or provide with handle interfaces
>> for more advanced uses.
>>
>
> I like the idea of mixins if we can see a future with many small
> components that can be included in an action class. However, like you I
> didn't manage to think of any real examples.
>
> It should be possible to migrate to a mixin approach later if we have the
> need.
>
>
> Well, I didn’t manage to find real use cases probably because I don’t
> develop lots of actions :) Although the example with policies seems almost
> real to me. This is something that was raised several times during design
> sessions in the past. Anyway, I agree with you that seems like we can add
> mixins later if we want to. I don’t see any reasons now why not.
>
>
One of the pain points for me as an action developer is the OpenStack
actions[1].  Since they all use the same method name to retrieve the
underlying client, you cannot simply inherit from more than one so you are
forced to rewrite the client access methods.  We saw this in creating
actions for TripleO[2].  In the base action in TripleO, we have actions
that make calls to more than one OpenStack client and so we end up
re-writing and maintaining code.  IMO the idea of using multiple
inheritance there would be helpful.  It may not require the mixin approach
here, but rather a design change in the generator to ensure the method
names don't match.

[1] https://github.com/openstack/mistral/blob/master/mistral
/actions/openstack/actions.py
[2] https://github.com/openstack/tripleo-common/blob/master/
tripleo_common/actions/base.py#L27


> Renat Akhmerov
> @Nokia
>
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>


-- 
Ryan Brady
Cloud Engineering
rbr...@redhat.com
919.890.8925 <(919)%20890-8925>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-10 Thread lương hữu tuấn
Hi,

I did not know about this change before but after reading the whole story,
IMHO i myself love the way of keeping it as simple at this moment as you
guys i think agreed on. For MixinAction or PolicyMixin, etc. we can develop
them later when we have concrete case studies.

Br,

Tuan/Nokia

On Fri, Mar 10, 2017 at 11:16 AM, Renat Akhmerov 
wrote:

>
> On 10 Mar 2017, at 15:09, Dougal Matthews  wrote:
>
> On 10 March 2017 at 04:22, Renat Akhmerov 
> wrote:
>
>> Hi,
>>
>> I probably like the base class approach better too.
>>
>> However, I’m trying to understand if we need this variety of classes.
>>
>>- Do we need a separate class for asynchronous actions? IMO, since
>>is_sync() is just an instance method that can potentially return both True
>>and False based on the instance state shouldn’t be introduced by a special
>>class. Otherwise it’s confusing that a classes declared as AsyncAction can
>>actually be synchronous (if its is_sync() returns True). So maybe we 
>> should
>>just leave this method in the base class.
>>- I”m also wondering if we should just always pass “context” into
>>run() method. Those action implementations that don’t need it could just
>>ignore it. Not sure though.
>>
>> This is a good point. I had originally thought it would be backwards
> incompatible to make this change - however, users will need to update their
> actions to inherit from mistral-lib so they will need to opt in. Then in
> mistral we can do something like...
>
> if isinstance(action, mistral_lib.Action):
> action.run(ctx)
> else:
> # deprecation warning about action now inheriting from mistral_lib and
> taking a context etc.
> action.run()
>
>>
> Yes, right.
>
> As far as mixin approach, I’d say I’d be ok with having mixing for
>> context-based actions. Although, like Dougal said, it may be a little
>> harder to read, this approach gives a huge flexibility for long term.
>> Imagine if we want to have a class of actions that some different kind of
>> information. Just making it up… For example, some of my actions need to be
>> aware of some policies (Congress-like) or information about metrics of the
>> current operating system (this is probably a bad example because it’s easy
>> to use standard Python modules but I’m just trying to illustrate the idea).
>> In this case we could have PolicyMixin and OperatingSystemMixin that would
>> set required info into the instance state or provide with handle interfaces
>> for more advanced uses.
>>
>
> I like the idea of mixins if we can see a future with many small
> components that can be included in an action class. However, like you I
> didn't manage to think of any real examples.
>
> It should be possible to migrate to a mixin approach later if we have the
> need.
>
>
> Well, I didn’t manage to find real use cases probably because I don’t
> develop lots of actions :) Although the example with policies seems almost
> real to me. This is something that was raised several times during design
> sessions in the past. Anyway, I agree with you that seems like we can add
> mixins later if we want to. I don’t see any reasons now why not.
>
>
> Renat Akhmerov
> @Nokia
>
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-10 Thread Renat Akhmerov

> On 10 Mar 2017, at 15:09, Dougal Matthews  wrote:
> 
> On 10 March 2017 at 04:22, Renat Akhmerov  > wrote:
> Hi,
> 
> I probably like the base class approach better too.
> 
> However, I’m trying to understand if we need this variety of classes.
> Do we need a separate class for asynchronous actions? IMO, since is_sync() is 
> just an instance method that can potentially return both True and False based 
> on the instance state shouldn’t be introduced by a special class. Otherwise 
> it’s confusing that a classes declared as AsyncAction can actually be 
> synchronous (if its is_sync() returns True). So maybe we should just leave 
> this method in the base class.
> I”m also wondering if we should just always pass “context” into run() method. 
> Those action implementations that don’t need it could just ignore it. Not 
> sure though.
> This is a good point. I had originally thought it would be backwards 
> incompatible to make this change - however, users will need to update their 
> actions to inherit from mistral-lib so they will need to opt in. Then in 
> mistral we can do something like...
> 
> if isinstance(action, mistral_lib.Action):
> action.run(ctx)
> else:
> # deprecation warning about action now inheriting from mistral_lib and 
> taking a context etc.
> action.run()

Yes, right.

> As far as mixin approach, I’d say I’d be ok with having mixing for 
> context-based actions. Although, like Dougal said, it may be a little harder 
> to read, this approach gives a huge flexibility for long term. Imagine if we 
> want to have a class of actions that some different kind of information. Just 
> making it up… For example, some of my actions need to be aware of some 
> policies (Congress-like) or information about metrics of the current 
> operating system (this is probably a bad example because it’s easy to use 
> standard Python modules but I’m just trying to illustrate the idea). In this 
> case we could have PolicyMixin and OperatingSystemMixin that would set 
> required info into the instance state or provide with handle interfaces for 
> more advanced uses.
> 
> I like the idea of mixins if we can see a future with many small components 
> that can be included in an action class. However, like you I didn't manage to 
> think of any real examples.
> 
> It should be possible to migrate to a mixin approach later if we have the 
> need.


Well, I didn’t manage to find real use cases probably because I don’t develop 
lots of actions :) Although the example with policies seems almost real to me. 
This is something that was raised several times during design sessions in the 
past. Anyway, I agree with you that seems like we can add mixins later if we 
want to. I don’t see any reasons now why not.


Renat Akhmerov
@Nokia


__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-10 Thread Dougal Matthews
On 10 March 2017 at 04:22, Renat Akhmerov  wrote:

> Hi,
>
> I probably like the base class approach better too.
>
> However, I’m trying to understand if we need this variety of classes.
>
>- Do we need a separate class for asynchronous actions? IMO, since
>is_sync() is just an instance method that can potentially return both True
>and False based on the instance state shouldn’t be introduced by a special
>class. Otherwise it’s confusing that a classes declared as AsyncAction can
>actually be synchronous (if its is_sync() returns True). So maybe we should
>just leave this method in the base class.
>- I”m also wondering if we should just always pass “context” into
>run() method. Those action implementations that don’t need it could just
>ignore it. Not sure though.
>
> This is a good point. I had originally thought it would be backwards
incompatible to make this change - however, users will need to update their
actions to inherit from mistral-lib so they will need to opt in. Then in
mistral we can do something like...

if isinstance(action, mistral_lib.Action):
action.run(ctx)
else:
# deprecation warning about action now inheriting from mistral_lib and
taking a context etc.
action.run()

So just having one class would really be the simplest approach.


As far as mixin approach, I’d say I’d be ok with having mixing for
> context-based actions. Although, like Dougal said, it may be a little
> harder to read, this approach gives a huge flexibility for long term.
> Imagine if we want to have a class of actions that some different kind of
> information. Just making it up… For example, some of my actions need to be
> aware of some policies (Congress-like) or information about metrics of the
> current operating system (this is probably a bad example because it’s easy
> to use standard Python modules but I’m just trying to illustrate the idea).
> In this case we could have PolicyMixin and OperatingSystemMixin that would
> set required info into the instance state or provide with handle interfaces
> for more advanced uses.
>

I like the idea of mixins if we can see a future with many small components
that can be included in an action class. However, like you I didn't manage
to think of any real examples.

It should be possible to migrate to a mixin approach later if we have the
need.


What do you think?
>
> Renat Akhmerov
> @Nokia
>
> On 9 Mar 2017, at 11:35, Ryan Brady  wrote:
>
> At the PTG and previous discussions in IRC, I mentioned there were two
> different design ideas I had for the developer experience for custom action
> development in mistral-lib.  The purpose and intent behind the patch[1] was
> discussed in person at the PTG and that was helpful for me wrt to scope.  I
> feel it would be helpful to discuss and decide together the final piece of
> this patch.  I'd like to get any feedback on either of these two ideas as
> they will shape how developers integrate with Mistral in the future, impact
> our OpenStack integration efforts in mistral-extra.  Nothing stops a
> developer from adopting either style in their custom action libraries, but
> most will likely want to remain consistent with style present in the
> upstream code.
>
> I have created separate declaration and usage examples in hopes of
> illustrating some of the similarities and differences.  To me it seems the
> base class example is more declarative/explicit, but the mixin example is
> more extensible and dry.  Both examples reflect on backwards compatibility
> and possible changes to how mistral checks for sync/async actions and how
> to pass the context (as needed by actions that integrate with OpenStack).
>
>
> base classes declaration: https://gist.github.com/rbrady/
> ff86c484e8e6e53ba2dc3dfa17b01b09
>
> base class usage: https://gist.github.com/rbrady/
> 716a02fb2bd38d822c6df8bd642d3ea6
>
> mixins declaration: https://gist.github.com/rbrady/
> d30ae640b19df658a17cd93827125678
>
> mixins usage: https://gist.github.com/rbrady/
> 248cb52d5c5f94854d8c76eee911ce8e
>
>
> Thanks,
>
> Ryan
>
> --
> Ryan Brady
> Cloud Engineering
> rbr...@redhat.com
> 919.890.8925 <(919)%20890-8925>
>
>
> [1] https://review.openstack.org/#/c/411412/
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: 

Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-09 Thread Renat Akhmerov
Hi,

I probably like the base class approach better too.

However, I’m trying to understand if we need this variety of classes.
Do we need a separate class for asynchronous actions? IMO, since is_sync() is 
just an instance method that can potentially return both True and False based 
on the instance state shouldn’t be introduced by a special class. Otherwise 
it’s confusing that a classes declared as AsyncAction can actually be 
synchronous (if its is_sync() returns True). So maybe we should just leave this 
method in the base class.
I”m also wondering if we should just always pass “context” into run() method. 
Those action implementations that don’t need it could just ignore it. Not sure 
though.

As far as mixin approach, I’d say I’d be ok with having mixing for 
context-based actions. Although, like Dougal said, it may be a little harder to 
read, this approach gives a huge flexibility for long term. Imagine if we want 
to have a class of actions that some different kind of information. Just making 
it up… For example, some of my actions need to be aware of some policies 
(Congress-like) or information about metrics of the current operating system 
(this is probably a bad example because it’s easy to use standard Python 
modules but I’m just trying to illustrate the idea). In this case we could have 
PolicyMixin and OperatingSystemMixin that would set required info into the 
instance state or provide with handle interfaces for more advanced uses.

What do you think?

Renat Akhmerov
@Nokia

> On 9 Mar 2017, at 11:35, Ryan Brady  wrote:
> 
> At the PTG and previous discussions in IRC, I mentioned there were two 
> different design ideas I had for the developer experience for custom action 
> development in mistral-lib.  The purpose and intent behind the patch[1] was 
> discussed in person at the PTG and that was helpful for me wrt to scope.  I 
> feel it would be helpful to discuss and decide together the final piece of 
> this patch.  I'd like to get any feedback on either of these two ideas as 
> they will shape how developers integrate with Mistral in the future, impact 
> our OpenStack integration efforts in mistral-extra.  Nothing stops a 
> developer from adopting either style in their custom action libraries, but 
> most will likely want to remain consistent with style present in the upstream 
> code.
> 
> I have created separate declaration and usage examples in hopes of 
> illustrating some of the similarities and differences.  To me it seems the 
> base class example is more declarative/explicit, but the mixin example is 
> more extensible and dry.  Both examples reflect on backwards compatibility 
> and possible changes to how mistral checks for sync/async actions and how to 
> pass the context (as needed by actions that integrate with OpenStack).
> 
> 
> base classes declaration: 
> https://gist.github.com/rbrady/ff86c484e8e6e53ba2dc3dfa17b01b09 
> 
> 
> base class usage: 
> https://gist.github.com/rbrady/716a02fb2bd38d822c6df8bd642d3ea6 
> 
> 
> mixins declaration: 
> https://gist.github.com/rbrady/d30ae640b19df658a17cd93827125678 
> 
> 
> mixins usage: https://gist.github.com/rbrady/248cb52d5c5f94854d8c76eee911ce8e 
> 
> 
> 
> Thanks,
> 
> Ryan
> 
> -- 
> Ryan Brady
> Cloud Engineering
> rbr...@redhat.com  
> 919.890.8925
> 
> 
> [1] https://review.openstack.org/#/c/411412/ 
> 
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-09 Thread Dougal Matthews
On 9 March 2017 at 17:19, Dougal Matthews  wrote:

> On 9 March 2017 at 04:35, Ryan Brady  wrote:
>
>> At the PTG and previous discussions in IRC, I mentioned there were two
>> different design ideas I had for the developer experience for custom action
>> development in mistral-lib.  The purpose and intent behind the patch[1] was
>> discussed in person at the PTG and that was helpful for me wrt to scope.  I
>> feel it would be helpful to discuss and decide together the final piece of
>> this patch.  I'd like to get any feedback on either of these two ideas as
>> they will shape how developers integrate with Mistral in the future, impact
>> our OpenStack integration efforts in mistral-extra.  Nothing stops a
>> developer from adopting either style in their custom action libraries, but
>> most will likely want to remain consistent with style present in the
>> upstream code.
>>
>> I have created separate declaration and usage examples in hopes of
>> illustrating some of the similarities and differences.  To me it seems the
>> base class example is more declarative/explicit, but the mixin example is
>> more extensible and dry.  Both examples reflect on backwards compatibility
>> and possible changes to how mistral checks for sync/async actions and how
>> to pass the context (as needed by actions that integrate with OpenStack).
>>
>>
>> base classes declaration: https://gist.github.com/rbrady/ff86c484e8e6e53b
>> a2dc3dfa17b01b09
>>
>> base class usage: https://gist.github.com/rbrady/716a02fb2bd38d822c6df8
>> bd642d3ea6
>>
>
> The base class approach gets my vote for two reasons:
>
> 1. It is the simplest to use and document.
> 2. I don't think we have enough combinations (yet?) to warrant mixins.
>

3. The set_context method on the mixin isn't as clear as passing it to run.
Imagine I am scanning your code, I can see from the run that the context is
passed in. I don't need to look for the base class and look to see if
self.context is used.


>
>
>
>>
>> mixins declaration: https://gist.github.com/rbrady/d30ae640b19df658
>> a17cd93827125678
>>
>> mixins usage: https://gist.github.com/rbrady/248cb52d5c5f94854d8c76
>> eee911ce8e
>>
>>
>> Thanks,
>>
>> Ryan
>>
>> --
>> Ryan Brady
>> Cloud Engineering
>> rbr...@redhat.com
>> 919.890.8925 <(919)%20890-8925>
>>
>>
>> [1] https://review.openstack.org/#/c/411412/
>>
>> 
>> __
>> OpenStack Development Mailing List (not for usage questions)
>> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscrib
>> e
>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>>
>>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [mistral] Mistral Custom Actions API Design

2017-03-09 Thread Dougal Matthews
On 9 March 2017 at 04:35, Ryan Brady  wrote:

> At the PTG and previous discussions in IRC, I mentioned there were two
> different design ideas I had for the developer experience for custom action
> development in mistral-lib.  The purpose and intent behind the patch[1] was
> discussed in person at the PTG and that was helpful for me wrt to scope.  I
> feel it would be helpful to discuss and decide together the final piece of
> this patch.  I'd like to get any feedback on either of these two ideas as
> they will shape how developers integrate with Mistral in the future, impact
> our OpenStack integration efforts in mistral-extra.  Nothing stops a
> developer from adopting either style in their custom action libraries, but
> most will likely want to remain consistent with style present in the
> upstream code.
>
> I have created separate declaration and usage examples in hopes of
> illustrating some of the similarities and differences.  To me it seems the
> base class example is more declarative/explicit, but the mixin example is
> more extensible and dry.  Both examples reflect on backwards compatibility
> and possible changes to how mistral checks for sync/async actions and how
> to pass the context (as needed by actions that integrate with OpenStack).
>
>
> base classes declaration: https://gist.github.com/rbrady/
> ff86c484e8e6e53ba2dc3dfa17b01b09
>
> base class usage: https://gist.github.com/rbrady/
> 716a02fb2bd38d822c6df8bd642d3ea6
>

The base class approach gets my vote for two reasons:

1. It is the simplest to use and document.
2. I don't think we have enough combinations (yet?) to warrant mixins.



>
> mixins declaration: https://gist.github.com/rbrady/
> d30ae640b19df658a17cd93827125678
>
> mixins usage: https://gist.github.com/rbrady/
> 248cb52d5c5f94854d8c76eee911ce8e
>
>
> Thanks,
>
> Ryan
>
> --
> Ryan Brady
> Cloud Engineering
> rbr...@redhat.com
> 919.890.8925 <(919)%20890-8925>
>
>
> [1] https://review.openstack.org/#/c/411412/
>
> __
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
>
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev