summaryrefslogtreecommitdiff
path: root/docs/dev/design_documents/resource_file_content_verification.md
blob: 3df3083395c07920d88fd6a98aa90591c1139ccf (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
# File Content Verification

File-based resources should be able to verify a file's content via
user-supplied instructions before deploying the new content.

## Specification

The `verify` attribute of the `file`, `template`, `cookbook_file`, and
`remote_file` resources will take a user-provided block or string. At
converge time, a block will be passed the path to a temporary file
holding the proposed content for the file. If the block returns `true`,
the provider will continue to update the file on disk as
appropriate. If the block returns `false`, the provider will raise an
error.

If a string argument to verify is passed, it will then be executed as
a system command. If the command's return code indicates success -- 0 on
unix-like system -- the provider will continue to update the file on
disk as appropriate. If the command's return code indicates failure,
the provider will raise an error.

The path to the temporary file with the proposed content will be
available by using Ruby's sprintf formatting:

   "%{path}"

Other variables may be made available to commands in the future.

If no verification block or string is supplied by the user, the
provider assumes the content is valid.

Multiple verify blocks may be provided by the user. All given verify
block must pass before the content is deployed.

As an example:

```ruby
# This should succeed
template "/tmp/foo" do
  verify do |path|
    true
  end
end

# This should succeed on most systems
template "/tmp/wombat" do
  verify "/usr/bin/true"
end

# This should raise an error
template "/tmp/bar" do
  verify do |path|
    false
  end
end

# This should raise an error on most systems
template "/tmp/turtle" do
  verify "/usr/bin/false"
end

# This should pass
template "/tmp/baz" do
  verify { true }
  verify { 1 == 1 }
end

# This should raise an error
template "/tmp/bat" do
   verify { true }
   verify { 1 == 0 }
end
```

Users could use this feature to shell out to tools, which check the
configuration:

```ruby
template "/etc/nginx.conf" do
  verify "nginx -t -c %{path}"
end
```

Chef ships built-in verifiers for common content-types such as
`:systemd_unit`, `:yaml` and `:json`. Built-in verifiers can be
used by passing well-known symbols to the verify attribute:

```ruby
template "/etc/config.json" do
  verify :json
end
```
```ruby
template "/etc/config.yaml" do
  verify :yaml
end
```

## Motivation

Typos and bugs in a template can lead Chef to render invalid
configuration files on a node. In some cases, this will cause the
related service to fail a notified restart and bring down the user's
application. One hopes to catch such errors in testing, but that is
not always possible.

Many applications provide a means to verify a configuration file, but
it is currently difficult to use these tools to verify a template
without an elaborate series of resources chained together with
notifications.

## Related BUGS

https://tickets.opscode.com/browse/CHEF-4416
https://tickets.opscode.com/browse/CHEF-3634