Something like that definitely makes sense.

It becomes a bit weird, though, because the graph has its own sorting, so whatever mechanism you provide needs to work in parallel with the graph. This is more of a Markus area - every time I try to think of this stuff, my brain starts hurting.

On Jul 8, 2010, at 12:42 PM, Jonathan A. Booth wrote:

Would it make sense to have the default 'ensurable' for the resource checking for an 'ordered?' method on the provider? Something like 'if exists? then {if/try not ordered? then :unordered else :present} else :absent', and then let the provider figure it out? You'd need another provider standard 'reorder' method for that new :unordered result, which in my iptables case is just 'destroy;create' but wouldn't have to be in other cases.

Concat is hacking around the same problem -- its just a file{} that allows multiple declarations per-path with content ordering.

On 07/07/2010 06:20 PM, Luke Kanies wrote:
Just as an additional point - we know this is unsolved by the
framework at this point, and we're definitely looking for a general
fix.  Any general recommendations on how to fix this would be greatly
appreciated.

On Jul 7, 2010, at 7:51 AM, Jonathan A. Booth wrote:

For what it's worth, my solution to the iptables-rules-ordering
problem was a type/provider pair where the exists? of the provider
tests all the relationships on its resource* to determine self-
validitiy. Any relations that are also of resource type firewall,
provider type iptables, and in the same chain, it then checks the
rule number of each rule. If those numbers aren't ordered right,
fail the exists?.

Then when the rule goes to create itself, there's an extra check to
see if the rule exists but is out of order, and if so it deletes
itself first, then recreates itself at the end of the chain
(iptables -A chain ...), then updates the internal provider-class
'@iptables = iptables-save' (so checking ruleno for further
resources is correct).

Of course if anything required that rule, those dependencies will
all fail the order part of exists?, leading to a cascade of rule
delete/creations. Messy in the logs, but very functional in terms of
getting the rules I want set in place, yet leaving system-local
unmanaged rules possibile.

The bad thing is that unmanaged rules will bubble up in the iptables
chains over time, so if you have an unmanaged rule that does a
blanket reject or similar, it will cause you problems at an
indeterminate time.

*: The test looks something like:

def exists?
[...]
# If I do exist, then I (may) need to check my ordering too.
# Note that an (empty array).all? is true, providing the default
# case if there are no dependencies.
r = @resource
r.catalog.relationship_graph.dependencies(r).all? do |ancestor|
   provider = ancestor.provider
   # If the ancestor is absent, not of our class, or not of this
   # provider, then we don't need to compute
   skip = ancestor.value(:ensure) == :absent ||
          r.class != ancestor.class ||
          self.class != provider.class ||
          self.chain != provider.chain
   # Otherwise make sure their ruleno is before mine
   skip || ((provider.ruleno || -1)<  ruleno)
end
end [for def exists]

There's a provider 'def ruleno [...] end' which just indexes this
iptables rule in the array of rules from iptables-save and returns
the result. I think the '|| -1' in exists? is actually unneeded now,
but I haven't done testing to be sure.


On 07/07/2010 02:07 AM, Luke Kanies wrote:
On Jul 5, 2010, at 8:25 AM, Marc Fournier wrote:

Hello,


On Fri, 2 Jul 2010 09:57:37 -0700
Luke Kanies<[email protected]>   wrote:

On Jun 29, 2010, at 6:56 AM, Annie Rana wrote:

Hi all,

I am new to Puppet and Ruby. Currently I am using puppet iptables
work
[...]
within initialise method or even after that. It is very important
for me to understand the flow because TC rules would also be
incorporated with same iptables rules.

I can't help too much on this particular code -- you're definitely
right that it doesn't follow what we consider to be recommended
practice. For instance, I can't really recommend the style of
development used in this module - it involves quite a lot of class variables, and uses no provider. That isn't to say it's wrong per
se
- whatever works, works - but it's always going to be a bit tougher
to understand and maintain this way.

Annie, as Luke politely suggests, this iptables type is definetely a
bad
example. Vcsrepo, sudo and other recent types are much better source
of
inspiration, IMHO.


However, the thing that's probably confusing you is the extent to
which the framework (mostly the transaction class) is making calls against the resource type. It looks like everything's being driven by the 'evaluate' and 'initialize' methods. 'initialize' is a bit
obvious, but 'evaluate' is called by the transaction.

Note to the developers of this module - in 2.6, the 'evaluate'
method goes away, so this code won't work any more.

Excellent, this gives us a deadline to fix this dreadful piece of
code :-)


The transaction calls 'evaluate' on the resource, which would
normally produce a bunch of change objects, which the transaction
then applies, thus actually doing work.  In this case, it's being
used as a hook to get some setup done, it looks like.

One reason this type is a bit wierd is that firewall rules need to
get applied
in a very precise order. Puppet's before/require mechanism isn't
really helpful
here.

Either you have resources tied together in a extremely rigid way
(annoying if
you put these resource in classes which don't get included on every
node):

 iptables { "rule 1": }
 iptables { "rule 2": require =>   Iptables[rule 1] }
 iptables { "rule 3": require =>   Iptables[rule 2] }

or you drop the require parameters and have them get applied in
random order,
which will be an issue except for extremely simplistic firewall
setups.

So the way puppet-iptables works is that it collects every Iptables
resource in
a class variable, and when there are all there, orders them based on
the
namevar and then feeds the formatted output to the "iptables-
restore" command.

This is the way it was done by the original author in october 2007
(puppet 0.23
something) and wasn't fundamentally changed since then.

As I guess Annie is going to have the same sort of need for her TC
type, I'm
wondering what would be the "2.6-way" of achieving this use-case ?

Is there a good way of holding back changes which have to get
applied on a
node, and only applying them after some sort of post-processing (or
post-ordering) ?  Or maybe is there a was to force some sort of
implicit
resource ordering, without the user having to resort to before/
require params ?

The short answer is that there's nothing built into the framework
that
will do this, so you have to do something like what is there.

However, there are better and worse ways of forcing something like
this, and my guess is that we could find better ways.

In particular, you could (as a not-completely-thought-out example)
use
'prefetch' on the provider to set up relationships.  Normally
'prefetch' is just used to collect the current state of the system,
but it can actually modify resources, although it wouldn't normally.
You could set the order you need as relationships on the resources
there.

Otherwise, stick with the same model but clean it up a bit,
although I
apparently don't have any great ideas for how to do so. :/


--
You received this message because you are subscribed to the Google
Groups "Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected]
.
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en
.



--
There are no such things as applied sciences, only applications of
science. -- Louis Pasteur
---------------------------------------------------------------------
Luke Kanies  -|-   http://puppetlabs.com   -|-   +1(615)594-8199

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected] . For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en .


--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected] . For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en .



--
A bore is a man who deprives you of solitude without providing you
with company. -- Gian Vincenzo Gravina
---------------------------------------------------------------------
Luke Kanies  -|-   http://puppetlabs.com   -|-   +1(615)594-8199

--
You received this message because you are subscribed to the Google Groups "Puppet 
Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to