I want to store a build version number that can be used later in a recipe to resolve the path to an msi in the "source" line. This version is specific to an environment. I'm undecided whether to use an environment attribute or a data bag, but either way I want to be able to update the attribute or data bag item from a script (I've got a master powershell script calling various AWS and knife functions).
However, the basic "knife environment edit.." or "knife data bag edit .." by default invokes an editor to manually edit the definition which is not workable from a script.
I've searched for solutions and have come across the following suggestions, but is there any accepted "best practice" or alternatives?
Dump the environment or data bag definitions as json files using "knife environment show ..." and replace values in the json files using standard search/replace tools and then use the "knife environment edit from file .." option.
Use custom ruby code called via knife exec -E (as suggested in http://www.getchef.com/blog/2014/01/23/attributes-or-data-bags-what-should-i-use/).
As an aside I'm finding it tricky getting this to run from a powershell script: In the case of trying to create a data bag, if I set the ruby code as a variable via a here-doc and call "knife exec -E $rubycode" it doesn't report an error but it doesn't create the databag either?
$rubycode= @"
require 'net/http'
require 'chef/rest'
require 'chef/config'
require 'chef/data_bag'
require 'chef/data_bag_item'
bagname = 'myapps'
appname = 'foo'
version = '1.0.0'
#Use the same config as knife uses
Chef::Config.from_file(File.join(ENV['USERPROFILE'], '.chef', 'knife.rb'))
#Load data bag item, or create it if it doesn't exist yet
begin
item = Chef::DataBagItem.load(bagname, appname)
rescue Net::HTTPServerException => e
if e.response.code == "404" then
puts("INFO: Creating a new data bag item")
item = Chef::DataBagItem.new
item.data_bag(bagname)
item['id'] = appname
else
puts("ERROR: Received an HTTPException of type " + e.response.code)
raise
end
end
item['version'] = version
item.save
"@#
knife exec -E $rubycode
- Calling the chef server api as described in http://docs.opscode.com/knife_exec.html
For example, in my powershell script, to create an environment I'm trying this (I haven't got to updating an attibute in an existing environment yet):
# A POST call to /environments creates a new environment. The request body should contain the JSON representation of the environment.
$environment_desc = @"
{
"name": "regtest",
"description": "",
"cookbook_versions": {},
"json_class": "Chef::Environment",
"chef_type": "environment",
"override_attributes": {}
}
"@
knife exec -E "api.post('/environments',$environment_desc)"
I'm getting the following error which I suspect might be something to do with powershell parsing
ERROR: SyntaxError: -E Argument: syntax error, unexpected $end, expecting '}' api.post('/environments',{
I realise some of the errors might well be due to powershell parsing but my question is as per the topic - is there a best practice method to edit environments and data bags non-interactively, either from the list above or some other methods?