1#######################################################
2#
3# Redmine#6584: file_select mtime consistency
4#
5#######################################################
6body common control
7{
8      inputs => { "../../default.cf.sub" };
9      bundlesequence  => { default("$(this.promise_filename)") };
10      version => "1.0";
11}
12
13bundle common g
14{
15  vars:
16    "datafile" string => "$(this.promise_dirname)/rules.json";
17}
18bundle agent init
19{
20  vars:
21    "files"
22      slist => { "file1.log", "file2.log", "file3.log" },
23      comment => "These are the files we will try to delete";
24
25    "tests"
26      slist => {
27                 "test_delete_with_spec_from_data",
28                 "test_delete_with_spec_from_policy",
29                },
30      comment => "We have two tests combined here because they should be kept in sync.";
31
32    "data" data => readjson($(g.datafile), 1M);
33    "idx" slist => getindices("data");
34
35  files:
36    "$(G.testdir)/$(tests)/$(data[$(idx)][location])/."
37      create => "true",
38      comment => "Make sure our directories exist so that files can be created";
39
40    "$(G.testdir)/$(tests)/$(data[$(idx)][location])/$(files)"
41      create => "true",
42      comment => "Make sure the files exist so they can be deleted";
43
44  commands:
45    "$(G.touch)"
46      args => "-a -m -t 200901181205.09 $(G.testdir)/$(tests)/$(data[$(idx)][location])/$(files)",
47      comment => "Make sure the files are 'old' so they will be selected for deletion";
48}
49
50bundle agent test
51{
52  meta:
53    "test_soft_fail"
54      string => "any",
55      meta => { "redmine#6584", "zendesk#1466" };
56
57  methods:
58      "Test delete with spec from policy"
59        usebundle => test_delete_with_spec_from_policy;
60
61      "Test delete with spec from data"
62        usebundle => test_delete_with_spec_from_data($(g.datafile));
63}
64
65bundle agent test_delete_with_spec_from_policy {
66  files:
67    # This promise should be an effictive mirror of the promise with handle 'test_delete_with_spec_from_data'
68      "$(G.testdir)/$(this.bundle)/tmp/logs/tidy"
69        delete => tidy,
70        file_select =>
71          select_file_with_extension_retention_mtime(".*.log", # == 'filter' key in JSON
72                                                     "plain",  # == 'type' key in JSON
73                                                     "2",      # == 'retention' key in JSON
74                                                     "$(G.testdir)/$(this.bundle)/tmp/logs/tidy"), # == 'location' key in JSON
75        depth_search => recurse("2"),                          # == 'depth' key in JSON
76        action => if_elapsed_inform("10"),                     # == 'frequency' key in JSON
77        if => "any";                                           # == 'context' key in JSON
78
79  reports:
80    DEBUG::
81    "'$(G.testdir)/$(this.bundle)/tmp/logs/tidy'";
82}
83
84bundle agent test_delete_with_spec_from_data(ref)
85{
86  vars:
87      "input_cleanup"
88        comment => "Read json file into container",
89        data => readjson("${ref}", 1024);
90
91      "i"
92        comment => "Get index of json for iteration",
93        slist => getindices("input_cleanup");
94
95  methods:
96      "do_cleanup" usebundle => do_cleanup("${input_cleanup[${i}][location]}",
97                                           "${input_cleanup[${i}][context]}",
98                                           "${input_cleanup[${i}][action]}",
99                                           "${input_cleanup[${i}][frequency]}",
100                                           "${input_cleanup[${i}][type]}",
101                                           "${input_cleanup[${i}][filter]}",
102                                           "${input_cleanup[${i}][retention]}",
103                                           "${input_cleanup[${i}][depth]}",
104                                           "${input_cleanup[${i}][size]}",
105                                           "${input_cleanup[${i}][reason]}");
106
107  reports:
108    DEBUG::
109      " # Spec from json data file '$(ref)'#
110location => ${input_cleanup[${i}][location]}
111context => ${input_cleanup[${i}][context]}
112action => ${input_cleanup[${i}][action]}
113frequency => ${input_cleanup[${i}][frequency]}
114type => ${input_cleanup[${i}][type]}
115filter => ${input_cleanup[${i}][filter]}
116retention => ${input_cleanup[${i}][retention]}
117depth => ${input_cleanup[${i}][depth]}
118size => ${input_cleanup[${i}][size]}
119reason => ${input_cleanup[${i}][reason]}
120";
121}
122
123
124
125bundle agent do_cleanup(location,
126                        context,
127                        action,
128                        frequency,
129                        type,
130                        filter,
131                        retention,
132                        depth,
133                        size,
134                        reason) {
135  classes:
136      #"action_tidy" expression => strcmp("$(action)", "TIDY");
137      #"action_rotate" expression => strcmp("$(action)", "ROTATE");
138      #"requested_size" expression => regcmp("[0-9]*", "$(size)");
139
140  files:
141    #action_tidy::
142      "$(G.testdir)/test_delete_with_spec_from_data/$(location)"
143        handle => "test_delete_with_spec_from_data",
144        delete => tidy,
145        file_select => select_file_with_extension_retention_mtime("$(filter)",
146                                                                  "$(type)",
147                                                                  "$(retention)",
148                                                                  "$(G.testdir)/test_delete_with_spec_from_data/$(location)"),
149        depth_search => recurse("$(depth)"),
150        action => if_elapsed_inform("$(frequency)"),
151        if => "$(context)";
152
153  reports:
154    DEBUG::
155      "Filter=$(filter) Type=$(type) Retension=$(retention) Location=$(G.testdir)/test_delete_with_spec_from_data/$(location).* Depth=$(depth) Freq=$(frequency) Context=$(context)";
156}
157
158bundle agent check
159{
160  vars:
161    "files[test_delete_with_spec_from_data]" slist => lsdir("$(G.testdir)/test_delete_with_spec_from_data/tmp/logs/tidy", ".*.log", "false");
162    "files[test_delete_with_spec_from_policy]" slist => lsdir("$(G.testdir)/test_delete_with_spec_from_policy/tmp/logs/tidy", ".*.log", "false");
163
164    "count_files[test_delete_with_spec_from_data]"
165      int => length("files[test_delete_with_spec_from_data]")
166      ;
167    "count_files[test_delete_with_spec_from_policy]"
168      int => length("files[test_delete_with_spec_from_policy]");
169
170    "files_in_tidy_dir_count_$(init.tests)" int => length("files_in_tidy_dir[$(init.tests)]");
171    "OK_tests" slist => maplist("OK_$(this)", @(init.tests));
172
173  classes:
174    "OK_$(init.tests)"
175      not => isgreaterthan("$(count_files[$(init.tests)])", 0),
176      comment => "Define a class for each test that has an empty directory as desired";
177
178    "OK"
179      and => { @(OK_tests) },
180      comment => "Pass if all tests are OK";
181
182  reports:
183    DEBUG::
184      "files[test_delete_with_spec_from_data] = $(files[test_delete_with_spec_from_data])";
185      "files[test_delete_with_spec_from_policy] = $(files[test_delete_with_spec_from_policy])";
186      "count_files[test_delete_with_spec_from_data] = $(count_files[test_delete_with_spec_from_data])";
187      "count_files[test_delete_with_spec_from_policy] = $(count_files[test_delete_with_spec_from_policy])";
188
189      "$(init.tests) pass"
190        if => "OK_$(init.tests)";
191
192      "$(init.tests) fail"
193        if => "!OK_$(init.tests)";
194
195    OK::
196      "$(this.promise_filename) Pass";
197
198    !OK::
199      "$(this.promise_filename) FAIL";
200}
201body file_select select_file_with_extension_retention_mtime(filter, type, days_old, location) {
202    mtime => irange(0, ago(0, 0, $(days_old), 0, 0, 0));
203    path_name => { "$(location)/.*" };
204    leaf_name => { "$(filter)" };
205    file_types => { "$(type)" };
206#    The intention is to select files older than x days (mtime between now and x days ago should be retained) I believe the second file_result is correct.
207#    file_result => "mtime.path_name.leaf_name.file_types"; # Oddly this works for test_delete_with_spec_from_policy, but not with test_delete_with_spec_from_data
208    file_result => "!mtime.path_name.leaf_name.file_types"; # Oddly this works for test_delete_with_spec_from_data, but not with test_delete_with_spec_from_policy
209}
210
211body action if_elapsed_inform(x) {
212    report_level => "inform";
213    ifelapsed => "$(x)";
214    expireafter => "$(x)";
215}
216