Build path string version for remote_file parsing it from another file to download

I have tried to use the remote_file resource to download a jar file. However, the version of the jar file is not known to me before hand to place in a variable. I have to fetch another file first that contains the version, parse it and use it to build the path which remote_file will use to download the jar version.

My attempts have not been successful, since at convergence whatever version I parsed from the file that contains the version, it not available for the path build string used in remote_file resource.

In summary, the version of the file to be fetch is contained in another file that needs to be downloaded first and parsed.

If you understand what I am explaining, do you have another way of doing this? Do you have any suggestion or guidance?

There are two solutions.

1: The simple way: Use the code you already have but use “lazy” [1] to read the version in the file. Lazy will read the file content when the remote_file resource is executed and at that time the file with the version will be there already.

2: Put all you code into a custom resource [2]. In there everything is executed in order and you will not face the problems of chefs 2 phase execution.

[1] https://docs.chef.io/resource_common.html#lazy-evaluation
[2] https://docs.chef.io/custom_resources.html

Your response is very helpful. Very much appreciated. It shows me that I was in the right path. I just need to learn more about custom_resources.

You may be better off not grabbing the first file using chef resources.

require 'open-uri'

download = open('http://example.com/stuff.json')
destination = "Chef::Config[:file_cache_path]/stuff.json"
IO.copy_stream(download, destination)

or just:

require 'open-uri'
require 'json'

data = JSON.parse(open('http://example.com/stuff.json').read)

The downside there is that you hit the URI and grab the file every time, and don’t take advantage of http etags for caching data. But if the file you’re pulling down is literally a manifest entry and you parse the version you need out of that, there’s nothing inherently wrong with this approach.

Where it would start to be incorrect would be if you weren’t saving this data into the file cache path, and you deployed the content somewhere that could be considered modifying the running state of the system – that’s where you’d want to at least feed the contents through a file resource rather than just using raw ruby to update the system.

You can use pure ruby to collect whatever data you like – even remote data – in order to construct your resource collection. Saving tempfiles in pure ruby is also fine. At some point though if you’re downloading the first file and just winding up re-implementing the remote_file resource via your own ruby code fed into a file resource, then this approach would break down. But you didn’t include enough information about what kind of file you’re pulling down first to be able to guess on what side of that line you fall on.

Thank you for your explanation Lamont_Granquist.