1 =head1 Summary of initialdata files
3 It's often useful to be able to test configuration/database changes and then
4 apply the same changes in production without manually clicking around. It's
5 also helpful if you're developing customizations or extensions to be able to
6 get a fresh database back to the state you want for testing/development.
8 This documentation applies to careful and thorough sysadmins as well as
9 extension authors who need to make database changes easily and repeatably for
10 new installs or upgrades.
14 RT ships with many initialdata files, only one of which is used to
15 configure a fresh install; the rest are used for upgrades, but function
16 the same despite being named differently.
21 The upgrade "content" files are meant to be incremental changes applied on top
22 of one another while the top level initialdata file is for fresh RT installs.
24 Extensions may also ship with database changes in such files. You may find
25 some in your install with:
27 find local/plugins -name initialdata -or -name content
29 =head1 What can be in an initialdata file?
31 initialdata files are Perl, but often consist primarily of a bunch of data
32 structures defining the new records you want and not much extra code. There's
33 nothing stopping you from writing a bunch of code, however!
35 The basic template of a new initialdata file should look something like this:
41 # some definitions here
45 # some other definitions here
50 The C<@Queues> and C<@Groups> arrays are expected by RT and should contain
51 hashref definitions. There are many other arrays RT will look for and act on,
52 described below. None are required, all may be used. Keep in mind that since
53 they're just normal Perl arrays, you can C<push> onto them from a loop or
54 C<grep> out definitions based on conditionals or generate their content with
57 The complete list of possible arrays which can be used, along with
58 descriptions of the values to place in them, is below.
64 Password => 'changethis',
66 Timezone => 'America/Vancouver',
71 Each hashref in C<@Users> is treated as a new user to create and passed
72 straight into C<< RT::User->Create >>. All of the normal user fields are
73 available, as well as C<Privileged> and C<Disabled> (both booleans) which will
74 do the appropriate internal group/flag handling.
76 For a full list of fields, read the documentation for L<RT::User/Create>.
81 Name => 'Example Employees',
82 Description => 'All of the employees of my company',
83 Members => { Users => [ qw/ alexmv trs falcone / ],
84 Groups => [ qw/ extras / ] },
87 Creates a new L<RT::Group> for each hashref. In almost all cases you'll want
88 to follow the example above to create a group just as if you had done it from
91 In addition to the C<Members> option shown above, which can take both
92 users and groups, the C<MemberOf> field may be a single value or an
93 array ref. Each value should be a user-defined group name or hashref to
94 pass into L<RT::Group/LoadByCols>. Each group found will have the new
95 group added as a member.
101 CorrespondAddress => 'help@example.com',
102 CommentAddress => 'help-comment@example.com',
105 Creates a new L<RT::Queue> for each hashref. Refer to the documentation of
106 L<RT::Queue/Create> for the fields you can use.
108 =head2 C<@CustomFields>
110 push @CustomFields, {
111 Name => 'Favorite color',
112 Type => 'FreeformSingle',
113 LookupType => 'RT::Queue-RT::Ticket',
116 Creates a new L<RT::CustomField> for each hashref. It is the most complex of
117 the initialdata structures. The most commonly used fields are:
123 The name of this CF as displayed in RT.
127 A short summary of what this CF is for.
131 May be a single value, or an array reference of such; each should be
132 either an ID or Name. If omitted, the CF is applied globally. This
133 should not be used for User or Group custom fields.
135 This argument may also be passed via C<Queue>, for backwards
136 compatibility, which also defaults the C<LookupType> to
137 C<RT::Queue-RT::Ticket>.
141 One of the following on the left hand side:
143 SelectSingle # Select one value
144 SelectMultiple # Select multiple values
146 FreeformSingle # Enter one value
147 FreeformMultiple # Enter multiple values
149 Text # Fill in one text area
150 Wikitext # Fill in one wikitext area
152 BinarySingle # Upload one file
153 BinaryMultiple # Upload multiple files
155 ImageSingle # Upload one image
156 ImageMultiple # Upload multiple images
158 Combobox # Combobox: Select or enter one value
160 AutocompleteSingle # Enter one value with autocompletion
161 AutocompleteMultiple # Enter multiple values with autocompletion
164 DateTime # Select datetime
166 IPAddressSingle # Enter one IP address
167 IPAddressMultiple # Enter multiple IP addresses
169 IPAddressRangeSingle # Enter one IP address range
170 IPAddressRangeMultiple # Enter multiple IP address ranges
172 If you don't specify "Single" or "Multiple" in the type, you must specify
177 Labeled in the CF admin page as "Applies to". This determines whether your CF
178 is for Tickets, Transactions, Users, Groups, or Queues. Possible values:
180 RT::Queue-RT::Ticket # Tickets
181 RT::Queue-RT::Ticket-RT::Transaction # Transactions
185 RT::Class-RT::Article # Articles
187 Ticket CFs are the most common, meaning C<RT::Queue-RT::Ticket> is the most
188 common C<LookupType>.
192 Only valid when C<Type> is "Select". Controls how the CF is displayed when
193 editing it. Valid values are: C<Select box>, C<List>, and C<Dropdown>.
195 C<List> is either a list of radio buttons or a list of checkboxes depending on
200 Determines whether this CF is a Single or Multiple type. 0 means multiple. 1
203 Make sure to set the C<MaxValues> field appropriately, otherwise you can end up
204 with unsupported CF types like a "Select multiple dates" (it doesn't Just
207 You can also use old-style C<Type>s which end with "Single" or "Multiple", for
208 example: SelectSingle, SelectMultiple, FreeformSingle, etc.
212 C<Values> should be an array ref (never a single value!) of hashrefs
213 representing new L<RT::CustomFieldValue> objects to create for the new custom
214 field. This only makes sense for "Select" CFs. An example:
217 push @CustomFields, {
218 LookupType => 'RT::Queue-RT::Ticket', # for Tickets
219 Name => 'Type of food',
220 Type => 'SelectSingle', # SelectSingle is the same as: Type => 'Select', MaxValues => 1
221 RenderType => 'Dropdown',
223 { Name => 'Fruit', Description => 'Berries, peaches, tomatos, etc', SortOrder => $i++ },
224 { Name => 'Vegetable', Description => 'Asparagus, peas, lettuce, etc', SortOrder => $i++ },
225 # more values as such...
229 In order to ensure the same sorting of C<Values>, set C<SortOrder> inside each
230 value. A clever way to do this easily is with a simple variable you increment
231 each time (as above with C<$i>). You can use the same variable throughout the
232 whole file, and don't need one per CF.
236 Name or ID of another Select Custom Field. This makes the named CF the source
237 of categories for your values.
241 The regular expression text (not C<qr//>!) used to validate values.
245 Refer to the documentation and implementation of L<RT::CustomField/Create> and
246 L<RT::CustomFieldValue/Create> for the full list of available fields and
251 C<@ACL> is very useful for granting rights on your newly created records or
252 setting up a standard system configuration. It is one of the most complex
253 initialdata structures.
257 All ACL definitions expect a key named C<Right> with the internal right name
258 you want to grant. The internal right names are visible in RT's admin
259 interface in grey next to the longer descriptions.
261 =head3 Pick a level: on a queue, on a CF, or globally
263 After picking a C<Right>, you need to specify on what object the right is
264 granted. This is B<different> than the user/group/role receiving the right.
268 =item Granted on a custom field by name (or ID), potentially a global or queue
271 LookupType => 'RT::User', # optional, in case you need to disambiguate
273 =item Granted on a queue
277 =item Granted on a custom field applied to a specific queue
282 =item Granted on a custom field applied to some other object
284 # This finds the CF named "Name" applied to Articles in the
287 LookupType => RT::Article->CustomFieldLookupType,
288 ObjectId => 'Responses',
290 =item Granted on some other object (article Classes, etc)
292 ObjectType => 'RT::Class',
295 =item Granted globally
297 Specifying none of the above will get you a global right.
301 There is currently no way to grant rights on a group or article class level.
302 Note that you can grant rights B<to> a group; see below. If you need to grants
303 rights on a group or article class level, you'll need to write an C<@Final>
304 subref to handle it using the RT Perl API.
306 =head3 Pick a Principal: User or Group or Role
308 Finally you need to specify to what system group, system/queue role,
309 user defined group, or user you want to grant the right B<to>.
313 =item An internal user group
315 GroupDomain => 'SystemInternal',
316 GroupType => 'Everyone, Privileged, or Unprivileged'
318 =item A system-level role
320 GroupDomain => 'RT::System-Role',
321 GroupType => 'Requestor, Owner, AdminCc, or Cc'
323 =item A queue-level role
325 GroupDomain => 'RT::Queue-Role',
327 GroupType => 'Requestor, Owner, AdminCc, or Cc',
329 =item A group you created
331 GroupDomain => 'UserDefined',
334 =item Individual user
336 UserId => 'Name or email or ID'
342 You're probably looking for definitions like these most of the time.
346 =item Grant a global right to a group you created
349 GroupDomain => 'UserDefined',
352 =item Grant a queue-level right to a group you created
356 GroupDomain => 'UserDefined',
359 =item Grant a CF-level right to a group you created
363 GroupDomain => 'UserDefined',
368 Since you often want to grant a list of rights on the same object/level to the
369 same role/group/user, we generally use Perl loops and operators to aid in the
370 generation of C<@ACL> without repeating ourselves.
372 # Give Requestors globally the right to see tickets, reply, and see the
373 # queue their ticket is in
377 GroupDomain => 'RT::System-Role',
378 GroupType => 'Requestor',
380 } qw(ShowTicket ReplyToTicket SeeQueue);
382 =head3 Troubleshooting
384 The best troubleshooting is often to see how the rights you define in C<@ACL>
385 show up in the RT admin interface.
389 Creates a new L<RT::Scrip> for each hashref. Refer to the documentation of
390 L<RT::Scrip/Create> for the fields you can use.
392 Additionally, the C<Queue> field is specially handled to make it easier to
393 setup the same Scrip on multiple queues:
403 Queue => 'General', # Name or ID
405 =item Multiple queues
407 Queue => ['General', 'Helpdesk', 13], # Array ref of Name or ID
411 =head2 C<@ScripActions>
413 Creates a new L<RT::ScripAction> for each hashref. Refer to the documentation
414 of L<RT::ScripAction/Create> for the fields you can use.
416 =head2 C<@ScripConditions>
418 Creates a new L<RT::ScripCondition> for each hashref. Refer to the
419 documentation of L<RT::ScripCondition/Create> for the fields you can use.
423 Creates a new L<RT::Template> for each hashref. Refer to the documentation of
424 L<RT::Template/Create> for the fields you can use.
426 =head2 C<@Attributes>
428 An array of L<RT::Attribute>s to create. You likely don't need to mess with
429 this. If you do, know that the key C<Object> is expected to be an
430 L<RT::Record> object or a subroutine reference that returns an object on which
431 to call C<AddAttribute>. If you don't provide C<Object> or it's undefined,
432 C<< RT->System >> will be used.
434 Here is an example of using a subroutine reference as a value for Object:
437 Name => 'SavedSearch',
438 Description => 'New Tickets in SomeQueue',
440 my $GroupName = 'SomeQueue Group';
441 my $group = RT::Group->new( RT->SystemUser );
443 my( $ret, $msg ) = $group->LoadUserDefinedGroup( $GroupName );
444 die $msg unless $ret;
449 Format => <<' END_OF_FORMAT',
452 Query => "Status = 'new' AND Queue = 'SomeQueue'",
462 C<@Initial> and C<@Final> are special and let you write your own processing
463 code that runs before anything else or after everything else. They are
464 expected to be arrays of subrefs (usually anonymous) like so:
467 RT->Logger->info("Finishing up!");
470 You have the full power of RT's Perl libraries at your disposal. Be sure to do
471 error checking and log any errors with C<< RT->Logger->error("...") >>!
473 =head1 What's missing?
475 There is currently no way, short of writing code in C<@Final> or C<@Initial>,
476 to easily create B<Classes>, B<Topics>, or B<Articles> from initialdata files.
478 =head1 Running an initialdata file
480 sbin/rt-setup-database --action insert --datafile /path/to/your/initialdata
482 This may prompt you for a database password.
484 =head1 Implementation details
486 All the handling of initialdata files is done in C<< RT::Handle->InsertData >>.
487 If you want to know B<exactly> what's happening with each array, your best bet
488 is to start reading the code there.
490 RT takes care of the ordering so that your new queues are created before it
491 processes the new ACLs for those queues. This lets you refer to new queues you
492 just created by Name.