How to manage dependent resources?


#1

I have an issue where I need to provide values generated dynamically by one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

ruby_block “foobarbaz” do

block do

Chef::Log.debug("t.base is #{t.base}")    # t.base evaluates to

“/usr/local/tomcat/jira”

end

end

I have found a solution thanks to Jorge Espada, but there really should be
a more straightforward way to do this.

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :nothing

end

t.run_action :install


#2

On Wed, Feb 29, 2012 at 7:53 PM, Bryan Berry bryan.berry@gmail.com wrote:

I have an issue where I need to provide values generated dynamically by one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the ivy
resource should place a .jar file in the #{base}/lib directory

If you are on a system that provides upstart, then I think you’ll find
upstart will scratch that itch most effectively[0].
Of course this assumes that each of the current resources can be
expressed as a task or service.
I generally use Chef to tweak a generic upstart conf template, and use
the emit/emits/start on/stop on to look after chaining and sequencing.
If you go down this path you might have to pay attention to upstart
synchronisation[1].

HTH

[0] http://upstart.ubuntu.com/cookbook/#run-a-job-when-a-file-or-directory-is-created-deleted
[1] http://upstart.ubuntu.com/cookbook/#synchronisation

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

ruby_block “foobarbaz” do

block do

Chef::Log.debug("t.base is #{t.base}")    # t.base evaluates to

“/usr/local/tomcat/jira”

end

end

I have found a solution thanks to Jorge Espada, but there really should be a
more straightforward way to do this.

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :nothing

end

t.run_action :install


πόλλ’ οἶδ ἀλώπηξ, ἀλλ’ ἐχῖνος ἓν μέγα
[The fox knows many things, but the hedgehog knows one big thing.]
Archilochus, Greek poet (c. 680 BC – c. 645 BC)
http://hedgehogshiatus.com


#3

argh my fears confirmed

The tomcat lwrp requires that the skeleton tomcat already exist in
/usr/local/tomcat/, created by the tomcat::base recipe. Using run_action
causes the tomcat lwrp to run before tomcat::base, argh

The only way I can see to fix this is hang the calculated values off of the
node object, so that the tomcat lwrp adds the base attribute to
node[‘jira’][‘base’] = t.base

and then create a special attribute for my ivy lwrp dest_attr that tells
the ivy lwrp to look in a node attribute for the value

ivy “mysql” do
groupId "mysql"
version "5.1.18"
dest “jira_base/lib” # tells ivy to look in node[‘jira’][‘base’]/lib
end

but frankly, this is pretty damn ugly

On Wed, Feb 29, 2012 at 9:53 AM, Bryan Berry bryan.berry@gmail.com wrote:

I have an issue where I need to provide values generated dynamically by
one resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

ruby_block “foobarbaz” do

block do

Chef::Log.debug("t.base is #{t.base}")    # t.base evaluates to

“/usr/local/tomcat/jira”

end

end

I have found a solution thanks to Jorge Espada, but there really should be
a more straightforward way to do this.

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :nothing

end

t.run_action :install


#4

hedge hog, tks, unfortunately i don’t think my particular resource can be
expressed as a task or a service, and I am on RHEL :frowning:

On Wed, Feb 29, 2012 at 10:05 AM, Hedge Hog hedgehogshiatus@gmail.comwrote:

On Wed, Feb 29, 2012 at 7:53 PM, Bryan Berry bryan.berry@gmail.com
wrote:

I have an issue where I need to provide values generated dynamically by
one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the
ivy
resource should place a .jar file in the #{base}/lib directory

If you are on a system that provides upstart, then I think you’ll find
upstart will scratch that itch most effectively[0].
Of course this assumes that each of the current resources can be
expressed as a task or service.
I generally use Chef to tweak a generic upstart conf template, and use
the emit/emits/start on/stop on to look after chaining and sequencing.
If you go down this path you might have to pay attention to upstart
synchronisation[1].

HTH

[0]
http://upstart.ubuntu.com/cookbook/#run-a-job-when-a-file-or-directory-is-created-deleted
[1] http://upstart.ubuntu.com/cookbook/#synchronisation

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

ruby_block “foobarbaz” do

block do

Chef::Log.debug("t.base is #{t.base}")    # t.base evaluates to

“/usr/local/tomcat/jira”

end

end

I have found a solution thanks to Jorge Espada, but there really should
be a
more straightforward way to do this.

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :nothing

end

t.run_action :install


πόλλ’ οἶδ ἀλώπηξ, ἀλλ’ ἐχῖνος ἓν μέγα
[The fox knows many things, but the hedgehog knows one big thing.]
Archilochus, Greek poet (c. 680 BC – c. 645 BC)
http://hedgehogshiatus.com


#5

On Wed, Feb 29, 2012 at 9:53 AM, Bryan Berry bryan.berry@gmail.com wrote:

I have an issue where I need to provide values generated dynamically by one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

The ivy provider should be able to retrieve the tomcat resource by
name, and then access any attribute.

So something like this:

ivy “mysql” do
groupId "mysql"
version "5.1.18"
base_resource :tomcat => "jira"
end

And then in the ivy provider do:

parent = resources(new_resource.base_resource)
parent.base

That’s off the top of my head so YMMV

Andrea


#6

that’s a good idea Andrea but I really like the solution that ssd7 came up
w/

I generate the base inside the initialize method for my tomcat LWRP

file: tomcat/resources/default.rb

def initialize(*args)s

super

@action = :install

catalina_parent = Pathname.new(node[‘tomcat’][‘home’]).parent.to_s

@base = “#{catalina_parent}/#{@name}”

Chef::Log.debug(“base_is #{@base}”)

@supports = {:report => true, :exception => true}

end

now my recipe code looks like this

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib”

end

much more elegant

thanks a lot SSD!

On Wed, Feb 29, 2012 at 4:22 PM, Andrea Campi
andrea.campi@zephirworks.comwrote:

On Wed, Feb 29, 2012 at 9:53 AM, Bryan Berry bryan.berry@gmail.com
wrote:

I have an issue where I need to provide values generated dynamically by
one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the
ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

The ivy provider should be able to retrieve the tomcat resource by
name, and then access any attribute.

So something like this:

ivy “mysql” do
groupId "mysql"
version "5.1.18"
base_resource :tomcat => "jira"
end

And then in the ivy provider do:

parent = resources(new_resource.base_resource)
parent.base

That’s off the top of my head so YMMV

Andrea


#7

On Wed, Feb 29, 2012 at 4:55 PM, Bryan Berry bryan.berry@gmail.com wrote:

that’s a good idea Andrea but I really like the solution that ssd7 came up
w/

I generate the base inside the initialize method for my tomcat LWRP

file: tomcat/resources/default.rb

def initialize(*args)s

super

@action = :install

catalina_parent = Pathname.new(node[‘tomcat’][‘home’]).parent.to_s

@base = “#{catalina_parent}/#{@name}”

Chef::Log.debug(“base_is #{@base}”)

@supports = {:report => true, :exception => true}

end

now my recipe code looks like this

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib”

end

much more elegant

For such a simple, explicit dependency I agree, it’s nice and elegant.
My approach probably works better in more complicated cases.

Andrea


#8

Another option we be an additional attribute on your tomcat resource that takes in a list of key/value pairs of ivy ‘packages’ to install:

tomcat “jira” do
user node[‘jira’][‘user’]
dependencies ‘mysql’ => ‘5.1.18’, ‘foo’ => '1.0.0’
action :install
end

Basically the provider for ‘tomcat’ would use the ivy LWRP under the covers to install everything.

Fun thing here is you could add support for other java dependency managers like maven relatively easy:

tomcat “jira” do
user node[‘jira’][‘user’]
dependencies ‘commons-lang’ => '2.0’
dependency_manager :maven
action :install
end


Seth Chisamore
Software Development Engineer, Opscode, Inc.
IRC, Skype, Twitter, Github: schisamo

On Wednesday, February 29, 2012 at 10:55 AM, Bryan Berry wrote:

that’s a good idea Andrea but I really like the solution that ssd7 came up w/

I generate the base inside the initialize method for my tomcat LWRP

file: tomcat/resources/default.rb

def initialize(*args)s
super
@action = :install
catalina_parent = Pathname.new(node[‘tomcat’][‘home’]).parent.to_s
@base = "#{catalina_parent}/#{@name}"
Chef::Log.debug(“base_is #{@base}”)
@supports = {:report => true, :exception => true}
end

now my recipe code looks like this

t = tomcat “jira” do
user node[‘jira’][‘user’]
action :install
end

get mysql connector

ivy “mysql-connector-java” do
groupId "mysql"
version "5.1.18"
dest "#{t.base}/lib"
end

much more elegant

thanks a lot SSD!

On Wed, Feb 29, 2012 at 4:22 PM, Andrea Campi <andrea.campi@zephirworks.com (mailto:andrea.campi@zephirworks.com)> wrote:

On Wed, Feb 29, 2012 at 9:53 AM, Bryan Berry <bryan.berry@gmail.com (mailto:bryan.berry@gmail.com)> wrote:

I have an issue where I need to provide values generated dynamically by one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

The ivy provider should be able to retrieve the tomcat resource by
name, and then access any attribute.

So something like this:

ivy “mysql” do
groupId "mysql"
version "5.1.18"
base_resource :tomcat => "jira"
end

And then in the ivy provider do:

parent = resources(new_resource.base_resource)
parent.base

That’s off the top of my head so YMMV

Andrea


#9

that’s an interesting idea Seth, unfortunately I have a n number of "ark"
resources after ivy that extract tarballs of dependencies to subdirectories
of the tomcat instance. That would work if I had a simpler use case

On Wed, Feb 29, 2012 at 5:40 PM, Seth Chisamore schisamo@opscode.comwrote:

Another option we be an additional attribute on your tomcat resource that
takes in a list of key/value pairs of ivy ‘packages’ to install:

tomcat “jira” do
user node[‘jira’][‘user’]
dependencies ‘mysql’ => ‘5.1.18’, ‘foo’ => '1.0.0’
action :install
end

Basically the provider for ‘tomcat’ would use the ivy LWRP under the
covers to install everything.

Fun thing here is you could add support for other java dependency managers
like maven relatively easy:

tomcat “jira” do
user node[‘jira’][‘user’]
dependencies ‘commons-lang’ => '2.0’
dependency_manager :maven
action :install
end


Seth Chisamore
Software Development Engineer, Opscode, Inc.
IRC, Skype, Twitter, Github: schisamo

On Wednesday, February 29, 2012 at 10:55 AM, Bryan Berry wrote:

that’s a good idea Andrea but I really like the solution that ssd7 came up
w/

I generate the base inside the initialize method for my tomcat LWRP

file: tomcat/resources/default.rb

def initialize(*args)s

super

@action = :install

catalina_parent = Pathname.new(node[‘tomcat’][‘home’]).parent.to_s

@base = “#{catalina_parent}/#{@name}”

Chef::Log.debug(“base_is #{@base}”)

@supports = {:report => true, :exception => true}

end

now my recipe code looks like this

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib”

end

much more elegant

thanks a lot SSD!

On Wed, Feb 29, 2012 at 4:22 PM, Andrea Campi <
andrea.campi@zephirworks.com> wrote:

On Wed, Feb 29, 2012 at 9:53 AM, Bryan Berry bryan.berry@gmail.com
wrote:

I have an issue where I need to provide values generated dynamically by
one
resource to resources that follow it

My tomcat lwrp generates a base directory for each new instance that is a
readable attribute “base”

Following resources will use that base attribute. In this example, the
ivy
resource should place a .jar file in the #{base}/lib directory

include_recipe “ark”

include_recipe “tomcat::base”

include_recipe “ivy”

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib” # evaluates to “/lib”

end

The ivy provider should be able to retrieve the tomcat resource by
name, and then access any attribute.

So something like this:

ivy “mysql” do
groupId "mysql"
version "5.1.18"
base_resource :tomcat => "jira"
end

And then in the ivy provider do:

parent = resources(new_resource.base_resource)
parent.base

That’s off the top of my head so YMMV

Andrea


#10

agreed and i may need to do that at some point in the future

On Wed, Feb 29, 2012 at 5:31 PM, Andrea Campi
andrea.campi@zephirworks.comwrote:

On Wed, Feb 29, 2012 at 4:55 PM, Bryan Berry bryan.berry@gmail.com
wrote:

that’s a good idea Andrea but I really like the solution that ssd7 came
up
w/

I generate the base inside the initialize method for my tomcat LWRP

file: tomcat/resources/default.rb

def initialize(*args)s

super

@action = :install

catalina_parent = Pathname.new(node[‘tomcat’][‘home’]).parent.to_s

@base = “#{catalina_parent}/#{@name}”

Chef::Log.debug(“base_is #{@base}”)

@supports = {:report => true, :exception => true}

end

now my recipe code looks like this

t = tomcat “jira” do

user node[‘jira’][‘user’]

action :install

end

get mysql connector

ivy “mysql-connector-java” do

groupId “mysql”

version “5.1.18”

dest “#{t.base}/lib”

end

much more elegant

For such a simple, explicit dependency I agree, it’s nice and elegant.
My approach probably works better in more complicated cases.

Andrea