summaryrefslogtreecommitdiff
path: root/lib/chef/resource/breakpoint.rb
blob: 360c064ff0e9c86cfd5923b07843dc8a6e01e25d (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
#
# Author:: Daniel DeLeo (<dan@kallistec.com>)
# 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 "chef-utils/dist" unless defined?(ChefUtils::Dist)

class Chef
  class Resource
    class Breakpoint < Chef::Resource
      unified_mode true

      provides :breakpoint, target_mode: true

      description "Use the **breakpoint** resource to add breakpoints to recipes. Run the #{ChefUtils::Dist::Infra::SHELL} in #{ChefUtils::Dist::Infra::PRODUCT} mode, and then use those breakpoints to debug recipes. Breakpoints are ignored by the #{ChefUtils::Dist::Infra::CLIENT} during an actual #{ChefUtils::Dist::Infra::CLIENT} run. That said, breakpoints are typically used to debug recipes only when running them in a non-production environment, after which they are removed from those recipes before the parent cookbook is uploaded to the Chef server."
      introduced "12.0"
      examples <<~DOC
      **A recipe without a breakpoint**

      ```ruby
      yum_key node['yum']['elrepo']['key'] do
        url  node['yum']['elrepo']['key_url']
        action :add
      end

      yum_repository 'elrepo' do
        description 'ELRepo.org Community Enterprise Linux Extras Repository'
        key node['yum']['elrepo']['key']
        mirrorlist node['yum']['elrepo']['url']
        includepkgs node['yum']['elrepo']['includepkgs']
        exclude node['yum']['elrepo']['exclude']
        action :create
      end
      ```

      **The same recipe with breakpoints**

      In the following example, the name of each breakpoint is an arbitrary string.

      ```ruby
      breakpoint "before yum_key node['yum']['repo_name']['key']" do
        action :break
      end

      yum_key node['yum']['repo_name']['key'] do
        url  node['yum']['repo_name']['key_url']
        action :add
      end

      breakpoint "after yum_key node['yum']['repo_name']['key']" do
        action :break
      end

      breakpoint "before yum_repository 'repo_name'" do
        action :break
      end

      yum_repository 'repo_name' do
        description 'description'
        key node['yum']['repo_name']['key']
        mirrorlist node['yum']['repo_name']['url']
        includepkgs node['yum']['repo_name']['includepkgs']
        exclude node['yum']['repo_name']['exclude']
        action :create
      end

      breakpoint "after yum_repository 'repo_name'" do
        action :break
      end
      ```

      In the previous examples, the names are used to indicate if the breakpoint is before or after a resource and also to specify which resource it is before or after.
      DOC

      default_action :break

      def initialize(action = "break", *args)
        super(caller.first, *args)
      end

      action :break, description: "Add a breakpoint for use with #{ChefUtils::Dist::Infra::SHELL}" do
        if defined?(Shell) && Shell.running?
          with_run_context :parent do
            run_context.resource_collection.iterator.pause
            new_resource.updated_by_last_action(true)
            run_context.resource_collection.iterator
          end
        end
      end
    end
  end
end