summaryrefslogtreecommitdiff
path: root/lib/chef/resource/ruby_block.rb
blob: b0ab19002f0bcbc56703327d86741b9197a44f4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: AJ Christensen (<aj@chef.io>)
# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require_relative "../resource"
require_relative "../provider/ruby_block"
require "chef-utils/dist" unless defined?(ChefUtils::Dist)

class Chef
  class Resource
    class RubyBlock < Chef::Resource
      unified_mode true

      provides :ruby_block, target_mode: true

      description "Use the **ruby_block** resource to execute Ruby code during a #{ChefUtils::Dist::Infra::PRODUCT} run. Ruby code in the `ruby_block` resource is evaluated with other resources during convergence, whereas Ruby code outside of a `ruby_block` resource is evaluated before other resources, as the recipe is compiled."
      examples <<~'DOC'
        **Reload Chef Infra Client configuration data**

        ```ruby
        ruby_block 'reload_client_config' do
          block do
            Chef::Config.from_file('/etc/chef/client.rb')
          end
          action :run
        end
        ```

        **Run a block on a particular platform**
        
        The following example shows how an if statement can be used with the `windows?` method in the Chef Infra Language to run code specific to Microsoft Windows. The code is defined using the ruby_block resource:
        
        ```ruby
        if windows?
          ruby_block 'copy libmysql.dll into ruby path' do
            block do
              require 'fileutils'
              FileUtils.cp "#{node['mysql']['client']['lib_dir']}\\libmysql.dll",
                node['mysql']['client']['ruby_dir']
            end
            not_if { ::File.exist?("#{node['mysql']['client']['ruby_dir']}\\libmysql.dll") }
          end
        end
        ```
        
        **Stash a file in a data bag**
        
        The following example shows how to use the ruby_block resource to stash a BitTorrent file in a data bag so that it can be distributed to nodes in the organization.
        
        ```ruby
        ruby_block 'share the torrent file' do
          block do
            f = File.open(node['bittorrent']['torrent'],'rb')
            #read the .torrent file and base64 encode it
            enc = Base64.encode64(f.read)
            data = {
              'id'=>bittorrent_item_id(node['bittorrent']['file']),
              'seed'=>node.ipaddress,
              'torrent'=>enc
            }
            item = Chef::DataBagItem.new
            item.data_bag('bittorrent')
            item.raw_data = data
            item.save
          end
          action :nothing
          subscribes :create, "bittorrent_torrent[#{node['bittorrent']['torrent']}]", :immediately
        end
        ```
        
        **Update the /etc/hosts file**
        
        The following example shows how the ruby_block resource can be used to update the /etc/hosts file:
        
        ```ruby
        ruby_block 'edit etc hosts' do
          block do
            rc = Chef::Util::FileEdit.new('/etc/hosts')
            rc.search_file_replace_line(/^127\.0\.0\.1 localhost$/,
              '127.0.0.1 #{new_fqdn} #{new_hostname} localhost')
            rc.write_file
          end
        end
        ```
        
        **Set environment variables**
        
        The following example shows how to use variables within a Ruby block to set environment variables using rbenv.
        
        ```ruby
        node.override[:rbenv][:root] = rbenv_root
        node.override[:ruby_build][:bin_path] = rbenv_binary_path
        
        ruby_block 'initialize' do
          block do
            ENV['RBENV_ROOT'] = node[:rbenv][:root]
            ENV['PATH'] = "#{node[:rbenv][:root]}/bin:#{node[:ruby_build][:bin_path]}:#{ENV['PATH']}"
          end
        end
        ```

        **Call methods in a gem**
        
        The following example shows how to call methods in gems not shipped in Chef Infra Client
        
        ```ruby
        chef_gem 'mongodb'

        ruby_block 'config_replicaset' do
          block do
            MongoDB.configure_replicaset(node, replicaset_name, rs_nodes)
          end
          action :run
        end
        ```
        DOC

      default_action :run
      allowed_actions :create, :run

      def block(&block)
        if block_given? && block
          @block = block
        else
          @block
        end
      end

      property :block_name, String, name_property: true
    end
  end
end