Puppet: System Administration Automated

Support

Ticket #671 (closed enhancement: wontfix)

Opened 1 year ago

Last modified 1 year ago

PATCH - Resource identification

Reported by: Tobu Assigned to: luke
Priority: normal Milestone:
Component: language Version:
Severity: normal Keywords: patch
Cc: thijso+puppet@gmail.com Triage Stage: Unreviewed
Attached Patches: Code Complexity: Unknown

Description

I am attaching my first stab at resource identification (still buggy, beware).

Here is how it works: when parsing a resource statement, check if an identical resource already exists. "identical" is defined as most constructor arguments being equal, including name, parameters, virtual-ness... At this stage, it is important that no overrides have been applied, otherwise resources could change and cease to be identical.

When calling Resource.finish , overrides are applied normally.

The criteria for identical-ness work for both resources and overrides; an override can be equal to another if both specify exacly the same parameters (an override cannot be identical to a plain resource).

Examples coming later.

Attachments

puppet-identify.patch (7.1 kB) - added by Tobu on 06/15/07 08:57:25.

Change History

06/15/07 08:57:25 changed by Tobu

  • attachment puppet-identify.patch added.

06/15/07 22:38:04 changed by Tobu

  • cc set to thijso+puppet@gmail.com.

Example: identification of overrides

#!/usr/bin/env puppet

class foo {
        file { "foo-dir":
                path => "/tmp/foo",
                ensure => directory,
        }
}

class bar inherits foo {
        File["foo-dir"] { ensure => file }
}

class baz inherits foo {
        File["foo-dir"] { ensure => file }
}
class mesh {
        include baz
        include bar
        # without identification, bang goes puppet
}

include mesh

CC-ing Thijs, from the mailing list.

06/15/07 22:41:30 changed by Tobu

Another example, plain identification

#!/usr/bin/env puppet

define mkdir ($a, $b) {
	file { "$a": ensure => directory }
	file { "$a/conf.d": ensure => directory }
	file { "$a/conf.d/$b": ensure => directory }
}

mkdir { "one":
	a => "/tmp",
	b => "ldap.ini",
}

mkdir { "two":
	a => "/tmp",
	b => "auth.ini",
}

#replace /tmp by /var/trac/proj for a real-world example.

06/15/07 22:43:44 changed by Tobu

This is rejected (no change here):

#!/usr/bin/env puppet

class foo {
	file { "foo-dir":
		path => "/tmp/foo",
		ensure => directory,
	}
}

define oink($a) {
	include foo
	File["foo-dir"] { path => "/tmp/foo/$a" }
}

class wut {
	oink { "o1": a => "123" }
	oink { "o2": a => "234" }
	#This should fail
}

include wut

06/15/07 22:51:55 changed by Tobu

It turns out that overrides aren't merged the way they should be in a complete configuration I have, I'm now looking for a simple test where this behaves incorrectly.

06/15/07 23:43:40 changed by luke

Here are some edge cases that make this complicated, and show that this patch isn't quite sufficient:

# Eventual equality
class one {
    file { "/testing": mode => 755, content => foo }
}

class two inherits one {
    File["/testing"] { owner => root }
}

class base {
    file { "/testing": owner => root, content => foo }
}

class sub inherits base {
    File["/testing"] { mode => 755 }
}

include two, sub

# Generated equality
define myfile($owner) {
    file { $name: owner => $owner }
}

class base {
    exec { echo: command => "/bin/echo something", refreshonly => true }

class one {
    myfile { $name: notify => Exec[echo], owner => root }
}

class two {
    file { $name: notify => Exec[echo], owner => root }
}

include base, one, two

# Within a single heirarchy
class base {
    file { "/testing": content => foo }
}

class sub1 inherits base {
    File["/testing"] { owner => root }
}

class sub2 inherits sub1 {
    File["/testing"] { group => root, mode => 755 }
}

class child1 inherits base {
    File["/testing"] { group => root, owner => root }
}

class child2 inherits child1 {
    File["/testing"] { mode => 755 }
}

include child2, sub2

06/16/07 00:17:17 changed by luke

More difficult edge cases:

# Initial equality, but not actual
class base {
    file { "/testing": content => foo }
}

class sub1 inherits base {
    File["/testing"] { mode => 755 }
}

class head {
    file { "/testing": content => foo }
}

class child1 inherits head {
    File["/testing"] { mode => 644 }
}

# "Valid" override, but only when evaluated in the right order.
# How do you guarantee that you keep the resource from 'base'
# around, not 'head'?
class base {
    file { "/testing": content => foo }
}

class sub1 inherits base {
    File["/testing"] { mode => 755 }
}

class head {
    file { "/testing": content => foo }
}

# Equal at definition time but not once metaparams are added.
define myfile($owner) {
    file { $name: owner => $owner }
}

class class1 {
    myfile { "/testing": owner => root, notify => Exec[myexec] }
}

class class2 {
    file { $name: owner => root }
}

06/16/07 01:24:37 changed by Tobu

A few points to keep in mind, that make identification currently difficult in puppet

  • the same parameter may be overriden multiple times, provided it is done on the same class hierarchy. This is a problem because we have to keep track of the context an override was declared in, and with identification, this context may become a set of contexts.
  • an override is only valid if made in a scope that includes the overriden resource
  • metaparameters can be applied to a defined type, where it cascades to the resources contained there.

The third point does not seem too hard, if metaparameters can be merged. eg, noop + not noop -> not noop, Exec[a] + Exec b -> [Exec[a], Exec[b]], etc.

06/18/07 23:27:48 changed by luke

  • status changed from new to closed.
  • resolution set to wontfix.

After much discussion, it looks like this feature is currently painfully difficult and likely will become impossible in the near future. Sorry.