Now we have seen how to make use of a DSC resource inside of a Chef recipe, I thought of investigating a feature of Chef I heard about which is currently impossible to accomplish with native DSC without providing an intermediate state to the LCM.
Index:
- Part 1: Chef intro
- Part 2: Chef notifications
- Part 3: Chef server
- Part 4: Chef bootstrapping
- Part 5: Chef client settings
- Part 6: Puppet intro
- Part 7: Puppet notifications
- Part 8: Puppet server
- Part 9: Puppet Modules, Roles and more
- Part 10: Puppet bootstrap
The scenario is, something changes in one resource and to effectuate the change, a service or process needs to cycle / reload (e.g. the configuration file of the docker daemon is changed and now the docker daemon needs to restart).
When delivering this change with DSC, you would have 3 / configuration documents:
- the original state with the old desired configuration
- the new intermediate state with the change to the configuration file and the docker daemon stopped
- the final desired state with the change to the configuration file and the docker daemon started
To circumvent the need for an intermediate configuration state, I see people creating their own version of DSC resources, like the file resource, which flag the LCM that a reboot is required whenever the set method is called. This is of course not a good practice although understandable. It’s an immaturaty issue that should be solved so please vote here!
With Chef there is no need to define an intermediate state or ask for a reboot to effectuate. Instead we can make use of the subscribe and notify resource properties which are common functions for all Chef resources (like PSDscRunAsCredential is a common property for a DSC resource).
As an example, let’s look at the previous recipe.
dsc_resource 'some file' do
resource :File
module_name 'PSDesiredStateConfiguration'
module_version '1.1'
property :DestinationPath, 'c:\testfile.txt'
property :Contents, 'some text'
property :Ensure, 'Present'
end
Let’s pretent that c:\testfile.txt is such a configuration file which determines a daemons’ behavior. First let’s define the service in our recipe making use of windows_service Chef resource. We’ll pretent that the bits service is impacted on the file change.
windows_service 'bits' do
action :start
startup_type :automatic
end
dsc_resource 'some file' do
resource :File
module_name 'PSDesiredStateConfiguration'
module_version '1.1'
property :DestinationPath, 'c:\testfile.txt'
property :Contents, 'some text'
property :Ensure, 'Present'
end
The configuration of the windows_service
resource, the bits service should be started when on evaluation it is in the stopped state for some reason. And the service should be started when the system is booted by setting the startup type to Automatic.
Now we introduce the scenario where the bits service should be restarted when the dsc_resource
overwrites the c:\testfile.txt file induced by drift or change. We can make the windows_service
resource listen for such an occurance and have it subscribe to the dsc_resource
change event.
windows_service 'bits' do
action :start
startup_type :automatic
subscribes :restart, 'dsc_resource[some file]', :immediately
end
dsc_resource 'some file' do
resource :File
module_name 'PSDesiredStateConfiguration'
module_version '1.1'
property :DestinationPath, 'c:\testfile.txt'
property :Contents, 'some text'
property :Ensure, 'Present'
end
Let’s remove the c:\testfile.txt to create configuration drift and run this recipe.
rm c:\testfile.txt
chef-client --local-mode .\dsc01.rb
As you can see in the screenshot, the bits service was in the desired state at the start of the recipe execution. Then the dsc_resource
resource had a change event as the file was missing. The windows_service
resource picked up this event and restarted the service. Very cool!
Now let’s change the scenario a tiny bit and solve it using the notifies resource property instead. The scenario will be that the service needs to be stopped before the change to the text file can be made (e.g. due to a file lock).
windows_service 'bits' do
action :start
startup_type :automatic
end
dsc_resource 'some file' do
resource :File
module_name 'PSDesiredStateConfiguration'
module_version '1.1'
property :DestinationPath, 'c:\testfile.txt'
property :Contents, 'some text2'
property :Ensure, 'Present'
notifies :stop, 'windows_service[bits]', :before
notifies :start, 'windows_service[bits]', :immediately
end
Instead of the windows_service
resource subscribing to a change event, we now notify it of a change pending, on which it needs to stop the service. Once the change event of the dsc_resource
resource is done, we will notify the windows_service
resource again to start the service.
The change event is happening because I changed the file content a bit. Let’s have a look at what will happen.
As you can see, the bits service was already in the desired state. Then, the dsc_resource
found out that it needed to call into the set method but first notified the windows_service
resource to stop the service. It than ran the set method and after that was done, the windows_service
resource was notified again that it could start the service again. Nice!
I’ll stick with Chef for the next couple of blogs. To be continued!