├── .fixtures.yml
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── Gemfile
├── LICENSE
├── README.md
├── REFERENCE.md
├── Rakefile
├── Vagrantfile
├── data
└── common.yaml
├── hiera.yaml
├── manifests
├── agent.pp
├── config.pp
├── dahdi.pp
├── dotd
│ └── file.pp
├── extensions.pp
├── feature.pp
├── iax.pp
├── init.pp
├── install.pp
├── language.pp
├── manager.pp
├── queue.pp
├── registry
│ ├── iax.pp
│ └── sip.pp
├── service.pp
├── sip.pp
└── voicemail.pp
├── metadata.json
├── renovate.json
├── spec
├── classes
│ └── init_spec.rb
└── spec_helper.rb
├── templates
├── config_file.conf.epp
├── registry
│ ├── iax.epp
│ └── sip.epp
└── snippet
│ ├── agent.epp
│ ├── feature.epp
│ ├── manager.epp
│ ├── queue.epp
│ ├── sip.epp
│ └── voicemail.epp
├── tests
├── Puppetfile
├── init.pp
└── one_of_all.pp
└── types
├── access.pp
├── extglobalvars.pp
├── featuremap.pp
├── featuresgeneral.pp
├── logfile.pp
└── managerperms.pp
/.fixtures.yml:
--------------------------------------------------------------------------------
1 | ---
2 | fixtures:
3 | symlinks:
4 | "asterisk": "#{source_dir}"
5 | forge_modules:
6 | "stdlib":
7 | repo: "puppetlabs/stdlib"
8 | ref: "8.5.0"
9 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | setup_matrix:
7 | name: 'Setup Test Matrix'
8 | runs-on: ubuntu-latest
9 | outputs:
10 | puppet_major_versions: ${{ steps.get-outputs.outputs.puppet_major_versions }}
11 | puppet_unit_test_matrix: ${{ steps.get-outputs.outputs.puppet_unit_test_matrix }}
12 | env:
13 | BUNDLE_WITHOUT: development:release
14 | steps:
15 | - uses: actions/checkout@v4
16 | - name: Setup ruby
17 | uses: ruby/setup-ruby@v1
18 | with:
19 | ruby-version: '2.7'
20 | bundler-cache: true
21 | - name: Run rake validate
22 | run: bundle exec rake validate
23 | - name: Run rake rubocop
24 | run: bundle exec rake rubocop
25 | - name: Setup Test Matrix
26 | id: get-outputs
27 | run: bundle exec metadata2gha --pidfile-workaround false
28 |
29 | unit:
30 | needs: setup_matrix
31 | runs-on: ubuntu-latest
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | include: ${{fromJson(needs.setup_matrix.outputs.puppet_unit_test_matrix)}}
36 | env:
37 | BUNDLE_WITHOUT: docs
38 | PUPPET_VERSION: "~> ${{ matrix.puppet }}.0"
39 | name: Puppet ${{ matrix.puppet }} (Ruby ${{ matrix.ruby }})
40 | steps:
41 | - uses: actions/checkout@v4
42 | - name: Setup ruby
43 | uses: ruby/setup-ruby@v1
44 | with:
45 | ruby-version: ${{ matrix.ruby }}
46 | bundler-cache: true
47 | - name: Run tests
48 | run: bundle exec rake spec
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle
2 | .vagrant
3 | /pkg
4 | spec/fixtures
5 | /doc
6 | Gemfile.lock
7 | /.yardoc
8 | /vendor
9 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format documentation
3 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | ---
2 | require: rubocop-rspec
3 | AllCops:
4 | DisplayCopNames: true
5 | TargetRubyVersion: '2.7'
6 | NewCops: enable
7 | Exclude:
8 | - bin/*
9 | - ".vendor/**/*"
10 | - pkg/**/*
11 | - spec/fixtures/**/*
12 | - vendor/**/*
13 | Layout/EmptyLinesAroundAttributeAccessor:
14 | Enabled: true
15 | Layout/LineLength:
16 | Description: People have wide screens, use them.
17 | Max: 200
18 | Layout/SpaceAroundMethodCallOperator:
19 | Enabled: true
20 | Lint/BinaryOperatorWithIdenticalOperands:
21 | Enabled: true
22 | Lint/DeprecatedOpenSSLConstant:
23 | Enabled: true
24 | Lint/DuplicateElsifCondition:
25 | Enabled: true
26 | Lint/DuplicateRescueException:
27 | Enabled: true
28 | Lint/EmptyConditionalBody:
29 | Enabled: true
30 | Lint/FloatComparison:
31 | Enabled: true
32 | Lint/MissingSuper:
33 | Enabled: true
34 | Lint/MixedRegexpCaptureTypes:
35 | Enabled: true
36 | Lint/OutOfRangeRegexpRef:
37 | Enabled: true
38 | Lint/RaiseException:
39 | Enabled: true
40 | Lint/SelfAssignment:
41 | Enabled: true
42 | Lint/StructNewOverride:
43 | Enabled: true
44 | Lint/TopLevelReturnWithArgument:
45 | Enabled: true
46 | Lint/UnreachableLoop:
47 | Enabled: true
48 | RSpec/BeforeAfterAll:
49 | Description: Beware of using after(:all) as it may cause state to leak between tests.
50 | A necessary evil in acceptance testing.
51 | Exclude:
52 | - spec/acceptance/**/*.rb
53 | RSpec/HookArgument:
54 | Description: Prefer explicit :each argument, matching existing module's style
55 | EnforcedStyle: each
56 | Style/BlockDelimiters:
57 | Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to
58 | be consistent then.
59 | EnforcedStyle: braces_for_chaining
60 | Style/ClassAndModuleChildren:
61 | Description: Compact style reduces the required amount of indentation.
62 | EnforcedStyle: compact
63 | Style/EmptyElse:
64 | Description: Enforce against empty else clauses, but allow `nil` for clarity.
65 | EnforcedStyle: empty
66 | Style/FormatString:
67 | Description: Following the main puppet project's style, prefer the % format format.
68 | EnforcedStyle: percent
69 | Style/FormatStringToken:
70 | Description: Following the main puppet project's style, prefer the simpler template
71 | tokens over annotated ones.
72 | EnforcedStyle: template
73 | Style/FrozenStringLiteralComment:
74 | Enabled: false
75 | Style/Lambda:
76 | Description: Prefer the keyword for easier discoverability.
77 | EnforcedStyle: literal
78 | Style/RegexpLiteral:
79 | Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168
80 | EnforcedStyle: percent_r
81 | Style/TernaryParentheses:
82 | Description: Checks for use of parentheses around ternary conditions. Enforce parentheses
83 | on complex expressions for better readability, but seriously consider breaking
84 | it up.
85 | EnforcedStyle: require_parentheses_when_complex
86 | Style/TrailingCommaInArguments:
87 | Description: Prefer always trailing comma on multiline argument lists. This makes
88 | diffs, and re-ordering nicer.
89 | EnforcedStyleForMultiline: comma
90 | Style/TrailingCommaInArrayLiteral:
91 | Description: Prefer always trailing comma on multiline literals. This makes diffs,
92 | and re-ordering nicer.
93 | EnforcedStyleForMultiline: comma
94 | Style/TrailingCommaInHashLiteral:
95 | Description: Prefer always trailing comma on multiline literals. This makes diffs,
96 | and re-ordering nicer.
97 | EnforcedStyleForMultiline: comma
98 | Style/SymbolArray:
99 | Description: Using percent style obscures symbolic intent of array's contents.
100 | EnforcedStyle: brackets
101 | RSpec/MessageSpies:
102 | EnforcedStyle: receive
103 | Style/CollectionMethods:
104 | Enabled: true
105 | Style/MethodCalledOnDoEndBlock:
106 | Enabled: true
107 | Style/StringMethods:
108 | Enabled: true
109 | Layout/EndOfLine:
110 | Enabled: false
111 | Metrics/AbcSize:
112 | Enabled: false
113 | Metrics/BlockLength:
114 | Enabled: false
115 | Metrics/ClassLength:
116 | Enabled: false
117 | Metrics/CyclomaticComplexity:
118 | Enabled: false
119 | Metrics/MethodLength:
120 | Enabled: false
121 | Metrics/ModuleLength:
122 | Enabled: false
123 | Metrics/ParameterLists:
124 | Enabled: false
125 | Metrics/PerceivedComplexity:
126 | Enabled: false
127 | RSpec/DescribeClass:
128 | Enabled: false
129 | RSpec/ExampleLength:
130 | Enabled: false
131 | RSpec/MessageExpectation:
132 | Enabled: false
133 | RSpec/MultipleExpectations:
134 | Enabled: false
135 | RSpec/NestedGroups:
136 | Enabled: false
137 | Style/AccessorGrouping:
138 | Enabled: true
139 | Style/ArrayCoercion:
140 | Enabled: true
141 | Style/AsciiComments:
142 | Enabled: false
143 | Style/BisectedAttrAccessor:
144 | Enabled: true
145 | Style/CaseLikeIf:
146 | Enabled: true
147 | Style/ExplicitBlockArgument:
148 | Enabled: true
149 | Style/ExponentialNotation:
150 | Enabled: true
151 | Style/GlobalStdStream:
152 | Enabled: true
153 | Style/HashAsLastArrayItem:
154 | Enabled: true
155 | Style/HashEachMethods:
156 | Enabled: true
157 | Style/HashLikeCase:
158 | Enabled: true
159 | Style/HashTransformKeys:
160 | Enabled: true
161 | Style/HashTransformValues:
162 | Enabled: true
163 | Style/IfUnlessModifier:
164 | Enabled: true
165 | Style/OptionalBooleanParameter:
166 | Enabled: true
167 | Style/RedundantAssignment:
168 | Enabled: true
169 | Style/RedundantFetchBlock:
170 | Enabled: true
171 | Style/RedundantFileExtensionInRequire:
172 | Enabled: true
173 | Style/RedundantRegexpCharacterClass:
174 | Enabled: true
175 | Style/RedundantRegexpEscape:
176 | Enabled: true
177 | Style/SingleArgumentDig:
178 | Enabled: true
179 | Style/SlicingWithRange:
180 | Enabled: true
181 | Style/StringConcatenation:
182 | Enabled: true
183 | Style/SymbolProc:
184 | Enabled: false
185 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | puppetversion = ENV.key?('PUPPET_VERSION') ? ENV['PUPPET_VERSION'].to_s : ['>= 3.3']
4 |
5 | gem 'puppet', puppetversion
6 | gem 'rake'
7 |
8 | group :tests do
9 | gem 'facter', '>= 2.4.0'
10 | # Use info from metadata.json for tests
11 | gem 'puppetlabs_spec_helper', '>= 0.10.0'
12 | gem 'puppet-lint', '>= 2.3.0'
13 | gem 'puppet_metadata'
14 | gem 'rspec-puppet', '>= 2.4.0'
15 | # This draws in rubocop and other useful gems for puppet tests
16 | gem 'voxpupuli-test'
17 | end
18 |
19 | group :docs do
20 | gem 'puppet-strings'
21 | end
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Puppet module for Asterisk
2 | ==========================
3 |
4 | To install Asterisk on a server, simply use the following:
5 |
6 | ```puppet
7 | include asterisk
8 | ```
9 |
10 | This will install a plain version of Asterisk without any extra
11 | features enabled.
12 |
13 | Users that are upgrading (e.g. switching or merging to current master) should
14 | consult the section named [Upgrade notices](#upgrade-notices) near the end.
15 |
16 | Requirements
17 | ------------
18 |
19 | In order to use this module, you need the stdlib module from:
20 |
21 | https://github.com/puppetlabs/puppetlabs-stdlib
22 |
23 | You should also make sure that augeas is installed since it is used to enable
24 | the service in `/etc/default/asterisk`.
25 |
26 | Reference reading
27 | -----------------
28 |
29 | Some good references to consult when it comes to Asterisk configuration are:
30 |
31 | * The most up to date reference and documentation for all configurations can
32 | be found in upstream default configuration files. They can also be found in
33 | the `asterisk-doc` debian package.
34 | * Online version of "Asterisk: The Definitive Guide" 3rd edition. This is
35 | definitely the best and most up to date documentation available. A must
36 | read for anyone that is configuring a PBX with Asterisk. Consult this
37 | reference if you need more information about any options that can be
38 | configured with this module. The web site mentions a 4th edition was
39 | released but it is not available online: http://asteriskdocs.org/
40 | * A good reference for VoIP and Asterisk (some information might be outdated):
41 | http://www.voip-info.org/
42 | * The Asterisk project wiki: https://wiki.asterisk.org/
43 |
44 | Configuring Asterisk
45 | ====================
46 |
47 | Parameters to the asterisk class
48 | --------------------------------
49 |
50 | The main class has a couple of parameters that determine what is managed and
51 | how general configuration is set.
52 |
53 | * `$manage_service` is a boolean that determines whether puppet will ensure
54 | that the service is running. Default value is true.
55 |
56 | * `$manage_package` is a boolean that determines whether puppet will ensure
57 | that the package is installed. Default value is true.
58 |
59 | * `$package_name` can be used to override the name of the package that
60 | installs Asterisk. Default value is "asterisk".
61 |
62 | * `$service_name` can be used to override the name of the Asterisk service.
63 | Default value is "asterisk".
64 |
65 | * `$confdir` can be used to override the path to the Asterisk configuration.
66 | Default value is "/etc/asterisk".
67 |
68 | * `$purge_confdir` is a boolean that enables or disables (default) removal of
69 | all files inside `confdir` that are not managed by puppet. This makes sure
70 | that the state of your service is well known.
71 |
72 | * `$iax_general` is a hash of global options for IAX2. See section IAX2
73 | Options.
74 |
75 | * `$sip_general` is a hash of global options for SIP. See section SIP Options.
76 |
77 | * `$voicemail_general` is a hash of global options for voicemail. See section
78 | Voicemail Options.
79 |
80 | * `$extensions_general` is a hash of global options for extensions. See
81 | section Extensions Options.
82 |
83 | Options section.
84 |
85 | * `$features_general` and `$featuremap` are detailed in the Features Options
86 | section.
87 |
88 | * `$queues_general` is detailed in the Queues Options section.
89 |
90 | * `$modules_autoload`, `$modules_noload`, `$modules_load` and
91 | `$modules_global` are detailed in the Modules section.
92 |
93 | * `$manager_enable`, `$manager_port` and `$manager_bindaddr` are detailed in
94 | the Manager Options section.
95 |
96 | ### Setting options with the $xyz_general or $xyz_global parameters ###
97 |
98 | Asterisk has lots and lots of configuration variables that can be set in
99 | different files.
100 |
101 | As you will see in some of the following configuration sections, some
102 | configuration files will be customizable through option hashes. The format of
103 | those hashes is always the same and looks like the following, where xyz would
104 | match the name of the configuration file:
105 |
106 | ```puppet
107 | $xyz_general = {
108 | 'configuration-option1' => 'value1',
109 | 'allow' => ['list-value1', 'list-value2'],
110 | #[...]
111 | }
112 | ```
113 |
114 | In order to simplify the module, we're actually not validating that the options
115 | passed in are valid ones and expect this validation to be done by the user.
116 |
117 | We encourage users to use strings as hash keys as in the example above since
118 | some Asterisk options have dashes in their name and dashes are prohibited in
119 | puppet DSL symbols.
120 |
121 | Some options should always be arrays: the option can be specified in the
122 | configuration file more than once to declare more values. Those options will
123 | always be set in the hashes that define default values (see in each section
124 | below) as arrays either containing a number of strings, or being empty. The
125 | module enforces that those options be arrays since it needs to iterate over them
126 | in templates. Empty arrays mean that the option should not appear in the
127 | configuration file.
128 |
129 | Default values are taken from Debian's default configuration files.
130 |
131 | Keys that are present in the option hash paramters to the `asterisk` class will
132 | override the default options (or set new ones for options that are not present
133 | in the default option hash). This lets you use all the default values but
134 | change only a couple of values.
135 |
136 | Source or content
137 | -----------------
138 |
139 | Most of the defined types that drop a configuration file in a .d directory can
140 | either take a puppet source specification (of the form 'puppet:///modules/...'
141 | or a textual content.
142 |
143 | The puppet source specification is always used with the `source` parameter and
144 | textual content with the `content` parameter.
145 |
146 | When using a puppet source specification the user has complete control over the
147 | contents of the configuration file. When textual content is used, the contents
148 | will usually be added after a line that defines a configuration section (e.g. a
149 | line of the form '[section]').
150 |
151 | `source` and `content` are always mutually exclusive.
152 |
153 | IAX2
154 | ----
155 |
156 | The `asterisk::iax` defined type helps you configure an IAX2 channel. `source`
157 | or `content` can be used with this type.
158 |
159 | ```puppet
160 | asterisk::iax { '5551234567':
161 | source => 'puppet:///modules/site_asterisk/5551234567',
162 | }
163 | ```
164 |
165 | The `asterisk::registry::iax` defined type is used to configure an IAX2
166 | registry. All parameters (except for ensure) are mandatory. For example:
167 |
168 | ```puppet
169 | asterisk::registry::iax { 'providerX':
170 | server => 'iax.providerX.com',
171 | user => 'doyoufindme',
172 | pass => 'attractive?',
173 | }
174 | ```
175 |
176 | ### IAX2 Options ###
177 |
178 | If you are using the IAX2 protocol, you'll want to set some global
179 | configuration options. For passing in settings, you need to send a hash to the
180 | `asterisk` class with the `iax_general` parameter.
181 |
182 | Here is the default hash with the default values, as defined in params.pp:
183 |
184 | ```puppet
185 | $iax_general = {
186 | 'allow' => [],
187 | 'disallow' => ['lpc10'],
188 | 'bandwidth' => 'low',
189 | 'jitterbuffer' => 'no',
190 | 'forcejitterbuffer' => 'no',
191 | 'autokill' => 'yes',
192 | 'delayreject' => 'yes',
193 | }
194 | ```
195 |
196 | SIP
197 | ---
198 |
199 | You can configure SIP channels with the `asterisk::sip` defined type. `source`
200 | and `content` can be used with this type.
201 |
202 | ```puppet
203 | asterisk::sip { '1234':
204 | ensure => present,
205 | secret => 'blah',
206 | context => 'incoming',
207 | }
208 | ```
209 |
210 | You can also use the `template_name` argument to either define a template, or
211 | make the channel definition inherit from a template.
212 |
213 | To define a template, set `template_name` to '!':
214 |
215 | ```puppet
216 | asterisk::sip { 'corporate_user':
217 | context => 'corporate',
218 | type => 'friend',
219 | # ...
220 | template_name => '!',
221 | }
222 | ```
223 |
224 | If inheriting from a template, set `template_name` to
225 | the name of the template from which the channel is inheriting options.
226 |
227 | ```puppet
228 | asterisk::sip { 'hakim':
229 | secret => 'ohnoes!',
230 | template_name => 'corporate_user',
231 | }
232 | ```
233 |
234 | The defined type `asterisk::registry::sip` lets you configure a SIP registry.
235 | The `server` and `user` paramters are mandatory.
236 |
237 | ```puppet
238 | asterisk::registry::sip { 'providerX':
239 | server => 'sip.providerX.com',
240 | user => 'doyoufindme',
241 | }
242 | ```
243 |
244 | Password, authuser, port number and extension are optional parameters. If you
245 | define authuser, you must specify a password.
246 |
247 | ```puppet
248 | asterisk::registry::sip { 'friends_home':
249 | server => 'home.friend.com',
250 | port => '8888',
251 | user => 'me',
252 | password => 'myselfandI',
253 | authuser => 'you',
254 | extension => 'whatsupfriend',
255 | }
256 | ```
257 |
258 |
259 | ### SIP Options ###
260 |
261 | If you are using the SIP protocol, you'll want to set some global
262 | configuration options. For passing in settings, you need to send a hash to the
263 | `asterisk` class with the `sip_general` parameter.
264 |
265 | Here is the default hash with the default values, as defined in params.pp:
266 |
267 | ```puppet
268 | $sip_general = {
269 | 'disallow' => [],
270 | 'allow' => [],
271 | 'domain' => [],
272 | 'localnet' => [],
273 | 'context' => 'default',
274 | 'allowoverlap' => 'no',
275 | 'udpbindaddr' => '0.0.0.0',
276 | 'tcpenable' => 'no',
277 | 'tcpbindaddr' => '0.0.0.0',
278 | 'transport' => 'udp',
279 | 'srvlookup' => 'yes',
280 | 'allowguest' => 'no',
281 | 'alwaysauthreject' => 'yes',
282 | }
283 | ```
284 |
285 | ### SIP encryption ###
286 |
287 | If you want to enable SIP encryption, you can set the following settings in the
288 | `sip_general` parameter to the `asterisk` class:
289 |
290 | ```puppet
291 | $sip_option = {
292 | 'transports' => ['tls'],
293 | 'encryption' => 'yes',
294 | 'tlsenable' => 'yes',
295 | # Change the following two values to the full paths where you're placing your
296 | # own certificat and CA files, respectively.
297 | 'tlscertfile' => '/etc/ssl/somecert.crt',
298 | 'tlscafile' => '/etc/ssl/someca.crt',
299 | # Only set this to 'yes' if you can't possibly get a verifiable certificate.
300 | 'tlsdontverifyserver' => 'no',
301 | }
302 | ```
303 |
304 | Note: the 'transports' option needs to be an array, so even though you only
305 | enable 'tls' as a transport, you need to enclose the string inside an array.
306 |
307 | Voicemail
308 | ---------
309 |
310 | With the defined type `asterisk::voicemail` you can configure a voicemail. The
311 | `context` and `password` parameters are mandatory:
312 |
313 | ```puppet
314 | asterisk::voicemail { '3000':
315 | context => 'some_context',
316 | password => '5555',
317 | user_name => 'Bob Bobby',
318 | email => 'bob@bobby.comcom',
319 | }
320 | ```
321 |
322 | You can also use the optional 'pager_email' parameter to set the email that
323 | should receive a page about new voice messages.
324 |
325 | And finally, the argument 'options' can take a hash of voicemail options like
326 | the following:
327 |
328 | ```puppet
329 | asterisk::voicemail { '3001':
330 | context => 'blah',
331 | password => '112233',
332 | options => { 'attach' => 'yes', 'delete' => 'yes' },
333 | }
334 | ```
335 |
336 | ### Voicemail Options ###
337 |
338 | Voicemail can be configured through a set of options in the `[general]`
339 | context. To set those options, you can pass values as a hash to the
340 | `voicemail_general` parameter to the main class.
341 |
342 | Here is the default hash with the default values, as defined in params.pp:
343 |
344 | ```puppet
345 | $voicemail_general = {
346 | 'format' => 'wav49|gsm|wav',
347 | 'serveremail' => 'asterisk',
348 | 'attach' => 'yes',
349 | 'skipms' => 3000,
350 | 'maxsilence' => 10,
351 | 'silencethreshold' => 128,
352 | 'maxlogins' => 3,
353 | # This is not really the default value for emailbody but it makes more
354 | # sense to be a bit more verbose by default.
355 | 'emailbody' => 'Dear ${VM_NAME}:\n\n\tjust wanted to let you know you were just ${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?left:forwarded)} a ${VM_DUR} long message (number ${VM_MSGNUM})\nin mailbox ${VM_MAILBOX} from ${VM_CALLERID} <${VM_CIDNUM}>, on ${VM_DATE},\n${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?so:(originally sent by ${ORIG_VM_CALLERID} on ${ORIG_VM_DATE})\nso)} you might want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n',
356 | 'emaildateformat' => '%A, %B %d, %Y at %r',
357 | 'pagerdateformat' => '%A, %B %d, %Y at %r',
358 | 'sendvoicemail' => 'yes',
359 | }
360 | ```
361 |
362 | Extensions
363 | ----------
364 |
365 | Extensions can be set with the `asterisk::extensions` defined type. `source` or
366 | `content` can be used with this type.
367 |
368 | ```puppet
369 | asterisk::extensions { 'incoming':
370 | ensure => present,
371 | content => template('site_asterisk/extensions/incoming.erb'),
372 | }
373 | ```
374 |
375 | ### Extensions Options ###
376 |
377 | Some global options can be set for extensions. You can achieve that by passing
378 | a hash to the `extensions_general` parameter to the `asterisk` class.
379 |
380 | Here is the default hash with the default values, as defined in params.pp:
381 |
382 | ```puppet
383 | $extensions_general = {
384 | 'static' => 'yes',
385 | 'writeprotect' => 'no',
386 | 'clearglobalvars' => 'no',
387 | }
388 | ```
389 |
390 | Note that by default no global variables (e.g. values set in the `[globals]`
391 | context) are set. To set global variables, you can use an
392 | `asterisk::extensions` resource with a context value of "globals".
393 |
394 | Agents
395 | ------
396 |
397 | To define an agent you can use the `asterisk::agent` defined type. The `ext`,
398 | `password` and `agent_name` parameters are mandatory.
399 |
400 | To define a static agent:
401 |
402 | ```puppet
403 | asterisk::agent { 'joe':
404 | ext => '1001',
405 | password => '123413425',
406 | agent_name => 'Joe Bonham',
407 | }
408 | ```
409 |
410 | You can also assign a static agent to one or more agent groups with the
411 | `groups` parameter. This parameter is a list of group names:
412 |
413 | ```puppet
414 | asterisk::agent { 'cindy':
415 | ext => '1002',
416 | password => '754326',
417 | agent_name => 'Cindy Rotterbauer',
418 | groups => ['1']
419 | }
420 | ```
421 |
422 | Static agents have some disadvantages compared to dynamic agents. For example,
423 | once assigned to a queue they cannot logout of that queue. For more information
424 | on how to setup dynamic agents, see:
425 |
426 | * [https://www.voip-info.org/asterisk-cmd-agentlogin](https://www.voip-info.org/asterisk-cmd-agentlogin)
427 | * [https://www.voip-info.org/asterisk-cmd-addqueuemember](https://www.voip-info.org/asterisk-cmd-addqueuemember)
428 | * [https://www.voip-info.org/asterisk-cmd-removequeuemember](https://www.voip-info.org/asterisk-cmd-removequeuemember)
429 |
430 | ### Agents Options ###
431 |
432 | Global options in the `[agents]` context can be set by passing a hash to the
433 | `agents_global` parameter to the `asterisk` class. By default this parameter
434 | doesn't define any global options.
435 |
436 | For creating agents, it is recommended to use the `asterisk::agent` defined
437 | type.
438 |
439 | Features
440 | --------
441 |
442 | Features let you configure call parking and special numbers that trigger
443 | special functionality. The `asterisk::feature` defined type helps you
444 | configuring such features. The `options` parameter is mandatory.
445 |
446 | Define features that are contained within feature group "myfeaturegroup":
447 |
448 | ```puppet
449 | $ft_options = {
450 | 'pausemonitor' => '#1,self/callee,Pausemonitor',
451 | 'unpauseMonitor' => '#3,self/callee,UnPauseMonitor',
452 | }
453 | asterisk::feature { 'myfeaturegroup':
454 | options => $ft_options,
455 | }
456 | ```
457 |
458 | A special section in the features configuration file, namely
459 | `[applicationmaps]` lets you define global features. The
460 | `asterisk::feature::applicationmap` defined type helps you configure such a
461 | global feature. The `feature` and `value` parameters are mandatory:
462 |
463 | ```puppet
464 | asterisk::feature::applicationmap { 'pausemonitor':
465 | feature => 'pausemonitor',
466 | value => '#1,self/callee,Pausemonitor',
467 | }
468 | ```
469 |
470 | ### Features global configurations ###
471 |
472 | Some global feature options can be configured, like the default parkinglot, via
473 | the `features_general` parameter to the `asterisk` class.
474 |
475 | Here is the default hash with the default values, as defined in params.pp:
476 |
477 | ```puppet
478 | $features_general = {
479 | 'parkext' => '700',
480 | 'parkpos' => '701-720',
481 | 'context' => 'parkedcalls',
482 | }
483 | ```
484 |
485 | A special context, `featuremap`, lets you configure global features. By
486 | default, no feature is configured. You can pass a hash to the
487 | `features_featuremap` parameter to the `asterisk` class to configure features
488 | in this context.
489 |
490 | Another special context, `applicationmap`, lets you configure dynamic features.
491 | To set entries in this context, you should use the
492 | `asterisk::feature::applicationmap` defined type. Note also that for dynamic
493 | features to work the DYNAMIC_FEATURES channel variable must be set by listing
494 | features enabled in the channel, separated by '#'.
495 |
496 | To configure additional feature contexts, you can use the `asterisk::feature`
497 | defined type.
498 |
499 | Queues
500 | ------
501 |
502 | Asterisk can put call in queues, for example when all agents are busy and the call cannot get connected. To create a queue, you can use the `asterisk::queue` defined type:
503 |
504 | ```puppet
505 | asterisk::queue { 'frontline':
506 | ensure => present,
507 | stragegy => 'rrmemory',
508 | members => [
509 | 'SIP/reception',
510 | 'SIP/secretary',
511 | ],
512 | maxlen => 30,
513 | timeout => 20,
514 | retry => 10,
515 | }
516 | ```
517 |
518 | Call queues have lots of options and can interact with agents. Because of this
519 | we will not detail all of the parameters here. Please refer to the
520 | manifests/queue.pp file for the complete list of supported parameters. Also,
521 | for an in-depth coverage of call queueing, see:
522 | http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/asterisk-ACD.html
523 |
524 | ### Queues Options ###
525 |
526 | For queues some global configurations and default values can be set in the
527 | `[general]` context. You can set options by passing a hash to the
528 | `queues_general` parameter to the `asterisk` class.
529 |
530 | Here is the default hash with the default values, as defined in params.pp:
531 |
532 | ```puppet
533 | $queues_general = {
534 | 'persistentmembers' => 'yes',
535 | 'monitor-type' => 'MixMonitor',
536 | }
537 | ```
538 |
539 | Modules
540 | -------
541 |
542 | Configuring Asterisk modules is key to implementing your features right. Four
543 | parameter to the `asterisk` class offer you the possibility to customize what
544 | modules are loaded or not on your PBX. Default values for the parameters were
545 | taken from the default config file in Debian.
546 |
547 | * `modules_autoload`: a boolean value (defaults to `true`) that decides
548 | whether or not Asterisk will try to automatically load required modules even
549 | though they are not explicitely marked as needing to be loaded in the
550 | modules.conf file.
551 |
552 | * `modules_noload`: an array of strings of explicitely unwanted modules that
553 | won't load even though `modules_autoload` is true. Specifying an array to
554 | this parameter overrides the default list so make sure to include all
555 | unwanted modules. The default array is the following:
556 |
557 | ```puppet
558 | $modules_noload = [
559 | 'pbx_gtkconsole.so',
560 | 'pbx_kdeconsole.so',
561 | 'app_intercom.so',
562 | 'chan_modem.so',
563 | 'chan_modem_aopen.so',
564 | 'chan_modem_bestdata.so',
565 | 'chan_modem_i4l.so',
566 | 'chan_capi.so',
567 | 'chan_alsa.so',
568 | 'cdr_sqlite.so',
569 | 'app_directory_odbc.so',
570 | 'res_config_odbc.so',
571 | 'res_config_pgsql.so'
572 | ]
573 | ```
574 |
575 | * `modules_load`: an array of strings of explicitely wanted modules.
576 | Specifying an array to this parameter overrides the default list so make
577 | sure to include all wanted modules. The default array is the following:
578 |
579 | ```puppet
580 | $modules_load = ['res_musiconhold.so']
581 | ```
582 |
583 | * `modules_global`: a hash of options that should be set in the
584 | `[global]` context. These options let you customize behaviours for modules
585 | that are loaded.
586 |
587 | Managers
588 | --------
589 |
590 | Asterisk can expose an interface for managing the PBX. This interface can be
591 | offered to different users with different permissions. You can configure read
592 | and write access to certain features of the PBX for each user.
593 |
594 | The `asterisk::manager` defined type helps you configure a manager access. The
595 | `secret` parameter is mandatory. By default, the resource name is used as the
596 | manager name:
597 |
598 | ```puppet
599 | asterisk::manager { 'nagios':
600 | secret => 'topsecret1234',
601 | read => ['all'],
602 | write => ['system', ' call', ' log', ' verbose', ' command', ' agent', ' user'],
603 | }
604 | ```
605 |
606 | Here's a paranoid version of the above configuration, with minimal network
607 | access, but the option to run system commands and trigger calls:
608 |
609 | ```puppet
610 | asterisk::manager { 'nagios':
611 | secret => 'topsecret1234',
612 | read => ['system', 'call'],
613 | write => ['system', 'call'],
614 | }
615 | ```
616 |
617 | Here, we permit remote management to two other systems on an internal network:
618 |
619 | ```puppet
620 | asterisk::manager { 'robocall':
621 | secret => 'robotsdeservesomeloveafterall',
622 | permit => ['10.10.10.200/255.255.255.0', '10.20.20.200/255.255.255.0'],
623 | read => ['system', 'call', 'log'],
624 | write => ['system', 'call', 'originate'],
625 | }
626 | ```
627 |
628 | To override the manager name, you can use the `manager_name` parameter:
629 |
630 | ```puppet
631 | asterisk::manager { 'sysadmin':
632 | secret => 'nowyouseemenowyoudont',
633 | read => ['all'],
634 | write => ['all'],
635 | manager_name => 'surreptitioustyrant',
636 | }
637 | ```
638 |
639 | ### Manager Options ###
640 |
641 | Asterisk maintains a service on a port through which you can inspect asterisk's
642 | state and issue commands to the PBX. You can control on which IP and port it
643 | binds to and if it is enabled at all with three parameters to the `asterisk`
644 | class.
645 |
646 | * `manager_enable`: a boolean value that decides whether or not the manager is
647 | in function. Defaults to true.
648 |
649 | * `manager_port`: an integer value that specifies on which port the manager
650 | will listen. Default value is 5038.
651 |
652 | * `manager_bindaddr`: a string that contains the IP address on which the
653 | manager should bind. Default value is 127.0.0.1.
654 |
655 | By default, no user access is configured. If you want to enable users to
656 | interact with the manager, you should declare `asterisk::manager`
657 | resources.
658 |
659 | Dahdi
660 | -----
661 |
662 | Dahdi is a set of kernel modules combined with an asterisk module that let
663 | people interact with Digium cards to send and receive calls from the POTS. To
664 | enable dahdi, use the following:
665 |
666 | ```puppet
667 | include 'asterisk::dahdi'
668 | ```
669 |
670 | Language sounds
671 | ---------------
672 |
673 | To include any language sounds, you can use the following (in this example,
674 | we're installing french and spanish sounds):
675 |
676 | ```puppet
677 | asterisk::language {
678 | ['fr-armelle', 'es']:
679 | }
680 | ```
681 |
682 | Valid languages strings are the following (these are all based on debian
683 | package names for now -- either asterisk-prompt-X or asterisk-Y. the language
684 | strings that start with core-sounds enable you to install language sounds in a
685 | specific encoding to avoid the need for asterisk to recode it while feeding it
686 | to a device):
687 |
688 | * de
689 | * es-co
690 | * fr-armelle
691 | * fr-proformatique
692 | * it-menardi
693 | * it-menardi-alaw
694 | * it-menardi-gsm
695 | * it-menardi-wav
696 | * se
697 | * es
698 | * core-sounds-en
699 | * core-sounds-en-g722
700 | * core-sounds-en-gsm
701 | * core-sounds-en-wav
702 | * core-sounds-es
703 | * core-sounds-es-g722
704 | * core-sounds-es-gsm
705 | * core-sounds-es-wav
706 | * core-sounds-fr
707 | * core-sounds-fr-g722
708 | * core-sounds-fr-gsm
709 | * core-sounds-fr-wav
710 | * core-sounds-ru
711 | * core-sounds-ru-g722
712 | * core-sounds-ru-gsm
713 | * core-sounds-ru-wav
714 |
715 | Upgrade notices
716 | ===============
717 |
718 | * The module used to manage files under /etc/asterisk/file.conf.d
719 | for all values of "file" that were managed. Things have been moved to
720 | /etc/asterisk/file.d, so before upgrading you should remove all .conf.d
721 | directories (all files under the old dirs will be automatically recreated in
722 | the new directories).
723 |
724 | * The defines that were previously named asterisk::context::xyz (or
725 | transitorily asterisk::snippet::xyz) are now named asterisk::xyz. Users will
726 | need to adjust their manifests to upgrade.
727 |
728 | * The `queues_monitor_type` and `queues_monitor_format` parameters to the
729 | default class were removed in favor of using quoted strings in the options
730 | array. Users who used those two options need to place their values in the
731 | `$queues_general` hash with 'monitor-type' and 'monitor-format' strings as
732 | keys, respectively. To ensure that 'monitor-type' is not present in the
733 | config file, simply leave it out (as opposed to the previous behaviour of
734 | the option that required an empty string for this).
735 |
736 | * Some default values were removed and some others were modified to be closer
737 | to default Debian config files. You should verify that new values or
738 | variables that disappear won't have an impact on your setup.
739 |
740 | Patches and Testing
741 | ===================
742 |
743 | Contributions are highly welcomed, more so are those which contribute patches
744 | with tests. Or just more tests! We have
745 | [rspec-puppet](http://rspec-puppet.com/) tests.
746 | When [contributing patches](Github WorkFlow), please make sure that your
747 | patches pass tests:
748 |
749 | user@host01 ~/src/bw/puppet-composer (git)-[master] % rake tests
750 | ....................................
751 |
752 | Finished in 2.29 seconds
753 | 36 examples, 0 failures
754 |
755 |
756 | Still not implemented !
757 | -----------------------
758 |
759 | Types:
760 |
761 | * `asterisk::mwi`
762 |
763 | License
764 | =======
765 |
766 | This module is licensed under the GPLv3+, feel free to redistribute, modify and
767 | contribute changes.
768 |
769 | A copy of the GPLv3 license text should be included with the module. If not,
770 | check out the github repository at https://github.com/lelutin/puppet-asterisk
771 | or one of its clones.
772 |
773 | The license text can also be downloaded from:
774 |
775 | https://www.gnu.org/licenses/gpl-3.0.txt
776 |
777 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'puppetlabs_spec_helper/rake_tasks'
2 | require 'puppet-syntax/tasks/puppet-syntax'
3 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure('2') do |config|
5 | config.vm.box = 'debian/bullseye64'
6 |
7 | config.vm.define :test do |test|
8 | # This shell script will make sure that you have your module copied in
9 | # place with all of its current dependencies as they are declared in
10 | # metadata.json.
11 | # Note though that only the latest git commit will get deployed; you won't
12 | # be able to test changes that are still uncommitted. This is a bit
13 | # annoying.
14 | # Also, because librarian-puppet caches things, if you create a new commit
15 | # in the module, you will need to either destroy/up the VM or ssh in, and
16 | # run the following:
17 | # sudo -i
18 | # cd /tmp/vagrant-puppet
19 | # libraria-puppet clean
20 | # rm Puppetfile.lock
21 | # After the above you can run vagrant provision to test the newest commit.
22 | #
23 | # You do NOT want to have librarian-puppet work on a synced_dir if it's
24 | # using nfs: this could destroy all your files on the host.
25 | test.vm.provision 'install librarian-puppet and install dependencies', type: 'shell' do |s|
26 | s.inline = <<-SHELL
27 | apt-get update
28 | apt-get install -y librarian-puppet git
29 | cd /tmp/vagrant-puppet/
30 | [[ -L Puppetfile ]] || ln -s /vagrant/tests/Puppetfile Puppetfile
31 | librarian-puppet install --verbose
32 | SHELL
33 | end
34 |
35 | test.vm.provision :puppet do |puppet|
36 | puppet.manifests_path = 'tests'
37 | # Change this to any file name in tests/ to run another test
38 | puppet.manifest_file = 'init.pp'
39 | puppet.options = ['--modulepath', '/tmp/vagrant-puppet/modules']
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/data/common.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | asterisk::manage_service: true
3 | asterisk::manage_package: true
4 | asterisk::package_name:
5 | - 'asterisk'
6 | - 'asterisk-core-sounds-en'
7 | - 'asterisk-core-sounds-en-gsm'
8 | asterisk::service_name: 'asterisk'
9 | asterisk::confdir: '/etc/asterisk'
10 | asterisk::purge_confdir: false
11 | asterisk::iax_general:
12 | allow: []
13 | disallow:
14 | - 'lpc10'
15 | bandwidth: 'low'
16 | jitterbuffer: 'no'
17 | forcejitterbuffer: 'no'
18 | autokill: 'yes'
19 | # Some added security default options
20 | delayreject: 'yes'
21 | asterisk::sip_general:
22 | disallow: []
23 | allow: []
24 | domain: []
25 | localnet: []
26 | context: 'default'
27 | allowoverlap: 'no'
28 | udpbindaddr: '0.0.0.0'
29 | tcpenable: 'no'
30 | tcpbindaddr: '0.0.0.0'
31 | transport: 'udp'
32 | srvlookup: 'yes'
33 | # Some added security default options
34 | allowguest: 'no'
35 | alwaysauthreject: 'yes'
36 | asterisk::voicemail_general:
37 | format: 'wav49|gsm|wav'
38 | serveremail: 'asterisk'
39 | attach: 'yes'
40 | skipms: 3000
41 | maxsilence: 10
42 | silencethreshold: 128
43 | maxlogins: 3
44 | # This is not really the default value for emailbody but it makes more
45 | # sense to be a bit more verbose by default.
46 | # NOTE: the value to this parameter needs to be on one line only and thus
47 | # it needs to contain litteral \n and \t character sequences. If the value
48 | # spans multiple lines, asterisk is confused about what's in the
49 | # configuration file.
50 | emailbody: 'Dear ${VM_NAME}:\n\n\tjust wanted to let you know you were just ${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?left:forwarded)} a ${VM_DUR} long message (number ${VM_MSGNUM})\nin mailbox ${VM_MAILBOX} from ${VM_CALLERID} <${VM_CIDNUM}>, on ${VM_DATE},\n${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?so:(originally sent by ${ORIG_VM_CALLERID} on ${ORIG_VM_DATE})\nso)} you might want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n'
51 | emaildateformat: '%A, %B %d, %Y at %r'
52 | pagerdateformat: '%A, %B %d, %Y at %r'
53 | sendvoicemail: 'yes'
54 | asterisk::extensions_general:
55 | static: 'yes'
56 | writeprotect: 'no'
57 | clearglobalvars: 'no'
58 | asterisk::extensions_globals: {}
59 | asterisk::agents_global: {}
60 | # defines the default parkinglot
61 | asterisk::features_general:
62 | parkext: '700'
63 | parkpos: '701-720'
64 | context: 'parkedcalls'
65 | asterisk::features_featuremap: {}
66 | asterisk::features_applicationmap: {}
67 | asterisk::logger_general: {}
68 | asterisk::log_files:
69 | console:
70 | levels:
71 | - 'notice'
72 | - 'warning'
73 | - 'error'
74 | messages:
75 | levels:
76 | - 'notice'
77 | - 'warning'
78 | - 'error'
79 | asterisk::queues_general:
80 | persistentmembers: 'yes'
81 | monitor-type: 'MixMonitor'
82 | asterisk::modules_autoload: true
83 | asterisk::modules_preload: []
84 | asterisk::modules_noload:
85 | - 'pbx_gtkconsole.so'
86 | - 'pbx_kdeconsole.so'
87 | - 'app_intercom.so'
88 | - 'chan_modem.so'
89 | - 'chan_modem_aopen.so'
90 | - 'chan_modem_bestdata.so'
91 | - 'chan_modem_i4l.so'
92 | - 'chan_capi.so'
93 | - 'chan_alsa.so'
94 | - 'chan_console.so'
95 | - 'chan_oss.so'
96 | - 'cdr_sqlite.so'
97 | - 'app_directory_odbc.so'
98 | - 'res_config_odbc.so'
99 | - 'res_config_pgsql.so'
100 | asterisk::modules_load:
101 | - 'res_musiconhold.so'
102 | asterisk::modules_global: {}
103 | asterisk::manager_enable: true
104 | asterisk::manager_port: 5038
105 | asterisk::manager_bindaddr: '127.0.0.1'
106 | # resources created by create_resources. none by default
107 | asterisk::iax_contexts: {}
108 | asterisk::iax_registries: {}
109 | asterisk::sip_peers: {}
110 | asterisk::sip_registries: {}
111 | asterisk::voicemails: {}
112 | asterisk::extension_contexts: {}
113 | asterisk::agents: {}
114 | asterisk::features: {}
115 | asterisk::queues: {}
116 | asterisk::manager_accounts: {}
117 |
--------------------------------------------------------------------------------
/hiera.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | version: 5
3 | hierarchy:
4 | - name: "common"
5 | path: "common.yaml"
6 |
--------------------------------------------------------------------------------
/manifests/agent.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an asterisk agent
2 | #
3 | # @example Basic agent
4 | # asterisk::agent { 'provocateur':
5 | # ext => '700',
6 | # password => Sensitive.new('supersecret'),
7 | # agent_name => 'provocateur',
8 | # }
9 | #
10 | # @see https://www.voip-info.org/asterisk-cmd-agentlogin Dynamic agent login
11 | # @see https://www.voip-info.org/asterisk-cmd-addqueuemember Adding agents to queues
12 | # @see https://www.voip-info.org/asterisk-cmd-removequeuemember Removing agents from queues
13 | #
14 | # @param ext
15 | # Extension corresponding to the agent.
16 | # @param password
17 | # Login password of the agent.
18 | # @param agent_name
19 | # Name by which the agent is referred to within dialplan.
20 | # @param ensure
21 | # Can be set to absent to remove a given agent.
22 | # @param groups
23 | # List of groups to which the agent is associated.
24 | #
25 | define asterisk::agent (
26 | String $ext,
27 | Sensitive[String] $password,
28 | String $agent_name,
29 | Stdlib::Ensure::File::File $ensure = file,
30 | Array[String[1]] $groups = []
31 | ) {
32 | $agent_variables = {
33 | groups => $groups,
34 | ext => $ext,
35 | password => $password,
36 | agent_name => $agent_name,
37 | }
38 | asterisk::dotd::file { "agent_${name}.conf":
39 | ensure => $ensure,
40 | dotd_dir => 'agents.d',
41 | content => epp('asterisk/snippet/agent.epp', $agent_variables),
42 | filename => "${name}.conf",
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/manifests/config.pp:
--------------------------------------------------------------------------------
1 | # @summary asterisk basic configuration files.
2 | #
3 | # This class is not intended to be used directly.
4 | #
5 | # @api private
6 | #
7 | class asterisk::config {
8 | assert_private()
9 |
10 | file { $asterisk::confdir:
11 | ensure => directory,
12 | owner => 'asterisk',
13 | group => 'asterisk',
14 | mode => '0755',
15 | }
16 |
17 | if $asterisk::purge_confdir {
18 | File[$asterisk::confdir] {
19 | purge => true,
20 | recurse => true,
21 | }
22 | }
23 |
24 | $cf_with_directory = [
25 | 'iax',
26 | 'sip',
27 | 'voicemail',
28 | 'extensions',
29 | 'agents',
30 | 'features',
31 | 'queues',
32 | 'manager',
33 | ]
34 | $directories = $cf_with_directory + ['iax.registry', 'sip.registry']
35 |
36 | $directories.each |String $dir| {
37 | file { "${asterisk::confdir}/${dir}.d":
38 | ensure => directory,
39 | owner => 'asterisk',
40 | group => 'asterisk',
41 | mode => '0750',
42 | }
43 |
44 | # lint:ignore:140chars
45 | # Avoid error messages
46 | # [Nov 19 16:09:48] ERROR[3364] config.c: *********************************************************
47 | # [Nov 19 16:09:48] ERROR[3364] config.c: *********** YOU SHOULD REALLY READ THIS ERROR ***********
48 | # [Nov 19 16:09:48] ERROR[3364] config.c: Future versions of Asterisk will treat a #include of a file that does not exist as an error, and will fail to load that configuration file. Please ensure that the file '/etc/asterisk/iax.conf.d/*.conf' exists, even if it is empty.
49 | # lint:endignore
50 | file { "${asterisk::confdir}/${dir}.d/null.conf":
51 | ensure => file,
52 | owner => 'asterisk',
53 | group => 'asterisk',
54 | mode => '0640',
55 | content => '',
56 | }
57 | }
58 |
59 | # Options for the logfiles configuration file need some special per-line
60 | # formatting. This creates one formatted string value for each config line
61 | # and returns a hash with the string values instead of the sub-hash.
62 | $formatted_logfiles = $asterisk::log_files.map |$section, $options| {
63 | if $options['formatter'] !~ Undef {
64 | $formatter = "[${options['formatter']}]"
65 | }
66 | else {
67 | $formatter = ''
68 | }
69 |
70 | $return_value = {
71 | $section => "${formatter}${options['levels'].join(',')}",
72 | }
73 | }.reduce({}) |$result, $value| { $result + $value }
74 |
75 | $configs_with_registry = ['iax', 'sip']
76 | $config_sections = {
77 | iax => {
78 | general => {
79 | delimiter => '=',
80 | options => $asterisk::iax_general,
81 | },
82 | },
83 | sip => {
84 | general => {
85 | delimiter => '=',
86 | options => $asterisk::sip_general,
87 | },
88 | },
89 | voicemail => {
90 | general => {
91 | delimiter => '=',
92 | options => $asterisk::voicemail_general,
93 | },
94 | },
95 | extensions => {
96 | general => {
97 | delimiter => '=',
98 | options => $asterisk::extensions_general,
99 | },
100 | globals => {
101 | delimiter => '=',
102 | options => $asterisk::extensions_globals,
103 | },
104 | },
105 | agents => {
106 | general => {
107 | delimiter => '=',
108 | options => {},
109 | },
110 | agents => {
111 | delimiter => '=',
112 | options => $asterisk::agents_global,
113 | },
114 | },
115 | features => {
116 | general => {
117 | delimiter => '=',
118 | options => $asterisk::features_general,
119 | },
120 | featuremap => {
121 | delimiter => ' => ',
122 | options => $asterisk::features_featuremap,
123 | },
124 | applicationmap => {
125 | delimiter => ' => ',
126 | options => $asterisk::features_applicationmap,
127 | },
128 | },
129 | queues => {
130 | general => {
131 | delimiter => '=',
132 | options => $asterisk::queues_general,
133 | },
134 | },
135 | logger => {
136 | general => {
137 | delimiter => '=',
138 | options => $asterisk::logger_general,
139 | },
140 | logfiles => {
141 | delimiter => ' => ',
142 | options => $formatted_logfiles,
143 | },
144 | },
145 | manager => {
146 | general => {
147 | delimiter => '=',
148 | options => {
149 | enabled => $asterisk::manager_enable,
150 | port => $asterisk::manager_port,
151 | bindaddr => $asterisk::manager_bindaddr,
152 | },
153 | },
154 | },
155 | modules => {
156 | modules => {
157 | delimiter => ' => ',
158 | # Asterisk's config format is really weird. It looks like ini file but
159 | # it's not exactly that, and it can sometimes (like in this case) mix
160 | # up two types of option delimiters in the same section. The value in
161 | # oddball_options use '=' instead of ' => '
162 | oddball_delimiter => '=',
163 | oddball_options => {
164 | autoload => bool2str($asterisk::modules_autoload, 'yes', 'no'),
165 | },
166 | options => {
167 | preload => $asterisk::modules_preload,
168 | load => $asterisk::modules_load,
169 | noload => $asterisk::modules_noload,
170 | },
171 | },
172 | global => {
173 | delimiter => '=',
174 | options => $asterisk::modules_global,
175 | },
176 | },
177 | }
178 |
179 | $config_files = $cf_with_directory + [
180 | 'logger',
181 | 'modules',
182 | ]
183 | $config_files.each |String $filename| {
184 | if $filename in $cf_with_directory {
185 | $main_cf_dir = ["${filename}.d"]
186 | }
187 | else {
188 | $main_cf_dir = []
189 | }
190 |
191 | if $filename in $configs_with_registry {
192 | $cf_directories = $main_cf_dir + ["${filename}.registry.d"]
193 | } else {
194 | $cf_directories = $main_cf_dir
195 | }
196 |
197 | $template_variables = {
198 | config_name => $filename,
199 | include_dirs => $cf_directories,
200 | sections => $config_sections[$filename],
201 | }
202 | file { "${asterisk::confdir}/${filename}.conf":
203 | ensure => file,
204 | owner => 'asterisk',
205 | group => 'asterisk',
206 | mode => '0640',
207 | content => epp('asterisk/config_file.conf.epp', $template_variables),
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/manifests/dahdi.pp:
--------------------------------------------------------------------------------
1 | # @summary Requirements for the asterisk dahdi module to work
2 | #
3 | # DAHDI (Digium/Asterisk Hardware Device Interface) lets you connect your
4 | # Asterisk PBX to a card, Digium and some other models, that bridges calls with
5 | # the POTS.
6 | #
7 | # @see https://wiki.asterisk.org/wiki/display/DAHDI/DAHDI
8 | #
9 | # @see https://wiki.asterisk.org/wiki/display/AST/chan_dahdi+Channel+Variables
10 | #
11 | # @todo This class could be merged into config.pp and used conditionally to a
12 | # boolean parameter that enables/disables (off by default) dahdi.
13 | #
14 | # @todo The module would also need to template out chan_dahdi.conf -- changes
15 | # to that file need to trigger a full restart of asterisk, not just a reload.
16 | #
17 | class asterisk::dahdi {
18 | package { [
19 | 'asterisk-dahdi',
20 | 'dahdi',
21 | 'dahdi-dkms', # dahdi autokompile ubuntu
22 | 'dahdi-linux', # dahdi linux kernel module
23 | 'dahdi-source', # dahdi sources
24 | ]:
25 | ensure => installed,
26 | }
27 |
28 | # User['asterisk'] {
29 | # groups => 'dialout',
30 | # }
31 | }
32 |
--------------------------------------------------------------------------------
/manifests/dotd/file.pp:
--------------------------------------------------------------------------------
1 | # @summary Create a file inside a .d directory and set its permissions correctly.
2 | #
3 | # This defined type is not intended to be used directly.
4 | #
5 | # @api private
6 | #
7 | # @param dotd_dir
8 | # Path of the .d directory, relative to asterisk's configuration directory,
9 | # in which the file should be created.
10 | # @param ensure
11 | # Set to `absent` to remove the file
12 | # @param source
13 | # Puppet file source where the contents can be found.
14 | # @param content
15 | # Textual contents of the file. This option is mutually exclusive with
16 | # `$source`.
17 | # @param filename
18 | # Can be used to override the name of the file created. Otherwise, `$name` is
19 | # used as the file name.
20 | #
21 | define asterisk::dotd::file (
22 | String $dotd_dir,
23 | Stdlib::Ensure::File::File $ensure = file,
24 | Optional[String] $content = undef,
25 | Optional[Stdlib::Filesource] $source = undef,
26 | String $filename = $name,
27 | ) {
28 | assert_private()
29 |
30 | include asterisk::config
31 | include asterisk::service
32 |
33 | $nb_set = count([$content, $source])
34 | if $nb_set == 0 {
35 | fail('One of $content or $source need to be defined, none were set')
36 | }
37 | if $nb_set == 2 {
38 | fail('Please provide either a $source or a $content, but not both.')
39 | }
40 |
41 | file { "/etc/asterisk/${dotd_dir}/${filename}":
42 | ensure => $ensure,
43 | owner => 'root',
44 | group => 'asterisk',
45 | mode => '0640',
46 | require => Class['asterisk::config'],
47 | notify => Class['asterisk::service'],
48 | }
49 |
50 | if $content =~ String {
51 | File["/etc/asterisk/${dotd_dir}/${filename}"] {
52 | content => $content,
53 | }
54 | } else {
55 | File["/etc/asterisk/${dotd_dir}/${filename}"] {
56 | source => $source,
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/manifests/extensions.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure a dialplan context and extensions within that context
2 | #
3 | # This can be used to configure your different contexts with extensions, but it
4 | # can also be used to create macros that can be called in other contexts.
5 | #
6 | # @example basic context with one extension
7 | # asterisk::extensions { 'basic':
8 | # content => 'exten => 666,1,Hangup()',
9 | # }
10 | #
11 | # @see https://www.voip-info.org/asterisk-config-extensionsconf/
12 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/asterisk-DP-Basics.html
13 | #
14 | # @param ensure
15 | # Set this to false to remove the corresponding configuration file.
16 | # @param source
17 | # Puppet file source where the contents of the file can be found.
18 | # @param content
19 | # Textual contents of the file. This option is mutually exclusive with
20 | # `$source`.
21 | #
22 | define asterisk::extensions (
23 | Stdlib::Ensure::File::File $ensure = file,
24 | Optional[Stdlib::Filesource] $source = undef,
25 | # Only enforcing type for this param since we're using its value
26 | Optional[String] $content = undef,
27 | ) {
28 | if $content !~ Undef {
29 | $real_content = "[${name}]\n${content}"
30 | }
31 | else {
32 | $real_content = $content
33 | }
34 |
35 | asterisk::dotd::file { "extensions_${name}.conf":
36 | ensure => $ensure,
37 | dotd_dir => 'extensions.d',
38 | source => $source,
39 | content => $real_content,
40 | filename => "${name}.conf",
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/manifests/feature.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an asterisk feature application map grouping
2 | #
3 | # This resource will define an application map grouping. It can be used to set
4 | # dynamic features with the DYNAMIC_FEATURES variable: instead of listing all
5 | # of the application maps that need to be enabled in DYNAMIC_FEATURES, you can
6 | # use the name of a group to enable them all.
7 | #
8 | # To configure global features, see the `features_general` parameter to the
9 | # main class, `asterisk`.
10 | #
11 | # @example feature configuration
12 | # asterisk::feature { 'shifteight':
13 | # options => {
14 | # unpauseMonitor => '*1',
15 | # pauseMonitor => '*2',
16 | # }
17 | # }
18 | #
19 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/AdditionalConfig_id256654.html#AdditionalConfig_id256980
20 | # @see https://www.voip-info.org/asterisk-config-featuresconf/
21 | #
22 | # @todo list specific options as params instead of using an options hash
23 | #
24 | # @param options
25 | # Hash of options with keys being option names and values their values.
26 | # @param ensure
27 | # Set this to `absent` to remove the feature.
28 | #
29 | define asterisk::feature (
30 | Hash $options,
31 | Stdlib::Ensure::File::File $ensure = file,
32 | ) {
33 | $feature_variables = {
34 | context => $name,
35 | options => $options,
36 | }
37 | asterisk::dotd::file { "featuremap_group_${name}.conf":
38 | ensure => $ensure,
39 | dotd_dir => 'features.d',
40 | content => epp('asterisk/snippet/feature.epp', $feature_variables),
41 | filename => "${name}.conf",
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/manifests/iax.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an IAX2 context and its options
2 | #
3 | # A context named after `$name` will be created. You can configure iax2 users,
4 | # peers or the special context `callnumberlimits` that lets you override limits
5 | # to call numbers per IP address range.
6 | #
7 | # @see https://www.voip-info.org/asterisk-config-iaxconf/
8 | #
9 | # @todo list all options as parameters instead of using textual contents
10 | #
11 | # @param ensure
12 | # Set this to `absent` to remove the configuration file.
13 | # @param source
14 | # Puppet file source where the contents of the file can be found.
15 | # @param content
16 | # Textual contents of the file being created. This option is mutually
17 | # exclusive with `$source`. The content is placed after the name of the
18 | # context (which is `$name`) and so it should not include the context name
19 | # definition.
20 | #
21 | define asterisk::iax (
22 | Stdlib::Ensure::File::File $ensure = file,
23 | Optional[Stdlib::Filesource] $source = undef,
24 | # Only enforcing type for this param since we're using its value
25 | Optional[String] $content = undef
26 | ) {
27 | if $content !~ Undef {
28 | $real_content = "[${name}]\n${content}"
29 | }
30 | else {
31 | $real_content = $content
32 | }
33 |
34 | asterisk::dotd::file { "iax_${name}.conf":
35 | ensure => $ensure,
36 | dotd_dir => 'iax.d',
37 | source => $source,
38 | content => $real_content,
39 | filename => "${name}.conf",
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/manifests/init.pp:
--------------------------------------------------------------------------------
1 | # @summary Install and configure an asterisk server.
2 | #
3 | # @example simple install
4 | # class { 'asterisk': }
5 | #
6 | # @see https://wiki.asterisk.org/wiki/display/AST/Asterisk+Queues
7 | #
8 | # @todo make it possible to manage dialplan with the two other methods (e.g.
9 | # AEL and Lua)
10 | # @todo overhaul README file before release. lots of things have changed
11 | # @todo write spec tests for all the code
12 | # @todo manage pjsip.conf
13 | # @todo manage cdr*.conf
14 | # @todo manage musiconhold.conf
15 | #
16 | # @param manage_service
17 | # Set this to false to avoid managing the asterisk service. By default puppet
18 | # will enable the service and ensure that it is running.
19 | # @param manage_package
20 | # Set this to false to avoid installing the asterisk package.
21 | # @param package_name
22 | # Name or array of the package(s) being installed for asterisk.
23 | # @param service_name
24 | # Name of the asterisk service.
25 | # @param confdir
26 | # Absolute path to the asterisk configuration directory.
27 | # @param purge_confdir
28 | # Set this to true to enable autoremoval of configuration files that are
29 | # not managed by puppet inside of asterisk's `confdir`.
30 | #
31 | # @param iax_general
32 | # Global configurations for IAX2. Options are set in the file as `key =
33 | # value` in the `[general]` section of `iax.conf`.
34 | # @param iax_contexts
35 | # Hash of resource_name => params used to instantiate `asterisk::iax`
36 | # defined types.
37 | # @param iax_registries
38 | # Hash of resource_name => params used to instantiate
39 | # `asterisk::registry::iax` defined types.
40 | # @param sip_general
41 | # Global configurations for SIP. Options are set in the file as `key = value`
42 | # in the `[general]` section of the `sip.conf` file.
43 | # @param sip_peers
44 | # Hash of resource_name => params used to instantiate `asterisk::sip`
45 | # defined types.
46 | # @param sip_registries
47 | # Hash of resource_name => params used to instantiate
48 | # `asterisk::registry::sip` defined types.
49 | # @param voicemail_general
50 | # Global configurations for voicemail. Options are set in the file as `key =
51 | # value` in the `[general]` section of the `voicemail.conf` file.
52 | # @param voicemails
53 | # Hash of resource_name => params used to instantiate `asterisk::voicemail`
54 | # defined types.
55 | # @param extensions_general
56 | # Global configurations for the dialplan. Options are set in the file as `key
57 | # = value` in the `[general]` section of the `extensions.conf` file.
58 | # @param extensions_globals
59 | # Hash of global variables for the dialplan, placed in the `[globals]`
60 | # section of the `extensions.conf` file.
61 | #
62 | # WARNING: If you load any other extension configuration engine, such as
63 | # pbx_ael.so, your global variables may be overridden by that file. Please
64 | # take care to use only one location to set global variables, and you will
65 | # likely save yourself a ton of grief.
66 | #
67 | # The variables defined here can be accessed throughout the dialplan with the
68 | # `GLOBAL()` function. Global variables can make dialplans reusable by
69 | # different servers with different use cases.
70 | #
71 | # They also make dialplans easier to maintain by concentrating certain
72 | # information in one location (e.g. to avoid having to modify the same value
73 | # through many contexts and macros).
74 | #
75 | # Global variables can also be used for hiding passwords from Asterisk logs,
76 | # for example for `register` lines or calls to `Dial()` where information
77 | # about the provider is combined with username and password: when using a
78 | # global variable, the variable name will be shown in logs, not the actual
79 | # password.
80 | #
81 | # Variables are set in the file as `key=value`. If you pass in a Sensitive
82 | # type as the value, it will be unwrapped for outputting in the configuration
83 | # file: this can avoid showing certain sensitive information (as passwords)
84 | # in puppet logs.
85 | # @param extension_contexts
86 | # Hash of resource_name => params used to instantiate `asterisk::extension`
87 | # defined types.
88 | # @param agents_global
89 | # Global configurations for agents. Options are set in the file as `key =
90 | # value` in the `[agents]` section of the `agents.conf` file.
91 | # @param agents
92 | # Hash of resource_name => params used to instantiate `asterisk::agent`
93 | # defined types.
94 | # @param features_general
95 | # Global call features. Options are set in the file as `key = value` in the
96 | # `[general]` section of `features.conf`.
97 | # @param features_featuremap
98 | # Global feature maps. Options are set in the file as `key => value` in the
99 | # `[featuremap]` section of `features.conf`.
100 | # @param features_applicationmap
101 | # Global application feature maps. Options are set in the file as
102 | # `key => value` in the `[applicationmap]` section of `features.conf`.
103 | # @param features
104 | # Hash of resource_name => params used to instantiate `asterisk::feature`
105 | # defined types.
106 | # @param logger_general
107 | # Global configurations for asterisk logging. Options are set in the file as
108 | # `key=value` in the `[general]` section of `logger.conf`.
109 | # @param log_files
110 | # A hash defining log files.
111 | #
112 | # Top-level keys set log file names.
113 | #
114 | # Log files can use the special names `console` or `syslog` to determine
115 | # what output is sent to the asterisk CLI console and syslog, respectively.
116 | #
117 | # All other top-level keys represent a file name. File names can
118 | # be either relative to the `asterisk.conf` setting `astlogdir` or an
119 | # absolute path.
120 | #
121 | # Values associated to the top-level keys should be a hash that
122 | # contains at least one key, `levels`. The value for `levels` should be an
123 | # array listing logging levels for this log file.
124 | #
125 | # As well as `levels`, there can be an optional key, `formatter`. Its value
126 | # should be a string containing either `default` or `json` and it defines
127 | # which format will be output to the log. If the `formatter` key is
128 | # omitted, asterisk's default log format is used.
129 | # @param queues_general
130 | # Global configurations for queues. Options are set in the file as
131 | # `key => value` in the `[general]` section of the `queues.conf` file.
132 | # @param queues
133 | # Hash of resource_name => params used to instantiate `asterisk::queue`
134 | # defined types.
135 | # @param modules_autoload
136 | # Set this to false to avoid having asterisk load modules automatically on an
137 | # as-needed basis. This can be used to configure modules in a more
138 | # restrictive manner.
139 | # @param modules_preload
140 | # List of modules that asterisk should load before asterisk core has been
141 | # initialized. This can be useful if you wish to map all module configuration
142 | # files into Realtime storage.
143 | # @param modules_noload
144 | # List of modules that asterisk should not load. This can be useful if
145 | # `modules_autoload` is set to `true`.
146 | # @param modules_load
147 | # List of modules that asterisk should load on startup. This is useful if
148 | # you've set `modules_autoload` to `false`.
149 | # @param modules_global
150 | # Global configurations for modules. Options are set in the file as
151 | # `key => value` in the `[global]` section of the `modules.conf` file.
152 | # @param manager_enable
153 | # Set this to false to disable asterisk manager.
154 | # @param manager_port
155 | # Port number on which asterisk will listen to for manager connections.
156 | # Defaults to 5038.
157 | # @param manager_bindaddr
158 | # IP address to have asterisk bind to for manager connections. Defaults to
159 | # binding to localhost.
160 | # @param manager_accounts
161 | # Hash of resource_name => params used to instantiate `asterisk::manager`
162 | # defined types.
163 | #
164 | class asterisk (
165 | # Global management options
166 | Boolean $manage_service,
167 | Boolean $manage_package,
168 | Variant[String, Array[String]] $package_name,
169 | String $service_name,
170 | Stdlib::Absolutepath $confdir,
171 | Boolean $purge_confdir,
172 | # Asterisk modules and applications
173 | Hash $iax_general,
174 | Stdlib::CreateResources $iax_contexts,
175 | Stdlib::CreateResources $iax_registries,
176 | Hash $sip_general,
177 | Stdlib::CreateResources $sip_peers,
178 | Stdlib::CreateResources $sip_registries,
179 | Hash $voicemail_general,
180 | Stdlib::CreateResources $voicemails,
181 | Hash $extensions_general,
182 | Asterisk::ExtGlobalVars $extensions_globals,
183 | Stdlib::CreateResources $extension_contexts,
184 | Hash $agents_global,
185 | Stdlib::CreateResources $agents,
186 | Asterisk::FeaturesGeneral $features_general,
187 | Asterisk::Featuremap $features_featuremap,
188 | Hash[String,String] $features_applicationmap,
189 | Stdlib::CreateResources $features,
190 | Hash[String,String] $logger_general,
191 | Hash[String,Asterisk::Logfile] $log_files,
192 | Hash $queues_general,
193 | Stdlib::CreateResources $queues,
194 | Boolean $modules_autoload,
195 | Array[String] $modules_preload,
196 | Array[String] $modules_noload,
197 | Array[String] $modules_load,
198 | Hash $modules_global,
199 | Boolean $manager_enable,
200 | Integer $manager_port,
201 | String $manager_bindaddr,
202 | Stdlib::CreateResources $manager_accounts,
203 | ) {
204 | # We'll only ensure the type of some of the *_general on which templates
205 | # iterate. There's no complex data type that can let us be this flexible
206 | # (e.g. everything should be a string, but those handful of keys.
207 | assert_type(Array[String], $iax_general['allow'])
208 | assert_type(Array[String], $iax_general['disallow'])
209 |
210 | assert_type(Array[String], $sip_general['allow'])
211 | assert_type(Array[String], $sip_general['disallow'])
212 | assert_type(Array[String], $sip_general['domain'])
213 | assert_type(Array[String], $sip_general['localnet'])
214 |
215 | contain asterisk::install
216 | contain asterisk::config
217 | contain asterisk::service
218 |
219 | # create_resources:
220 | create_resources('asterisk::iax', $iax_contexts)
221 | create_resources('asterisk::registry::iax', $iax_registries)
222 | create_resources('asterisk::sip', $sip_peers)
223 | create_resources('asterisk::registry::sip', $sip_registries)
224 | create_resources('asterisk::voicemail', $voicemails)
225 | create_resources('asterisk::extension', $extension_contexts)
226 | create_resources('asterisk::agent', $agents)
227 | create_resources('asterisk::feature', $features)
228 | create_resources('asterisk::queue', $queues)
229 | create_resources('asterisk::manager', $manager_accounts)
230 |
231 | Class['asterisk::install']
232 | -> Class['asterisk::config']
233 | ~> Class['asterisk::service']
234 | }
235 |
--------------------------------------------------------------------------------
/manifests/install.pp:
--------------------------------------------------------------------------------
1 | # @summary Install packages that are necessary for an asterisk server.
2 | #
3 | # This class is not intended to be used directly.
4 | #
5 | # @api private
6 | #
7 | class asterisk::install {
8 | assert_private()
9 |
10 | if $asterisk::manage_package {
11 | package { $asterisk::package_name:
12 | ensure => installed,
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/manifests/language.pp:
--------------------------------------------------------------------------------
1 | # @summary Install an asterisk language pack.
2 | #
3 | # The name of the resource is the name of a language pack.
4 | #
5 | # The language packs defined here were taken directly from packages available
6 | # on debian and so this might not work for other distros.
7 | #
8 | # @example installing two language packs
9 | # asterisk::language { ['de', 'es']: }
10 | #
11 | define asterisk::language {
12 | $allowed_languages = [
13 | 'de',
14 | 'es-co',
15 | 'fr-armelle',
16 | 'fr-proformatique',
17 | 'it-menardi',
18 | 'it-menardi-alaw',
19 | 'it-menardi-gsm',
20 | 'it-menardi-wav',
21 | 'se',
22 | 'es',
23 | ]
24 | $allowed_core_languages = [
25 | 'core-sounds-en',
26 | 'core-sounds-en-g722',
27 | 'core-sounds-en-gsm',
28 | 'core-sounds-en-wav',
29 | 'core-sounds-es',
30 | 'core-sounds-es-g722',
31 | 'core-sounds-es-gsm',
32 | 'core-sounds-es-wav',
33 | 'core-sounds-fr',
34 | 'core-sounds-fr-g722',
35 | 'core-sounds-fr-gsm',
36 | 'core-sounds-fr-wav',
37 | 'core-sounds-ru',
38 | 'core-sounds-ru-g722',
39 | 'core-sounds-ru-gsm',
40 | 'core-sounds-ru-wav',
41 | ]
42 |
43 | if !($name in $allowed_languages) and !($name in $allowed_core_languages) {
44 | fail("Language '${name}' for Asterisk is unsupported.")
45 | }
46 |
47 | if ($name in $allowed_core_languages) {
48 | package { "asterisk-${name}": ensure => installed; }
49 | }
50 | else {
51 | package { "asterisk-prompt-${name}": ensure => installed; }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/manifests/manager.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an asterisk manager
2 | #
3 | # @example manager with default authorizations that can connect from LAN.
4 | # asterisk::manager { 'sophie':
5 | # secret => Sensitive.new('youllneverguesswhatitis'),
6 | # permit => ['192.168.120.0/255.255.255.0'],
7 | # }
8 | #
9 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/AMI-configuration.html#AMI_id265404
10 | # @see https://www.voip-info.org/asterisk-config-managerconf/
11 | #
12 | # @param secret
13 | # Authentication password for the manager.
14 | # @param ensure
15 | # Set to `absent` to remove the manager.
16 | # @param manager_name
17 | # Can be used to override the name of the manager. By default the
18 | # name of the manager corresponds to `$name`.
19 | # @param deny
20 | # List of IP specifications that are denied access to the manager. Denied
21 | # IPs can be overridden by `$permit`. This makes it possible to only permit
22 | # access to some IP addresses. Default value is to deny access to everybody.
23 | # @param permit
24 | # List of IP specifications that are permitted access to the manager.
25 | # Defaults to premitting only localhost.
26 | # @param read
27 | # List of authorizations given to the manager to read certain information or
28 | # configuration. Defaults to `system` and `call`.
29 | # @param write
30 | # List of authorizations given to the manager to write (change) certain
31 | # information or configuration. Defaults to `system` and `call`.
32 | # @param writetimeout
33 | # Timeout in milliseconds used by Asterisk when writing data to the AMI
34 | # connection for this user.
35 | # @param displayconnects
36 | # Set this to no to avoid reporting connections to the AMI as verbose
37 | # messages printed to the Asterisk console.
38 | # @param eventfilter
39 | # Whitelist- or blacklist-style filtering of manager events before they are
40 | # delivered to the AMI client application. Filters are specified using a
41 | # regular expression. A specified filter is a whitelist filter unless
42 | # preceded by an exclamation point.
43 | #
44 | define asterisk::manager (
45 | Sensitive[String[1]] $secret,
46 | Stdlib::Ensure::File::File $ensure = file,
47 | String[1] $manager_name = $name,
48 | Array[String[1]] $deny = ['0.0.0.0/0.0.0.0'],
49 | Array[String[1]] $permit = ['127.0.0.1/255.255.255.255'],
50 | Array[Asterisk::ManagerPerms] $read = ['system', 'call'],
51 | Array[Asterisk::ManagerPerms] $write = ['system', 'call'],
52 | Integer $writetimeout = 100,
53 | Boolean $displayconnects = true,
54 | Optional[String] $eventfilter = undef,
55 | ) {
56 | $wo_rights = ['config','command','originate']
57 | $wo_rights.each |String $right| {
58 | if $right in $read {
59 | fail("write-only right '${right}' given to the \$read parameter")
60 | }
61 | }
62 |
63 | $ro_rights = ['log','verbose','dtmf','cdr','dialplan','cc']
64 | $ro_rights.each |String $right| {
65 | if $right in $write {
66 | fail("read-only right '${right}' given to the \$write parameter")
67 | }
68 | }
69 |
70 | $manager_variables = {
71 | manager_name => $manager_name,
72 | secret => $secret,
73 | deny => $deny,
74 | permit => $permit,
75 | read => $read,
76 | write => $write,
77 | writetimeout => $writetimeout,
78 | displayconnects => bool2str($displayconnects, 'yes', 'no'),
79 | eventfilter => $eventfilter,
80 | }
81 | asterisk::dotd::file { "manager_${name}.conf":
82 | ensure => $ensure,
83 | dotd_dir => 'manager.d',
84 | content => epp('asterisk/snippet/manager.epp', $manager_variables),
85 | filename => "${name}.conf",
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/manifests/queue.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an asterisk queue
2 | #
3 | # This resource presents a multitude of options, corresponding to different
4 | # options that can be configured for queues.
5 | #
6 | # @see http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/ACD_id288901.html#options_defined_queues Definitions of options
7 | # @see http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/asterisk-ACD.html
8 | # @see http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/ACD_id288932.html#ACD_id36004485 Changing penalties dynamically
9 | #
10 | # @example create a queue with 10 max callers and strategy `random`
11 | # asterisk::queue { 'shortq':
12 | # stragegy => 'random',
13 | # maxlen => 10,
14 | # }
15 | #
16 | # @todo use better data types. some params should be boolean. some should have an enum.
17 | #
18 | # @param ensure
19 | # Set this to `absent` in order to remove a queue.
20 | #
21 | # @param strategy
22 | # Name of the queue strategy that determines which member phones are ringing
23 | # when there is a call in the queue that needs answering. If this parameter
24 | # is not defined, the strategy defaults to 'ringall'.
25 | # @param context
26 | # Name of a dialplan context. Allows a caller to exit the queue by pressing a
27 | # single DTMF digit. If a context is specified and the caller enters a
28 | # number, that digit will attempt to be matched in the context specified, and
29 | # dialplan execution will continue there.
30 | # @param defaultrule
31 | # Associates a queue rule as defined in queuerules.conf to this queue, which
32 | # is used to dynamically change the minimum and maximum penalties, which are
33 | # then used to select an available agent.
34 | # @param maxlen
35 | # Maximum number of allowed callers in the queue. A value of 0 allows an
36 | # unlimited number of callers in the queue. If unspecified, defaults to 0.
37 | # @param musicclass
38 | # Name of a music class as defined in `musiconhold.conf` to be used for this
39 | # particular queue. You can also override this value with the
40 | # CHANNEL(musicclass) channel variable.
41 | # @param servicelevel
42 | # Threshold in seconds for queue waiting time. This can be then used in
43 | # statistics to determine the number of calls that have passed the
44 | # `servicelevel` threshold.
45 | #
46 | # @param members
47 | # List of static members of this queue. Each member should be specified a
48 | # `Technology/Device_ID`.
49 | # @param memberdelay
50 | # Optional number of seconds to add as delay before the caller and member get
51 | # connected to each other.
52 | # @param penaltymemberslimit
53 | # Optional lower bound to start disregarding penalty if number of members in
54 | # the queue is lower than this number.
55 | # @param membermacro
56 | # Name of a macro to be executed just prior to bridging the caller and the
57 | # queue member.
58 | # @param membergosub
59 | # If set, run this gosub when connected to the queue member you can override
60 | # this gosub by setting the gosub option on the queue application
61 | # @param setinterfacevar
62 | # If set to `yes`, the channel variables `MEMBERINTERFACE`, `MEMBERNAME`,
63 | # `MEMBERCALLS`, `MEMBERLASTCALL`, `MEMBERPENALTY`, `MEMBERDYNAMIC` and
64 | # `MEMBERREALTIME` will be set just prior to connecting the caller with the
65 | # queue member.
66 | # @param setqueuevar
67 | # If set to `yes`, the channel variables `QUEUENAME`, `QUEUEMAX`,
68 | # `QUEUESTRATEGY`, `QUEUECALLS`, `QUEUEHOLDTIME`, `QUEUECOMPLETED`,
69 | # `QUEUEABANDONED`, `QUEUESRVLEVEL` and `QUEUESRVLEVELPERF` will be set just
70 | # prior to the call being bridged.
71 | # @param setqueueentryvar
72 | # If set to `yes`, the channel variables `QEHOLDTIME` and `QEORIGINALPOS`
73 | # will be set just prior to the call being bridged.
74 | # @param weight
75 | # The weight of a queue. A queue with a higher weight defined will get first
76 | # priority when members are associated with multiple queues.
77 | # @param reportholdtime
78 | # If set to `yes`, enables reporting of the caller’s hold time to the queue
79 | # member prior to bridging.
80 | # @param ringinuse
81 | # If set to `no`, avoid sending calls to members whose status is `In Use`.
82 | # Only the SIP channel driver is currently able to accurately report this
83 | # status.
84 | # @param wrapuptime
85 | # Number of seconds to keep a member unavailable in a queue after completing
86 | # a call.
87 | # @param timeout
88 | # Number of seconds to ring a member’s device. Also see `timeoutpriority`.
89 | # @param timeoutrestart
90 | # If set to `yes`, resets the timeout for an agent to answer if either a
91 | # `BUSY` or `CONGESTION` status is received from the channel. This can be
92 | # useful if the agent is allowed to reject or cancel a call.
93 | # @param timeoutpriority
94 | # Define which value of `timeout` takes precedence in case of a conflict. Set
95 | # to `conf` to have the value configured with `timeout` on this resource take
96 | # precedence. Defaults to `app`, which means the `timeout` value from the
97 | # `Queue()` application will take precedence.
98 | # @param retry
99 | # Number of seconds to wait before attempting the next member in the queue if
100 | # the `timeout` value is exhausted while attempting to ring a member of the
101 | # queue.
102 | # @param autopause
103 | # Set this to `yes` to enable the automatic pausing of members who fail to
104 | # answer a call. A value of `all` causes this member to be paused in all
105 | # queues they are a member of.
106 | #
107 | # @param joinempty
108 | # Controls whether a caller is added to the queue when no members are
109 | # available. Comma-separated options can be included to define how this
110 | # option determines whether members are available. See reference `Definitions
111 | # of options` to see what possible values this can take and what they mean.
112 | # @param leavewhenempty
113 | # control whether callers are kicked out of the queue when members are no
114 | # longer available to take calls. This can take values similar to
115 | # `joinempty`.
116 | # @param eventwhencalled
117 | # If set to `yes` manager events `AgentCalled`, `AgentDump`, `AgentConnect`
118 | # and `AgentComplete` will be sent to the Asterisk Manager Interface (AMI).
119 | # If set to vars, all channel variables associated with the agent will also
120 | # be sent to the AMI. Defaults to `no`.
121 | # @param eventmemberstatus
122 | # If set to `yes`, the QueueMemberStatus event will be sent to AMI. Note that
123 | # this may generate a lot of manager events.
124 | # @param monitor_type
125 | # If set to `MixMonitor`, the `MixMonitor()` application will be used for
126 | # recording calls within the queue. If not specified, the `Monitor()`
127 | # application will be used instead. This setting applies specifically for
128 | # this queue and overrides the general option with the same name.
129 | # @param monitor_format
130 | # File format to use when recording. If unspecified, calls will not be
131 | # recorded.
132 | # @param autofill
133 | # If set to `no`, the queue application will attempt to deliver calls to
134 | # agents in a serial manner. This means only one call is attempted to be
135 | # distributed to agents at a time. Additional callers are not distributed to
136 | # agents until that caller is connected to an agent. If set to `yes`, callers
137 | # are distributed to available agents simultaneously. This value overrides
138 | # the value from the general section for this particular queue.
139 | #
140 | # @param announce
141 | # Filename of an announcement played to the agent that answered the call,
142 | # typically to let them know what queue the caller is coming from. Useful
143 | # when the agent is in multiple queues, especially when set to auto-answer
144 | # the queue.
145 | # @param announce_frequency
146 | # Number of seconds to wait for before we should announce the caller’s
147 | # position and/or estimated hold time in the queue. Set this value to zero or
148 | # let the parameter unspecified to disable.
149 | # @param min_announce_frequency
150 | # Minimum amount of time, in seconds, that must pass before we announce the
151 | # caller’s position in the queue again. This is used when the caller’s
152 | # position may change frequently, to prevent the caller hearing multiple
153 | # updates in a short period of time.
154 | # @param announce_holdtime
155 | # Set to `yes` to play the estimated hold time along with the periodic
156 | # announcements. If set to `once`, the estimated hold time will be played
157 | # only once. Defaults to `no`.
158 | # @param announce_position
159 | # Set to `yes` to have periodic announcements always mention current position
160 | # in the queue. If set to `limit` announcements will only mention the
161 | # position in the queue if it is within the limit defined by
162 | # `announce_position_limit`. If set to `more`, announcements will only
163 | # mention the position in the queue if it is beyond the number in
164 | # `announce_position_limit`. Defaults to `no`.
165 | # @param announce_position_limit
166 | # Position in the queue that represents a threshold for announcements if
167 | # `announce_position` was set to `limit` or `more`.
168 | # @param announce_round_seconds
169 | # If set to a non-zero value, announcements will mention seconds as well,
170 | # rounded to the value specified in this parameter.
171 | # @param periodic_announce
172 | # List of file names of periodic announcements to be played. Prompts are
173 | # played in the order they are defined. If unset, defaults to
174 | # `queue-periodic-announce`.
175 | # @param periodic_announce_frequency
176 | # Time in seconds between periodic announcements to the caller.
177 | # @param random_periodic_announce
178 | # If set to `yes`, will play the defined periodic announcements in a random
179 | # order.
180 | # @param relative_periodic_announce
181 | # If set to `yes`, the periodic_announce_frequency timer will start from when
182 | # the end of the file being played back is reached, instead of from the
183 | # beginning. Defaults to `no`.
184 | # @param queue_youarenext
185 | # Filename of a prompt to play when caller reaches first position in queue.
186 | # If not defined, will play the default value (“You are now first in line”).
187 | # If set to an empty value, the prompt will not be played at all.
188 | # @param queue_thereare
189 | # Filename of a prompt to play in announcements when mentioning how much
190 | # people are before the caller. If not defined, will play the default value
191 | # (“There are”). If set to an empty value, the prompt will not be played at
192 | # all.
193 | # @param queue_callswaiting
194 | # Filename of a prompt to play in announcements after saying number of calls
195 | # before caller. If not defined, will play the default value (“calls
196 | # waiting”). If set to an empty value, the prompt will not be played at all.
197 | # @param queue_holdtime
198 | # Filename of a prompt to play when starting to announce estimated wait time.
199 | # If not defined, will play the default value (“The current estimated hold
200 | # time is”). If set to an empty value, the prompt will not be played at all.
201 | # @param queue_minute
202 | # Filename of a prompt to play after stating number of estimated minutes, if
203 | # the number is 1. If not defined, will play the default value (“minute”). If
204 | # set to an empty value, the prompt will not be played at all.
205 | # @param queue_minutes
206 | # Filename of a prompt. This is the same as `queue_minute` but for when the
207 | # number of minutes is more than 1.
208 | # @param queue_seconds
209 | # Filename of a prompt to play after stating number of estimated seconds. If
210 | # not defined, will play the default value (“seconds”). If set to an empty
211 | # value, the prompt will not be played at all.
212 | # @param queue_thankyou
213 | # Filename of a prompt. If not defined, will play the default value (“Thank
214 | # you for your patience”). If set to an empty value, the prompt will not be
215 | # played at all.
216 | # @param queue_reporthold
217 | # Filename of a prompt. If not defined, will play the default value (“Hold
218 | # time”). If set to an empty value, the prompt will not be played at all.
219 | #
220 | define asterisk::queue (
221 | Stdlib::Ensure::File::File $ensure = file,
222 | Optional[String[1]] $strategy = undef,
223 | Array[String[1]] $members = [],
224 | Optional[Integer] $memberdelay = undef,
225 | Optional[String[1]] $penaltymemberslimit = undef,
226 | Optional[String[1]] $membermacro = undef,
227 | Optional[String[1]] $membergosub = undef,
228 | Optional[String[1]] $context = undef,
229 | Optional[String[1]] $defaultrule = undef,
230 | Optional[Integer] $maxlen = undef,
231 | Optional[String[1]] $musicclass = undef,
232 | Optional[String[1]] $servicelevel = undef,
233 | Optional[Integer] $weight = undef,
234 | Array[String[1]] $joinempty = [],
235 | Array[String[1]] $leavewhenempty = [],
236 | Optional[String[1]] $eventwhencalled = undef,
237 | Optional[String[1]] $eventmemberstatus = undef,
238 | Optional[String[1]] $reportholdtime = undef,
239 | Optional[String[1]] $ringinuse = undef,
240 | Optional[String[1]] $monitor_type = undef,
241 | Array[String[1]] $monitor_format = [],
242 | Optional[String[1]] $announce = undef,
243 | Optional[Integer] $announce_frequency = undef,
244 | Optional[Integer] $min_announce_frequency = undef,
245 | Optional[String[1]] $announce_holdtime = undef,
246 | Optional[String[1]] $announce_position = undef,
247 | Optional[Integer] $announce_position_limit = undef,
248 | Optional[Integer] $announce_round_seconds = undef,
249 | Array[String[1]] $periodic_announce = [],
250 | Optional[Integer] $periodic_announce_frequency = undef,
251 | Optional[String[1]] $random_periodic_announce = undef,
252 | Optional[String[1]] $relative_periodic_announce = undef,
253 | Optional[String] $queue_youarenext = undef,
254 | Optional[String] $queue_thereare = undef,
255 | Optional[String] $queue_callswaiting = undef,
256 | Optional[String] $queue_holdtime = undef,
257 | Optional[String] $queue_minute = undef,
258 | Optional[String] $queue_minutes = undef,
259 | Optional[String] $queue_seconds = undef,
260 | Optional[String] $queue_thankyou = undef,
261 | Optional[String] $queue_reporthold = undef,
262 | Optional[Integer] $wrapuptime = undef,
263 | Optional[Integer] $timeout = undef,
264 | Optional[String[1]] $timeoutrestart = undef,
265 | Optional[String[1]] $timeoutpriority = undef,
266 | Optional[String[1]] $retry = undef,
267 | Optional[String[1]] $autofill = undef,
268 | Optional[String[1]] $autopause = undef,
269 | Optional[String[1]] $setinterfacevar = undef,
270 | Optional[String[1]] $setqueuevar = undef,
271 | Optional[String[1]] $setqueueentryvar = undef
272 | ) {
273 | $queue_variables = {
274 | queue_name => $name,
275 | strategy => $strategy,
276 | members => $members,
277 | memberdelay => $memberdelay,
278 | penaltymemberslimit => $penaltymemberslimit,
279 | membermacro => $membermacro,
280 | membergosub => $membergosub,
281 | context => $context,
282 | defaultrule => $defaultrule,
283 | maxlen => $maxlen,
284 | musicclass => $musicclass,
285 | servicelevel => $servicelevel,
286 | weight => $weight,
287 | joinempty => $joinempty,
288 | leavewhenempty => $leavewhenempty,
289 | eventwhencalled => $eventwhencalled,
290 | eventmemberstatus => $eventmemberstatus,
291 | reportholdtime => $reportholdtime,
292 | ringinuse => $ringinuse,
293 | monitor_type => $monitor_type,
294 | monitor_format => $monitor_format,
295 | announce => $announce,
296 | announce_frequency => $announce_frequency,
297 | min_announce_frequency => $min_announce_frequency,
298 | announce_holdtime => $announce_holdtime,
299 | announce_position => $announce_position,
300 | announce_position_limit => $announce_position_limit,
301 | announce_round_seconds => $announce_round_seconds,
302 | periodic_announce => $periodic_announce,
303 | periodic_announce_frequency => $periodic_announce_frequency,
304 | random_periodic_announce => $random_periodic_announce,
305 | relative_periodic_announce => $relative_periodic_announce,
306 | queue_youarenext => $queue_youarenext,
307 | queue_thereare => $queue_thereare,
308 | queue_callswaiting => $queue_callswaiting,
309 | queue_holdtime => $queue_holdtime,
310 | queue_minute => $queue_minute,
311 | queue_minutes => $queue_minutes,
312 | queue_seconds => $queue_seconds,
313 | queue_thankyou => $queue_thankyou,
314 | queue_reporthold => $queue_reporthold,
315 | wrapuptime => $wrapuptime,
316 | timeout => $timeout,
317 | timeoutrestart => $timeoutrestart,
318 | timeoutpriority => $timeoutpriority,
319 | retry => $retry,
320 | autofill => $autofill,
321 | autopause => $autopause,
322 | setinterfacevar => $setinterfacevar,
323 | setqueuevar => $setqueuevar,
324 | setqueueentryvar => $setqueueentryvar,
325 | }
326 | asterisk::dotd::file { "queue_${name}.conf":
327 | ensure => $ensure,
328 | dotd_dir => 'queues.d',
329 | content => epp('asterisk/snippet/queue.epp', $queue_variables),
330 | filename => "${name}.conf",
331 | }
332 | }
333 |
--------------------------------------------------------------------------------
/manifests/registry/iax.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure an IAX2 registry
2 | #
3 | # This makes it possible to register to an IAX2 peer for authenticated
4 | # connections.
5 | #
6 | # @param server
7 | # Hostname or IP address of the server to which Asterisk should register.
8 | # @param user
9 | # User name used for authenticating with the distant server.
10 | # @param password
11 | # Password used for authenticating.
12 | # @param ensure
13 | # Set to `absent` in order to remove the registry.
14 | #
15 | define asterisk::registry::iax (
16 | Stdlib::Host $server,
17 | String[1] $user,
18 | Sensitive[String[1]] $password,
19 | Stdlib::Ensure::File::File $ensure = file,
20 | ) {
21 | $iax_variables = {
22 | user => $user,
23 | password => $password,
24 | server => $server,
25 | }
26 | asterisk::dotd::file { "registry__iax_${name}.conf":
27 | ensure => $ensure,
28 | dotd_dir => 'iax.registry.d',
29 | content => epp('asterisk/registry/iax.epp', $iax_variables),
30 | filename => "${name}.conf",
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/manifests/registry/sip.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure a SIP registry
2 | #
3 | # This makes it possible to register to a SIP peer for authenticated
4 | # connections.
5 | #
6 | # @param server
7 | # Hostname or IP address of the server to which Asterisk should register.
8 | # @param user
9 | # User id for the local server.
10 | # @param ensure
11 | # Set to `absent` in order to remove the registry.
12 | # @param password
13 | # Optional password used for authenticating. This is required if our peer
14 | # does not match connections only on IP/port.
15 | # @param authuser
16 | # Optional user name used for authenticating with the remote server. This is
17 | # required if our peer does not match connections only on IP/port.
18 | # @param port
19 | # Numerical port with which a connection will be established to the remote
20 | # server.
21 | # @param extension
22 | # Extension that is used when calls are received from the remote server. When
23 | # not set, extension will be 's'.
24 | #
25 | define asterisk::registry::sip (
26 | Stdlib::Host $server,
27 | String[1] $user,
28 | Stdlib::Ensure::File::File $ensure = file,
29 | Optional[Sensitive[String[1]]] $password = undef,
30 | Optional[String[1]] $authuser = undef,
31 | Optional[Integer] $port = undef,
32 | Optional[String[1]] $extension = undef
33 | ) {
34 | if $password =~ Undef and $authuser !~ Undef {
35 | fail('authuser was specified but no value was given for password. You need both to authenticate.')
36 | }
37 |
38 | $sip_variables = {
39 | user => $user,
40 | password => $password,
41 | authuser => $authuser,
42 | server => $server,
43 | port => $port,
44 | extension => $extension,
45 | }
46 | asterisk::dotd::file { "registry__sip_${name}.conf":
47 | ensure => $ensure,
48 | dotd_dir => 'sip.registry.d',
49 | content => epp('asterisk/registry/sip.epp', $sip_variables),
50 | filename => "${name}.conf",
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/manifests/service.pp:
--------------------------------------------------------------------------------
1 | # @summary Ensure the Asterisk service is running.
2 | #
3 | # This class is not intended to be used directly.
4 | #
5 | # @api private
6 | #
7 | class asterisk::service {
8 | assert_private()
9 |
10 | if $asterisk::manage_service {
11 | service { $asterisk::service_name:
12 | ensure => running,
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/manifests/sip.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure a SIP peer, a user or a template for the previous.
2 | #
3 | # @note It is generally recommended to avoid assigning hostname to a `sip.conf`
4 | # section like `[provider.com]`.
5 | # @note It is generally recommended to use separate inbound and outbound
6 | # sections for SIP providers (instead of type=friend) if you have calls in
7 | # both directions
8 | #
9 | # @example create sip peer of providerZ
10 | # asterisk::sip { 'providerZ':
11 | # account_type => 'peer',
12 | # disallow => ['all'],
13 | # allow => ['ulaw'],
14 | # host => 'sip-host.local',
15 | # secret => Sensitive.new('callthisasecret'),
16 | # }
17 | #
18 | # @see https://www.voip-info.org/asterisk-config-sipconf/
19 | #
20 | # @todo use better data types. some should be boolean, some should have an enum
21 | #
22 | # @param ensure
23 | # Set this to `absent` in order to remove SIP configuration.
24 | # @param template_name
25 | # Set this to `!` if you are creating a template. Set this to any name of a
26 | # template section to inherit options from it.
27 | #
28 | # @param account_type
29 | # Define how calls are handled. Roughly, `peer` handles outbound and inbound
30 | # calls matches calls by ip/port. `user` handles only inbound calls and
31 | # matches calls by `authname` and `secret`. `friend` handles both inbound and
32 | # outbound calls where inbound calls are matched by `authname` and `secret`
33 | # (like a `user`) but outbound calls are matched by ip and port like a
34 | # `peer`.
35 | # @param username
36 | # Deprecated option in asterisk. You probably want to use `defaultuser`
37 | # instead.
38 | # @param defaultuser
39 | # Authentication user name.
40 | # @param secret
41 | # Authentication secret for inbound connections.
42 | # @param md5secret
43 | # MD5-Hash of `:==SIP_realm==:` (can be used instead of
44 | # `secret`). Default for authenticating to an Asterisk server when SIP realm
45 | # is not explicitly declared is `:asterisk:`.
46 | # @param remotesecret
47 | # Authentication secret for outbound connections. If this is not set,
48 | # `$secret` is used for outbound connections.
49 | # @param context
50 | # Name of the dialplan context that is used as starting point when an inbound
51 | # call is received through this peer/user.
52 | # @param canreinvite
53 | # Deprecated option in asterisk: was renamed to `directmedia`. Whether or not
54 | # to issue a reinvite to the client unless really necessary. This is used to
55 | # interoperate with some (buggy) hardware that crashes if we reinvite, such
56 | # as the common Cisco ATA 186. Setting this to `nonat` will allow reinvite
57 | # when local, deny reinvite when NAT. Finally setting this to `update` will
58 | # use `UPDATE` instead of `INVITE`.
59 | # @param directmedia
60 | # By default, Asterisk tries to re-invite media streams to an optimal path.
61 | # If there's no reason for Asterisk to stay in the media path, the media will
62 | # be redirected. This does not really work well in the case where Asterisk is
63 | # outside and the clients are on the inside of a NAT. In that case, you want
64 | # to set this parameter to `nonat`. `nonat` will allow media path redirection
65 | # (reinvite) but only when the peer where the media is being sent is known to
66 | # not be behind a NAT (as the RTP core can determine it based on the apparent
67 | # IP address the media arrives from). If you set this parameter to `update`,
68 | # Asterisk will use an `UPDATE` command instead of an `INVITE` command to
69 | # redirect media. `update` can also be combined with `nonat` with the value
70 | # `nonat,update`.
71 | # @param directrtpsetup
72 | # Set this to `true` to enable the new experimental direct RTP setup. This
73 | # sets up the call directly with media peer-2-peer without re-invites. Will
74 | # not work for video and cases where the callee sends RTP payloads and fmtp
75 | # headers in the 200 OK that does not match the callers INVITE. This will
76 | # also fail if directmedia is enabled when the device is actually behind NAT.
77 | # @param directmediadeny
78 | # List of CIDR prefixes (e.g. of the form `prefix/number of bits for mask` --
79 | # for example `172.16.0.0/16`) that should be denied passing directmedia to
80 | # other peers. You can use this if some of your phones are on IP addresses
81 | # that can not reach each other directly. This way you can force RTP to
82 | # always flow through asterisk in such cases. See also `directmediapermit`.
83 | # @param directmediapermit
84 | # List of CIDR prefixes that should be allowed passing directmedia to other
85 | # peers. See `directmediadeny`.
86 | # @param host
87 | # Set this to `dynamic` to require the device to register itself before
88 | # authenticating. Set to a hostname or IP address to match only for this host
89 | # or IP address.
90 | # @param insecure
91 | # If set to `port`, allow matching of peer by IP address without matching
92 | # port number. If set to `invite`, do not require authentication of incoming
93 | # INVITEs. If set to `no`, all connections will be authenticated regardless
94 | # of port or IP address. Defaults to `no`.
95 | # @param language
96 | # Language code to define prompts for this peer/user.
97 | # @param nat
98 | # Use methods to bypass issues when a phone is behind a NAT. This setting is
99 | # not useful for when the asterisk server is the one behind the NAT. Set this
100 | # to `yes` to ignore the address information in the SIP and SDP headers. Set
101 | # this to `force_rport` fore RFC 3581 behavior and disable symmetric RTP
102 | # support. Set this to `comedia` to enable RFC 3581 behavior if the remote
103 | # side requests it and enables symmetric RTP support.
104 | # @param qualify
105 | # If set to `yes`, the check if client is reachable every `qualifyfreq`
106 | # seconds (defaults to 60 seconds). If set to an integer number, corresponds
107 | # to `yes` and defines the timeout in milliseconds after a check packet is
108 | # sent: when the timeout is reached, a peer is considered offline. Valid only
109 | # with `type` set to `peer`.
110 | # @param vmexten
111 | # Name of dialplan extension to reach mailbox. When unspecified, defaults to
112 | # `asterisk`. Valid only with `type` set to `peer`.
113 | # @param callerid
114 | # Caller ID information used when nothing else is available. When
115 | # unspecified, defaults to `asterisk`.
116 | # @param call_limit
117 | # Number of simultaneous calls through this user/peer.
118 | # @param callgroup
119 | # Call groups for calls to this device.
120 | # @param mailbox
121 | # Voicemail extension (for message waiting indications). Not valid for `type`
122 | # set to `user`.
123 | # @param pickupgroup
124 | # Group that can pickup fellow workers’ calls using `*8` and the `Pickup()`
125 | # application on the `*8` extension.
126 | # @param fromdomain
127 | # Default `From:` domain in SIP messages when acting as a SIP UAC (client).
128 | # @param fromuser
129 | # User to put in `from` instead of `$CALLERID(number)` (overrides the
130 | # callerid) when placing calls _to_ a peer (another SIP proxy). Valid only
131 | # with `type` set to `peer`.
132 | # @param outboundproxy
133 | # SRV name (excluding the _sip._udp prefix), hostname, or IP address of the
134 | # outbound SIP Proxy. Valid only with `type` set to `peer`.
135 | # @param t38pt_udptl
136 | # Enable T.83 Fax support. Set to `yes` to enable T.38 with FEC error
137 | # correction. Additionally, you can add comma-separated options: `redundancy`
138 | # enables redundancy error correction. `none` disables error correction.
139 | # `maxdatagram=NN` overrides the maximum datagram value to NN bytes (useful
140 | # for some problematic cases like Cisco media gateways).
141 | # @param disallow
142 | # List of codecs to disallow for this peer/user. The list can contain `all` to
143 | # disallow all known codecs. If set to `all`, codecs that are present in the
144 | # `allow` list will override this setting, so this can be used to restrict to
145 | # a narrow number of codecs.
146 | # @param allow
147 | # List of codecs to allow for this peer/user. The list can contain `all` to
148 | # allow all known codecs. If set to `all`, codecs in `disallow` will override
149 | # this setting, so this can be used to blacklist only a narrow set of codecs.
150 | # @param dtmfmode
151 | # How the client handles DTMF signalling. Defaults to `rfc2833`. Warning:
152 | # `inband` leads to very high CPU load.
153 | # @param transports
154 | # Accepted transport types for this peer/user. Can be `udp`, `tcp` or both
155 | # with the order defining which is set as default (first value is default).
156 | # @param encryption
157 | # Set to `yes` to offer SRTP encrypted media (and only SRTP encrypted media)
158 | # on outgoing calls to a peer. Calls will fail with `HANGUPCAUSE=58` if the
159 | # peer does not support SRTP. Defaults to `no`.
160 | # @param access
161 | # List of permit/deny rules for CIDR prefixes like `prefix/mask`. Each
162 | # element of the list should be a one element hash that specifies either
163 | # 'permit' or 'deny' as a key and the CIDR prefix as its value. Order
164 | # Matters! – Rules are placed in the configuration file in the same order as
165 | # elements were inserted into the list. The last matching deny/permit rule is
166 | # the one used. If no rule matches, then the connection is permitted.
167 | # @param trustrpid
168 | # If a Remote-Party-ID SIP header should be sent. Defaults to `no`.
169 | # @param sendrpid
170 | # If Remote-Party-ID SIP header should be trusted. Defaults to `no`.
171 | #
172 | define asterisk::sip (
173 | Stdlib::Ensure::File::File $ensure = file,
174 | # lint:ignore:optional_default
175 | Optional[String[1]] $template_name = undef,
176 | Optional[String[1]] $account_type = 'friend',
177 | Optional[String[1]] $username = undef,
178 | Optional[String[1]] $defaultuser = undef,
179 | Optional[Sensitive[String[1]]] $secret = undef,
180 | Optional[String[1]] $md5secret = undef,
181 | Optional[Sensitive[String[1]]] $remotesecret = undef,
182 | Optional[String[1]] $context = undef,
183 | Optional[String[1]] $canreinvite = undef,
184 | Optional[String[1]] $directmedia = 'no',
185 | Optional[Boolean] $directrtpsetup = true,
186 | Array[String[1]] $directmediadeny = [],
187 | Array[String[1]] $directmediapermit = [],
188 | Optional[String[1]] $host = 'dynamic',
189 | Optional[String[1]] $insecure = 'no',
190 | Optional[String[1]] $language = 'en',
191 | Optional[String[1]] $nat = undef,
192 | Optional[String[1]] $qualify = 'no',
193 | Optional[String[1]] $vmexten = undef,
194 | Optional[String[1]] $callerid = undef,
195 | Optional[Integer] $call_limit = undef,
196 | Optional[String[1]] $callgroup = undef,
197 | Optional[String[1]] $mailbox = undef,
198 | Optional[String[1]] $pickupgroup = undef,
199 | Optional[String[1]] $fromdomain = undef,
200 | Optional[String[1]] $fromuser = undef,
201 | Optional[String[1]] $outboundproxy = undef,
202 | Optional[String[1]] $t38pt_udptl = undef,
203 | Array[String[1]] $disallow = [],
204 | Array[String[1]] $allow = [],
205 | Optional[String[1]] $dtmfmode = undef,
206 | Array[String[1]] $transports = [],
207 | Optional[String] $encryption = undef,
208 | Array[Asterisk::Access] $access = [],
209 | Optional[Enum['yes', 'no']] $trustrpid = undef,
210 | Optional[Enum['yes', 'no', 'pai', 'rpid']] $sendrpid = undef
211 | # lint:endignore
212 | ) {
213 | if $canreinvite !~ Undef {
214 | deprecation(@(DEPRECATED_OPTION)
215 | The option "canreinvite" was deprecated by asterisk and replaced with
216 | directmedia. You should check asterisk documentation and use the new
217 | option instead.
218 | | DEPRECATED_OPTION
219 | )
220 | }
221 |
222 | if $directrtpsetup =~ Boolean {
223 | $real_directrtpsetup = bool2str($directrtpsetup, 'yes', 'no')
224 | }
225 | else {
226 | $real_directrtpsetup = $directrtpsetup
227 | }
228 |
229 | $sip_variables = {
230 | peer_name => $name,
231 | template_name => $template_name,
232 | account_type => $account_type,
233 | username => $username,
234 | defaultuser => $defaultuser,
235 | secret => $secret,
236 | md5secret => $md5secret,
237 | remotesecret => $remotesecret,
238 | context => $context,
239 | canreinvite => $canreinvite,
240 | directmedia => $directmedia,
241 | directrtpsetup => $directrtpsetup,
242 | directmediadeny => $directmediadeny,
243 | directmediapermit => $directmediapermit,
244 | host => $host,
245 | insecure => $insecure,
246 | language => $language,
247 | nat => $nat,
248 | qualify => $qualify,
249 | vmexten => $vmexten,
250 | callerid => $callerid,
251 | call_limit => $call_limit,
252 | callgroup => $callgroup,
253 | mailbox => $mailbox,
254 | pickupgroup => $pickupgroup,
255 | fromdomain => $fromdomain,
256 | fromuser => $fromuser,
257 | outboundproxy => $outboundproxy,
258 | t38pt_udptl => $t38pt_udptl,
259 | disallow => $disallow,
260 | allow => $allow,
261 | dtmfmode => $dtmfmode,
262 | transports => $transports,
263 | encryption => $encryption,
264 | access => $access,
265 | trustrpid => $trustrpid,
266 | sendrpid => $sendrpid,
267 | }
268 | asterisk::dotd::file { "sip_${name}.conf":
269 | ensure => $ensure,
270 | dotd_dir => 'sip.d',
271 | content => epp('asterisk/snippet/sip.epp', $sip_variables),
272 | filename => "${name}.conf",
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/manifests/voicemail.pp:
--------------------------------------------------------------------------------
1 | # @summary Configure a voicemail
2 | #
3 | # @example voicemail with email address
4 | # asterisk::voicemail { 'taro':
5 | # context => 'support2',
6 | # password => Sensitive.new('557722981749'),
7 | # email => 'taro.suupaa@support.com',
8 | # }
9 | #
10 | # @param context
11 | # Name of the context in which the voicemail is assigned.
12 | # @param password
13 | # Authentication password set for accessing the voicemail. This is usually a
14 | # series of numbers so that phones can dial the password, but it can be a
15 | # textual password as well.
16 | # @param ensure
17 | # Set to `absent` to remove the voicemail.
18 | # @param user_name
19 | # Name assigned to the voicemail, usually the name of the person using it.
20 | # @param email
21 | # Email address to which voicemail message sounds will be sent.
22 | # @param pager_email
23 | # Email address to which a page will be sent upon receiving a voicemail.
24 | # @param options
25 | # Hash containing options that are set for the voicemail. For
26 | # example, a specific timezone can be set on individual voicemails with the
27 | # 'tz' option. Options are set in the file as `key = value`.
28 | #
29 | define asterisk::voicemail (
30 | String[1] $context,
31 | Sensitive[String[1]] $password,
32 | Stdlib::Ensure::File::File $ensure = file,
33 | Optional[String[1]] $user_name = undef,
34 | Optional[String[1]] $email = undef,
35 | Optional[String[1]] $pager_email = undef,
36 | Hash[String,String] $options = {}
37 | ) {
38 | $voicemail_variables = {
39 | context => $context,
40 | voicemail => $name,
41 | password => $password,
42 | user_name => $user_name,
43 | email => $email,
44 | pager_email => $pager_email,
45 | options => $options,
46 | }
47 | asterisk::dotd::file { "${context}-${name}.conf":
48 | ensure => $ensure,
49 | content => epp('asterisk/snippet/voicemail.epp', $voicemail_variables),
50 | dotd_dir => 'voicemail.d',
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "LeLutin-asterisk",
3 | "version": "2.0.3",
4 | "author": "LeLutin",
5 | "summary": "Install and configure the Asterisk PBX service",
6 | "license": "GPL-3.0+",
7 | "source": "https://github.com/lelutin/puppet-asterisk",
8 | "project_page": "https://github.com/lelutin/puppet-asterisk",
9 | "issues_url": "https://github.com/lelutin/puppet-asterisk/issues",
10 | "dependencies": [
11 | {"name":"puppetlabs/stdlib","version_requirement":">= 8.5.0"}
12 | ],
13 | "requirements": [
14 | {
15 | "name": "puppet",
16 | "version_requirement": ">= 6.0.0 < 9.0.0"
17 | }
18 | ],
19 | "operatingsystem_support": [
20 | {
21 | "operatingsystem": "Debian",
22 | "operatingsystemrelease":[ "10", "11" ]
23 | }
24 | ],
25 | "tags": ["asterisk", "sip", "iax", "PBX", "VoIP"]
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base",
5 | ":disableDependencyDashboard"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/spec/classes/init_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | describe 'asterisk' do
3 | let(:title) { 'asterisk' }
4 | let(:facts) do
5 | {
6 | os: {
7 | family: 'Debian',
8 | },
9 | }
10 | end
11 |
12 | context 'with defaults for all parameters' do
13 | it { is_expected.to contain_class('asterisk') }
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'puppetlabs_spec_helper/module_spec_helper'
2 | require 'rspec-puppet-facts'
3 |
--------------------------------------------------------------------------------
/templates/config_file.conf.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | ;
4 | ; To change values found in this file, see the parameters related to
5 | ; <%= $config_name %> on the asterisk module's main class.
6 | ;
7 | ; To see all comments that document each available option, on Debian
8 | ; systems, refer to /usr/share/doc/asterisk-config/samples
9 | ;
10 | <%
11 | $sections.each |String $sect_name, Hash $section_options| {
12 | -%>
13 | [<%= $sect_name %>]
14 | <%
15 | # Weird case where options in the same section use two different assignment
16 | # delimiters. The weird case comes in first in the config file.
17 | if $section_options['oddball_options'] !~ Undef {
18 | $odb_delimiter = $section_options['oddball_delimiter']
19 | $section_options['oddball_options'].each |String $odb_opt_name, String $odb_value| {
20 | -%>
21 | <%= $odb_opt_name %><%= $odb_delimiter %><%= $odb_value %>
22 | <%
23 | }
24 | # Add a blank line to the config file to better see the difference in the
25 | # two forms of assignments.
26 | -%>
27 |
28 | <%
29 | }
30 | $delimiter = $section_options['delimiter']
31 | $section_options['options'].each |String $opt_name, Any $value| {
32 | if $value =~ Array {
33 | $value.each |String $v| {
34 | -%>
35 | <%= $opt_name -%><%= $delimiter %><%= $v %>
36 | <%
37 | }
38 | }
39 | else {
40 | -%>
41 | <%= $opt_name -%><%= $delimiter %><%= $value %>
42 | <%
43 | }
44 | }
45 | -%>
46 |
47 | <%
48 | }
49 | -%>
50 | <%
51 | $include_dirs.each |String $dir_path| {
52 | -%>
53 | #include "<%= $dir_path %>/*.conf"
54 | <%
55 | }
56 | -%>
57 |
--------------------------------------------------------------------------------
/templates/registry/iax.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | register => <%= $user %>:<%= $password.unwrap %>@<%= $server %>
4 |
--------------------------------------------------------------------------------
/templates/registry/sip.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | register => <%= $user %><% if $password { -%>:<%= $password.unwrap %><% if $authuser { -%>:<%= $authuser %><% } } -%>@<%= $server %><% if $port { -%>:<%= $port %><% } if $extension { -%>/<%= $extension %><% } -%>
4 |
5 |
--------------------------------------------------------------------------------
/templates/snippet/agent.epp:
--------------------------------------------------------------------------------
1 | <% if ! empty($groups) { -%>
2 | group=<%= $groups.join(",") %>
3 | <% } -%>
4 | agent => <%= $ext %>,<%= $password.unwrap %>,<%= $agent_name %>
5 | <% if ! empty($groups) { -%>
6 | ; Reset group to avoid having an impact on other config files.
7 | group=
8 | <% } -%>
9 |
--------------------------------------------------------------------------------
/templates/snippet/feature.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | [<%= $context %>]
4 | <% $options.map |String $name, String $value| { -%>
5 | <%= $name -%> => <%= $value %>
6 | <% } -%>
7 |
--------------------------------------------------------------------------------
/templates/snippet/manager.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | [<%= $manager_name %>]
4 | secret = <%= $secret.unwrap %>
5 | <% $deny.each |$deny_rule| { -%>
6 | deny = <%= $deny_rule %>
7 | <% } -%>
8 | <% $permit.each |$permit_rule| { -%>
9 | permit = <%= $permit_rule %>
10 | <% } -%>
11 | read = <%= $read.join(",") %>
12 | write = <%= $write.join(",") %>
13 | writetimeout = <%= $writetimeout %>
14 | displayconnects = <%= $displayconnects %>
15 | <% if $eventfilter { -%>
16 | eventfilter = <%= $eventfilter %>
17 | <% } -%>
18 |
--------------------------------------------------------------------------------
/templates/snippet/queue.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | [<%= $queue_name %>]
4 | <% if $strategy { -%>
5 | strategy=<%= $strategy %>
6 | <% } -%>
7 | <% $members.each |String $member| { -%>
8 | member=<%= $member %>
9 | <% } -%>
10 | <% if $memberdelay { -%>
11 | memberdelay=<%= $memberdelay %>
12 | <% } -%>
13 | <% if $penaltymemberslimit { -%>
14 | penaltymemberslimit=<%= $penaltymemberslimit %>
15 | <% } -%>
16 | <% if $membermacro { -%>
17 | membermacro=<%= $membermacro %>
18 | <% } -%>
19 | <% if $membergosub { -%>
20 | membergosub=<%= $membergosub %>
21 | <% } -%>
22 | <% if $context { -%>
23 | context=<%= $context %>
24 | <% } -%>
25 | <% if $defaultrule { -%>
26 | defaultrule=<%= $defaultrule %>
27 | <% } -%>
28 | <% if $maxlen { -%>
29 | maxlen=<%= $maxlen %>
30 | <% } -%>
31 | <% if $musicclass { -%>
32 | musicclass=<%= $musicclass %>
33 | <% } -%>
34 | <% if $servicelevel { -%>
35 | servicelevel=<%= $servicelevel %>
36 | <% } -%>
37 | <% if $weight { -%>
38 | weight=<%= $weight %>
39 | <% } -%>
40 | <% if ! empty($joinempty) { -%>
41 | joinempty=<%= $joinempty.join(',') %>
42 | <% } -%>
43 | <% if ! empty($leavewhenempty) { -%>
44 | leavewhenempty=<%= $leavewhenempty.join(',') %>
45 | <% } -%>
46 | <% if $eventwhencalled { -%>
47 | eventwhencalled=<%= $eventwhencalled %>
48 | <% } -%>
49 | <% if $eventmemberstatus { -%>
50 | eventmemberstatus=<%= $eventmemberstatus %>
51 | <% } -%>
52 | <% if $reportholdtime { -%>
53 | reportholdtime=<%= $reportholdtime %>
54 | <% } -%>
55 | <% if $ringinuse { -%>
56 | ringinuse=<%= $ringinuse %>
57 | <% } -%>
58 | <% if $monitor_type { -%>
59 | monitor-type=<%= $monitor_type %>
60 | <% } -%>
61 | <% if ! empty($monitor_format) { -%>
62 | monitor-format=<%= $monitor_format.join('|') %>
63 | <% } -%>
64 | <% if $announce { -%>
65 | announce=<%= $announce %>
66 | <% } -%>
67 | <% if $announce_frequency { -%>
68 | announce-frequency=<%= $announce_frequency %>
69 | <% } -%>
70 | <% if $min_announce_frequency { -%>
71 | min-announce-frequency=<%= $min_announce_frequency %>
72 | <% } -%>
73 | <% if $announce_holdtime { -%>
74 | announce-holdtime=<%= $announce_holdtime %>
75 | <% } -%>
76 | <% if $announce_position { -%>
77 | announce-position=<%= $announce_position %>
78 | <% } -%>
79 | <% if $announce_position_limit { -%>
80 | announce-position-limit=<%= $announce_position_limit %>
81 | <% } -%>
82 | <% if $announce_round_seconds { -%>
83 | announce-round-seconds=<%= $announce_round_seconds %>
84 | <% } -%>
85 | <% if ! empty($periodic_announce) { -%>
86 | periodic-announce=<%= $periodic_announce.join(',') %>
87 | <% } -%>
88 | <% if $periodic_announce_frequency { -%>
89 | periodic-announce-frequency=<%= $periodic_announce_frequency %>
90 | <% } -%>
91 | <% if $random_periodic_announce { -%>
92 | random-periodic-announce=<%= $random_periodic_announce %>
93 | <% } -%>
94 | <% if $relative_periodic_announce { -%>
95 | relative-periodic-announce=<%= $relative_periodic_announce %>
96 | <% } -%>
97 | <% if $queue_youarenext { -%>
98 | queue-youarenext=<%= $queue_youarenext %>
99 | <% } -%>
100 | <% if $queue_thereare { -%>
101 | queue-thereare=<%= $queue_thereare %>
102 | <% } -%>
103 | <% if $queue_callswaiting { -%>
104 | queue-callswaiting=<%= $queue_callswaiting %>
105 | <% } -%>
106 | <% if $queue_holdtime { -%>
107 | queue-holdtime=<%= $queue_holdtime %>
108 | <% } -%>
109 | <% if $queue_minute { -%>
110 | queue-minute=<%= $queue_minute %>
111 | <% } -%>
112 | <% if $queue_minutes { -%>
113 | queue-minutes=<%= $queue_minutes %>
114 | <% } -%>
115 | <% if $queue_seconds { -%>
116 | queue-seconds=<%= $queue_seconds %>
117 | <% } -%>
118 | <% if $queue_thankyou { -%>
119 | queue-thankyou=<%= $queue_thankyou %>
120 | <% } -%>
121 | <% if $queue_reporthold { -%>
122 | queue-reporthold=<%= $queue_reporthold %>
123 | <% } -%>
124 | <% if $wrapuptime { -%>
125 | wrapuptime=<%= $wrapuptime %>
126 | <% } -%>
127 | <% if $timeout { -%>
128 | timeout=<%= $timeout %>
129 | <% } -%>
130 | <% if $timeoutrestart { -%>
131 | timeoutrestart=<%= $timeoutrestart %>
132 | <% } -%>
133 | <% if $timeoutpriority { -%>
134 | timeoutpriority=<%= $timeoutpriority %>
135 | <% } -%>
136 | <% if $retry { -%>
137 | retry=<%= $retry %>
138 | <% } -%>
139 | <% if $autofill { -%>
140 | autofill=<%= $autofill %>
141 | <% } -%>
142 | <% if $autopause { -%>
143 | autopause=<%= $autopause %>
144 | <% } -%>
145 | <% if $setinterfacevar { -%>
146 | setinterfacevar=<%= $setinterfacevar %>
147 | <% } -%>
148 | <% if $setqueuevar { -%>
149 | setqueuevar=<%= $setqueuevar %>
150 | <% } -%>
151 | <% if $setqueueentryvar { -%>
152 | setqueueentryvar=<%= $setqueueentryvar %>
153 | <% } -%>
154 |
--------------------------------------------------------------------------------
/templates/snippet/sip.epp:
--------------------------------------------------------------------------------
1 | ; THIS FILE IS MANAGED BY PUPPET
2 | ; all local modifications will be lost
3 | [<%= $peer_name %>]<% if $template_name { %>(<%= $template_name %>)<% } %>
4 | <% if $account_type { -%>
5 | type=<%= $account_type %>
6 | <% } -%>
7 | <% if $username { -%>
8 | username=<%= $username %>
9 | <% } -%>
10 | <% if $defaultuser { -%>
11 | defaultuser=<%= $defaultuser %>
12 | <% } -%>
13 | <% if $secret { -%>
14 | secret=<%= $secret.unwrap %>
15 | <% } -%>
16 | <% if $md5secret { -%>
17 | md5secret=<%= $md5secret %>
18 | <% } -%>
19 | <% if $remotesecret { -%>
20 | secret=<%= $remotesecret.unwrap %>
21 | <% } -%>
22 | <% if $context { -%>
23 | context=<%= $context %>
24 | <% } -%>
25 | <% if $canreinvite { -%>
26 | canreinvite=<%= $canreinvite %>
27 | <% } -%>
28 | <% if $directmedia { -%>
29 | directmedia=<%= $directmedia %>
30 | <% } -%>
31 | <% if $real_directrtpsetup { -%>
32 | directrtpsetup=<%= $real_directrtpsetup %>
33 | <% } -%>
34 | <% $directmediadeny.each |$dmdeny| { -%>
35 | directmediadeny=<%= $dmdeny %>
36 | <% } -%>
37 | <% $directmediapermit.each |$dmpermit| { -%>
38 | directmediapermit=<%= dmpermit %>
39 | <% } -%>
40 | <% if $host { -%>
41 | host=<%= $host %>
42 | <% } -%>
43 | <% if $insecure { -%>
44 | insecure=<%= $insecure %>
45 | <% } -%>
46 | <% if $language { -%>
47 | language=<%= $language %>
48 | <% } -%>
49 | <% if $nat { -%>
50 | nat=<%= $nat %>
51 | <% } -%>
52 | <% if $qualify { -%>
53 | qualify=<%= $qualify %>
54 | <% } -%>
55 | <% if $vmexten { -%>
56 | vmexten=<%= $vmexten %>
57 | <% } -%>
58 | <% if $fromdomain { -%>
59 | fromdomain=<%= $fromdomain %>
60 | <% } -%>
61 | <% if $fromuser { -%>
62 | fromuser=<%= $fromuser %>
63 | <% } -%>
64 | <% if $account_type == 'peer' and $outboundproxy { -%>
65 | outboundproxy=<%= $outboundproxy %>
66 | <% } -%>
67 | <% if $callerid { -%>
68 | callerid=<%= $callerid %>
69 | <% } -%>
70 | <% if $call_limit { -%>
71 | call-limit=<%= $call_limit %>
72 | <% } -%>
73 | <% if $callgroup { -%>
74 | callgroup=<%= $callgroup %>
75 | <% } -%>
76 | <% if $t38pt_udptl { -%>
77 | t38pt_udptl=<%= $t38pt_udptl %>
78 | <% } -%>
79 | <% if $mailbox { -%>
80 | mailbox=<%= $mailbox %>
81 | <% } -%>
82 | <% if $pickupgroup { -%>
83 | pickupgroup=<%= $pickupgroup %>
84 | <% } -%>
85 | <% $disallow.each |$dproto| { -%>
86 | disallow=<%= $dproto %>
87 | <% } -%>
88 | <% $allow.each |$aproto| { -%>
89 | allow=<%= $aproto %>
90 | <% } -%>
91 | <% if $dtmfmode { -%>
92 | dtmfmode=<%= $dtmfmode %>
93 | <% } -%>
94 | <% if ! empty($transports) { -%>
95 | transport=<%= $transports.join(',') %>
96 | <% } -%>
97 | <% if $encryption { -%>
98 | encryption=<%= $encryption %>
99 | <% } -%>
100 | <% if $trustrpid { -%>
101 | trustrpid=<%= $trustrpid %>
102 | <% } -%>
103 | <% if $sendrpid { -%>
104 | sendrpid=<%= $sendrpid %>
105 | <% } -%>
106 | <%
107 | $access.each |$acc| {
108 | $acc.each |$type, $spec| {
109 | -%>
110 | <%= $type %>=<%= $spec %>
111 | <%
112 | }
113 | }
114 | -%>
115 |
--------------------------------------------------------------------------------
/templates/snippet/voicemail.epp:
--------------------------------------------------------------------------------
1 | [<%= $context %>]
2 | <%= $voicemail %> => <%= $password.unwrap %>,<% if $user_name { -%><%= $user_name %><% } -%>,<% if $email { -%><%= $email %><% } -%>,<% if $pager_email { -%><%= $pager_email %><% } -%><% if ! empty($options) { -%>,<%= $options.map |$key, $value| { "${key}=${value}" }.join("|") %><% } -%>
3 |
4 |
--------------------------------------------------------------------------------
/tests/Puppetfile:
--------------------------------------------------------------------------------
1 | forge 'https://forgeapi.puppetlabs.com'
2 |
3 | mod 'lelutin-asterisk',
4 | git: '/vagrant/'
5 |
--------------------------------------------------------------------------------
/tests/init.pp:
--------------------------------------------------------------------------------
1 | # The baseline for module testing used by Puppet Labs is that each manifest
2 | # should have a corresponding test manifest that declares that class or defined
3 | # type.
4 | #
5 | # Tests are then run by using puppet apply --noop (to check for compilation
6 | # errors and view a log of events) or by fully applying the test in a virtual
7 | # environment (to compare the resulting system state to the desired state).
8 | #
9 | # Learn more about module testing here:
10 | # http://docs.puppetlabs.com/guides/tests_smoke.html
11 | #
12 | include asterisk
13 |
--------------------------------------------------------------------------------
/tests/one_of_all.pp:
--------------------------------------------------------------------------------
1 | # This test file is meant to be a quick and dirty acceptance test for the main
2 | # class without arguments and the most simple case for all of the defined
3 | # types. Its purpose is to make it easy to see if something got broken somehow.
4 |
5 | class { 'asterisk':
6 | extensions_globals => {
7 | 'TRUNK' => 'patate',
8 | 'CHUNKAWOMBA' => Sensitive.new('megamega'),
9 | }
10 | }
11 |
12 | asterisk::agent { 'smith':
13 | ext => '7000',
14 | password => Sensitive.new('misssteranderson'),
15 | agent_name => 'smith',
16 | }
17 |
18 | asterisk::extensions { 'press_one':
19 | content => 'exten => 500,1,Answer',
20 | }
21 |
22 | asterisk::feature { 'exclusivity':
23 | options => {
24 | phone => '555-555-5555',
25 | }
26 | }
27 |
28 | asterisk::iax { 'meetingroom':
29 | content => "type=user\ncontext=press_one",
30 | }
31 |
32 | asterisk::language { 'fr-armelle': }
33 |
34 | asterisk::manager { 'michael':
35 | secret => Sensitive.new('notagoodmanager'),
36 | }
37 |
38 | asterisk::queue { 'tail': }
39 |
40 | asterisk::sip { 'skippy': }
41 |
42 | asterisk::voicemail { '200':
43 | context => 'press_one',
44 | password => Sensitive.new('whoyougonnacall'),
45 | }
46 |
47 | asterisk::registry::iax { 'providerX':
48 | server => 'foo.local',
49 | user => 'carolina',
50 | password => Sensitive.new('thisisapasswordwhatyoulookingat'),
51 | }
52 |
53 | asterisk::registry::sip { 'myphone':
54 | server => 'sipphone.local',
55 | user => 'line1',
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/types/access.pp:
--------------------------------------------------------------------------------
1 | # @summary A deny or permit line for Asterisk configuration
2 | #
3 | # A couple of configuration files let administrators configure accesses. They
4 | # are usually order-dependent so one can interleave permit and deny lines to
5 | # create complex permissions.
6 | type Asterisk::Access = Hash[Enum['permit','deny'], String[1], 1, 1]
7 |
--------------------------------------------------------------------------------
/types/extglobalvars.pp:
--------------------------------------------------------------------------------
1 | # @summary A hash of global variables for the dialplan
2 | #
3 | type Asterisk::ExtGlobalVars = Hash[String, Variant[String,Sensitive]]
4 |
--------------------------------------------------------------------------------
/types/featuremap.pp:
--------------------------------------------------------------------------------
1 | # @summary Options that can be set for featuremap
2 | #
3 | # Those are the possible values that one could find in the `[featuremap]`
4 | # section of `features.conf`.
5 | #
6 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/AdditionalConfig_id256654.html#AdditionalConfig_id243783 List of featuremaps and their meangings
7 | #
8 | type Asterisk::Featuremap = Struct[{
9 | Optional[blindxfer] => String[1],
10 | Optional[disconnect] => String[1],
11 | Optional[automon] => String[1],
12 | Optional[atxfer] => String[1],
13 | Optional[parkcall] => String[1],
14 | Optional[automixmon] => String[1],
15 | }]
16 |
--------------------------------------------------------------------------------
/types/featuresgeneral.pp:
--------------------------------------------------------------------------------
1 | # @summary Possible values for the `[general]` section of features.conf
2 | #
3 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/AdditionalConfig_id256654.html#AdditionalConfig_id244340 List of options and their meaning
4 | #
5 | type Asterisk::Featuresgeneral = Struct[{
6 | Optional[parkext] => String[1],
7 | Optional[parkpos] => String[1],
8 | Optional[context] => String[1],
9 | Optional[parkinghints] => Enum['yes','no'],
10 | Optional[parkingtime] => Integer,
11 | Optional[comebacktoorigin] => Enum['yes','no'],
12 | Optional[courtesytone] => String[1],
13 | Optional[parkedplay] => Enum['callee','caller','both','no'],
14 | Optional[parkedcalltransfers] => Enum['callee','caller','both','no'],
15 | Optional[parkedcallreparking] => Enum['callee','caller','both','no'],
16 | Optional[parkedcallhangup] => Enum['callee','caller','both','no'],
17 | Optional[parkedcallrecording] => Enum['callee','caller','both','no'],
18 | Optional[parkeddynamic] => Enum['yes','no'],
19 | Optional[adsipark] => Enum['yes','no'],
20 | Optional[findslot] => Enum['first','next'],
21 | Optional[parkedmusicclass] => String[1],
22 | Optional[transferdigittimeout] => Integer,
23 | Optional[xfersound] => String[1],
24 | Optional[xferfailsound] => String[1],
25 | Optional[pickupexten] => String[1],
26 | Optional[pickupsound] => String[1],
27 | Optional[pickupfailsound] => String[1],
28 | Optional[featuredigittimeout] => Integer,
29 | Optional[atxfernoanswertimeout] => Integer,
30 | Optional[atxferdropcall] => Enum['yes','no'],
31 | Optional[atxferloopdelay] => Integer,
32 | Optional[atxfercallbackretries] => Integer,
33 | }]
34 |
--------------------------------------------------------------------------------
/types/logfile.pp:
--------------------------------------------------------------------------------
1 | # @summary Options that can be set for a log file
2 | #
3 | # @see https://wiki.asterisk.org/wiki/display/AST/Logging+Configuration
4 | #
5 | type Asterisk::Logfile = Struct[{
6 | Optional[formatter] => Enum['default','json'],
7 | levels => Array[
8 | Variant[
9 | Enum['debug','notice','warning','error','dtmf','fax','security','verbose'],
10 | Pattern[/^verbose\([1-9]\d*\)$/]]
11 | ,1],
12 | }]
13 |
--------------------------------------------------------------------------------
/types/managerperms.pp:
--------------------------------------------------------------------------------
1 | # @summary Possible permissions given to AMI users
2 | #
3 | # @see http://asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/AMI-configuration.html#AMI-readwriteopts List of rights and their meaning
4 | #
5 | type Asterisk::ManagerPerms = Enum[
6 | 'all',
7 | 'system',
8 | 'call',
9 | 'log',
10 | 'verbose',
11 | 'agent',
12 | 'user',
13 | 'config',
14 | 'command',
15 | 'dtmf',
16 | 'reporting',
17 | 'cdr',
18 | 'dialplan',
19 | 'originate',
20 | 'agi',
21 | 'cc',
22 | 'aoc'
23 | ]
24 |
--------------------------------------------------------------------------------