1# Development <a id="development"></a>
2
3This chapter provides hints on Icinga 2 debugging,
4development, package builds and tests.
5
6* [Debug Icinga 2](21-development.md#development-debug)
7    * [GDB Backtrace](21-development.md#development-debug-gdb-backtrace)
8    * [Core Dump](21-development.md#development-debug-core-dump)
9* [Test Icinga 2](21-development.md#development-tests)
10    * [Snapshot Packages (Nightly Builds)](21-development.md#development-tests-snapshot-packages)
11* [Develop Icinga 2](21-development.md#development-develop)
12    * [Preparations](21-development.md#development-develop-prepare)
13    * [Design Patterns](21-development.md#development-develop-design-patterns)
14    * [Build Tools](21-development.md#development-develop-builds-tools)
15    * [Unit Tests](21-development.md#development-develop-tests)
16    * [Style Guide](21-development.md#development-develop-styleguide)
17* [Development Environment](21-development.md#development-environment)
18    * [Linux Dev Environment](21-development.md#development-linux-dev-env)
19    * [macOS Dev Environment](21-development.md#development-macos-dev-env)
20    * [Windows Dev Environment](21-development.md#development-windows-dev-env)
21* [Package Builds](21-development.md#development-package-builds)
22    * [RPM](21-development.md#development-package-builds-rpms)
23    * [DEB](21-development.md#development-package-builds-deb)
24    * [Windows](21-development.md#development-package-builds-windows)
25* [Continuous Integration](21-development.md#development-ci)
26* [Advanced Tips](21-development.md#development-advanced)
27
28<!-- mkdocs requires 4 spaces indent for nested lists: https://github.com/Python-Markdown/markdown/issues/3 -->
29
30## Debug Icinga 2 <a id="development-debug"></a>
31
32This chapter targets all users who have been asked by developers to provide
33a stack trace or coredump if the application crashed. It is also useful
34for developers working with different debuggers.
35
36> **Note:**
37>
38> This is intentionally mentioned before any development insights
39> as debugging is a more frequent and commonly asked question.
40
41### Debug Requirements <a id="debug-requirements"></a>
42
43Make sure that the debug symbols are available for Icinga 2.
44The Icinga 2 packages provide a debug package which must be
45installed separately for all involved binaries, like `icinga2-bin`
46or `icinga2-ido-mysql`.
47
48Distribution       | Command
49-------------------|------------------------------------------
50Debian/Ubuntu      | `apt-get install icinga2-dbg`
51RHEL/CentOS        | `yum install icinga2-debuginfo`
52Fedora             | `dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo`
53SLES/openSUSE      | `zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo`
54
55Furthermore, you may also have to install debug symbols for Boost and your C++ library.
56
57If you're building your own binaries, you should use the `-DCMAKE_BUILD_TYPE=Debug` cmake
58build flag for debug builds.
59
60
61### GDB as Debugger <a id="development-debug-gdb"></a>
62
63Install GDB in your development environment.
64
65Distribution       | Command
66-------------------|------------------------------------------
67Debian/Ubuntu      | `apt-get install gdb`
68RHEL/CentOS        | `yum install gdb`
69Fedora             | `dnf install gdb`
70SLES/openSUSE      | `zypper install gdb`
71
72#### GDB Run <a id="development-debug-gdb-run"></a>
73
74Run the icinga2 binary `/usr/lib{,64}/icinga2/sbin/icinga2` with gdb, `/usr/bin/icinga2` is a shell wrapper.
75
76```
77gdb --args /usr/lib/icinga2/sbin/icinga2 daemon
78
79(gdb) set follow-fork-mode child
80```
81
82When gdb halts on SIGUSR2, press `c` to continue. This signal originates from the umbrella
83process and can safely be ignored.
84
85
86> **Note**
87>
88> Since v2.11 we would attach to the umbrella process spawned with `/usr/lib/icinga2/sbin/icinga2`,
89> therefore rather attach to a running process.
90>
91```bash
92# Typically the order of PIDs is: 1) umbrella 2) spawn helper 3) main process
93pidof icinga2
94
95gdb -p $(pidof icinga2 | cut -d ' ' -f3)
96```
97
98> **Note**
99>
100> If gdb tells you it's missing debug symbols, quit gdb and install
101> them: `Missing separate debuginfos, use: debuginfo-install ...`
102
103Run/restart the application.
104
105```
106(gdb) r
107```
108
109Kill the running application.
110
111```
112(gdb) k
113```
114
115Continue after breakpoint.
116
117```
118(gdb) c
119```
120
121#### GDB Core Dump <a id="development-debug-gdb-coredump"></a>
122
123Either attach to the running process using `gdb -p PID` or start
124a new gdb run.
125
126```
127(gdb) r
128(gdb) generate-core-file
129```
130
131#### GDB Backtrace <a id="development-debug-gdb-backtrace"></a>
132
133If Icinga 2 aborted its operation abnormally, generate a backtrace.
134
135> **Note**
136>
137> Please install the [required debug symbols](21-development.md#debug-requirements)
138> prior to generating a backtrace.
139
140`thread apply all` is important here since this includes all running threads.
141We need this information when e.g. debugging dead locks and hanging features.
142
143```
144(gdb) bt
145(gdb) thread apply all bt full
146```
147
148If gdb stops at a SIGPIPE signal please disable the signal before
149running Icinga 2. This isn't an error, but we need to workaround it.
150
151```
152(gdb) handle SIGPIPE nostop noprint pass
153(gdb) r
154```
155
156If you create a [new issue](https://github.com/Icinga/icinga2/issues),
157make sure to attach as much detail as possible.
158
159#### GDB Backtrace from Running Process <a id="development-debug-gdb-backtrace-running"></a>
160
161If Icinga 2 is still running, generate a full backtrace from the running
162process and store it into a new file (e.g. for debugging dead locks).
163
164> **Note**
165>
166> Please install the [required debug symbols](21-development.md#debug-requirements)
167> prior to generating a backtrace.
168
169Icinga 2 runs with 2 processes: main and command executor, therefore generate two backtrace logs
170and add them to the GitHub issue.
171
172```bash
173for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "thread apply all bt full" -ex "detach" -ex "q" > gdb_bt_${pid}_`date +%s`.log; done
174```
175
176#### GDB Thread List from Running Process <a id="development-debug-gdb-thread-list-running"></a>
177
178Instead of a full backtrace, you sometimes just need a list of running threads.
179
180```bash
181for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "info threads" -ex "detach" -ex "q" > gdb_threads_${pid}_`date +%s`.log; done
182```
183
184#### GDB Backtrace Stepping <a id="development-debug-gdb-backtrace-stepping"></a>
185
186Identifying the problem may require stepping into the backtrace, analysing
187the current scope, attributes, and possible unmet requirements. `p` prints
188the value of the selected variable or function call result.
189
190```
191(gdb) up
192(gdb) down
193(gdb) p checkable
194(gdb) p checkable.px->m_Name
195```
196
197#### GDB Breakpoints <a id="development-debug-gdb-breakpoint"></a>
198
199To set a breakpoint to a specific function call, or file specific line.
200
201```
202(gdb) b checkable.cpp:125
203(gdb) b icinga::Checkable::SetEnablePerfdata
204```
205
206GDB will ask about loading the required symbols later, select `yes` instead
207of `no`.
208
209Then run Icinga 2 until it reaches the first breakpoint. Continue with `c`
210afterwards.
211
212```
213(gdb) run
214(gdb) c
215```
216
217In case you want to step into the next line of code, use `n`. If there is a
218function call where you want to step into, use `s`.
219
220```
221(gdb) n
222
223(gdb) s
224```
225
226If you want to delete all breakpoints, use `d` and select `yes`.
227
228```
229(gdb) d
230```
231
232> **Tip**
233>
234> When debugging exceptions, set your breakpoint like this: `b __cxa_throw`.
235
236Breakpoint Example:
237
238```
239(gdb) b __cxa_throw
240(gdb) r
241(gdb) up
242....
243(gdb) up
244#11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function<void (icinga::String const&)> const&, int) (path=..., pattern=..., callback=..., type=1)
245    at /home/michi/coding/icinga/icinga2/lib/base/utility.cpp:609
246609			callback(cpath);
247(gdb) l
248604
249605	#endif /* _WIN32 */
250606
251607		std::sort(files.begin(), files.end());
252608		BOOST_FOREACH(const String& cpath, files) {
253609			callback(cpath);
254610		}
255611
256612		std::sort(dirs.begin(), dirs.end());
257613		BOOST_FOREACH(const String& cpath, dirs) {
258(gdb) p files
259$3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615,
260    m_Data = "/etc/icinga2/conf.d/commands.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/downtimes.conf"}, {static NPos = 18446744073709551615,
261    m_Data = "/etc/icinga2/conf.d/groups.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/notifications.conf"}, {static NPos = 18446744073709551615,
262    m_Data = "/etc/icinga2/conf.d/satellite.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/services.conf"}, {static NPos = 18446744073709551615,
263    m_Data = "/etc/icinga2/conf.d/templates.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/test.conf"}, {static NPos = 18446744073709551615,
264    m_Data = "/etc/icinga2/conf.d/timeperiods.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/users.conf"}}
265```
266
267
268### Core Dump <a id="development-debug-core-dump"></a>
269
270When the Icinga 2 daemon crashes with a `SIGSEGV` signal
271a core dump file should be written. This will help
272developers to analyze and fix the problem.
273
274#### Core Dump File Size Limit <a id="development-debug-core-dump-limit"></a>
275
276This requires setting the core dump file size to `unlimited`.
277
278
279##### Systemd
280
281```
282systemctl edit icinga2.service
283
284[Service]
285...
286LimitCORE=infinity
287
288systemctl daemon-reload
289
290systemctl restart icinga2
291```
292
293##### Init Script
294
295```
296vim /etc/init.d/icinga2
297...
298ulimit -c unlimited
299
300service icinga2 restart
301```
302
303##### Verify
304
305Verify that the Icinga 2 process core file size limit is set to `unlimited`.
306
307```
308for pid in $(pidof icinga2); do cat /proc/$pid/limits; done
309
310...
311Max core file size        unlimited            unlimited            bytes
312```
313
314
315#### Core Dump Kernel Format <a id="development-debug-core-dump-format"></a>
316
317The Icinga 2 daemon runs with the SUID bit set. Therefore you need
318to explicitly enable core dumps for SUID on Linux.
319
320```bash
321sysctl -w fs.suid_dumpable=2
322```
323
324Adjust the coredump kernel format and file location on Linux:
325
326```bash
327sysctl -w kernel.core_pattern=/var/lib/cores/core.%e.%p
328
329install -m 1777 -d /var/lib/cores
330```
331
332MacOS:
333
334```bash
335sysctl -w kern.corefile=/cores/core.%P
336
337chmod 777 /cores
338```
339
340#### Core Dump Analysis <a id="development-debug-core-dump-analysis"></a>
341
342Once Icinga 2 crashes again a new coredump file will be written. Please
343attach this file to your bug report in addition to the general details.
344
345Simple test case for a `SIGSEGV` simulation with `sleep`:
346
347```
348ulimit -c unlimited
349sleep 1800&
350[1] <PID>
351kill -SEGV <PID>
352gdb `which sleep` /var/lib/cores/core.sleep.<PID>
353(gdb) bt
354rm /var/lib/cores/core.sleep.*
355```
356
357Analyzing Icinga 2:
358
359```
360gdb /usr/lib64/icinga2/sbin/icinga2 core.icinga2.<PID>
361(gdb) bt
362```
363
364### LLDB as Debugger <a id="development-debug-lldb"></a>
365
366LLDB is available on macOS with the Xcode command line tools.
367
368```bash
369xcode-select --install
370```
371
372In order to run Icinga 2 with LLDB you need to pass the binary as argument.
373Since v2.11 we would attach to the umbrella process, therefore rather
374attach to a running process.
375
376```bash
377# Typically the order of PIDs is: 1) umbrella 2) spawn helper 3) main process
378pidof icinga2
379
380lldb -p $(pidof icinga2 | cut -d ' ' -f3)
381```
382
383In case you'll need to attach to the main process immediately, you can delay
384the forked child process and attach to the printed PID.
385
386```
387$ icinga2 daemon -DInternal.DebugWorkerDelay=120
388Closed FD 6 which we inherited from our parent process.
389[2020-01-29 12:22:33 +0100] information/cli: Icinga application loader (version: v2.11.0-477-gfe8701d77; debug)
390[2020-01-29 12:22:33 +0100] information/RunWorker: DEBUG: Current PID: 85253. Sleeping for 120 seconds to allow lldb/gdb -p <PID> attachment.
391```
392
393```bash
394lldb -p 85253
395```
396
397When lldb halts on SIGUSR2, press `c` to continue. This signal originates from the umbrella
398process and can safely be ignored.
399
400
401Breakpoint:
402
403```
404> b checkable.cpp:57
405> b icinga::Checkable::ProcessCheckResult
406```
407
408Full backtrace:
409
410```
411> bt all
412```
413
414Select thread:
415
416```
417> thr sel 5
418```
419
420Step into:
421
422```
423> s
424```
425
426Next step:
427
428```
429> n
430```
431
432Continue:
433
434```
435> c
436```
437
438Up/down in stacktrace:
439
440```
441> up
442> down
443```
444
445
446### Debug on Windows <a id="development-debug-windows"></a>
447
448
449Whenever the application crashes, the Windows error reporting (WER) can be [configured](https://docs.microsoft.com/en-gb/windows/win32/wer/collecting-user-mode-dumps)
450to create user-mode dumps.
451
452
453Tail the log file with Powershell:
454
455```
456Get-Content .\icinga2.log -tail 10 -wait
457```
458
459
460#### Debug on Windows: Dependencies <a id="development-debug-windows-dependencies"></a>
461
462Similar to `ldd` or `nm` on Linux/Unix.
463
464Extract the dependent DLLs from a binary with Visual Studio's `dumpbin` tool
465in Powershell:
466
467```
468C:> &'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\bin\Hostx64\x64\dumpbin.exe' /dependents .\debug\Bin\Debug\Debug\boosttest-test-base.exe
469DEBUG:    1+  >>>> &'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\bin\Hostx64\x64\dumpbin.exe' /dependents .\debug\Bin\Debug\Debug\boosttest-test-base.exe
470Microsoft (R) COFF/PE Dumper Version 14.22.27905.0
471Copyright (C) Microsoft Corporation.  All rights reserved.
472
473
474Dump of file .\debug\Bin\Debug\Debug\boosttest-test-base.exe
475
476File Type: EXECUTABLE IMAGE
477
478  Image has the following dependencies:
479
480    boost_coroutine-vc142-mt-gd-x64-1_76.dll
481    boost_date_time-vc142-mt-gd-x64-1_76.dll
482    boost_filesystem-vc142-mt-gd-x64-1_76.dll
483    boost_thread-vc142-mt-gd-x64-1_76.dll
484    boost_regex-vc142-mt-gd-x64-1_76.dll
485    libssl-1_1-x64.dll
486    libcrypto-1_1-x64.dll
487    WS2_32.dll
488    dbghelp.dll
489    SHLWAPI.dll
490    msi.dll
491    boost_unit_test_framework-vc142-mt-gd-x64-1_76.dll
492    KERNEL32.dll
493    SHELL32.dll
494    ADVAPI32.dll
495    MSVCP140D.dll
496    MSWSOCK.dll
497    bcrypt.dll
498    VCRUNTIME140D.dll
499    ucrtbased.dll
500
501  Summary
502
503        1000 .00cfg
504       68000 .data
505        B000 .idata
506      148000 .pdata
507      69C000 .rdata
508       25000 .reloc
509        1000 .rsrc
510      E7A000 .text
511        1000 .tls
512```
513
514
515## Test Icinga 2 <a id="development-tests"></a>
516
517### Snapshot Packages (Nightly Builds) <a id="development-tests-snapshot-packages"></a>
518
519Icinga provides snapshot packages as nightly builds from [Git master](https://github.com/icinga/icinga2).
520
521These packages contain development code which should be considered "work in progress".
522While developers ensure that tests are running fine with CI actions on PRs,
523things might break, or changes are not yet documented in the changelog.
524
525You can help the developers and test the snapshot packages, e.g. when larger
526changes or rewrites are taking place for a new major version. Your feedback
527is very much appreciated.
528
529Snapshot packages are available for all supported platforms including
530Linux and Windows and can be obtained from [https://packages.icinga.com](https://packages.icinga.com).
531
532The [Vagrant boxes](https://github.com/Icinga/icinga-vagrant) also use
533the Icinga snapshot packages to allow easier integration tests. It is also
534possible to use Docker with base OS images and installing the snapshot
535packages.
536
537If you encounter a problem, please [open a new issue](https://github.com/Icinga/icinga2/issues/new/choose)
538on GitHub and mention that you're testing the snapshot packages.
539
540#### RHEL/CentOS <a id="development-tests-snapshot-packages-rhel"></a>
541
5422.11+ requires the [EPEL repository](02-installation.md#package-repositories-rhel-epel) for Boost 1.66+.
543
544In addition to that, the `icinga-rpm-release` package already provides the `icinga-snapshot-builds`
545repository but it is disabled by default.
546
547```bash
548yum -y install https://packages.icinga.com/epel/icinga-rpm-release-7-latest.noarch.rpm
549yum -y install epel-release
550yum makecache
551
552yum install --enablerepo=icinga-snapshot-builds icinga2
553```
554
555#### Debian <a id="development-tests-snapshot-packages-debian"></a>
556
5572.11+ requires Boost 1.66+ which either is provided by the OS, backports or Icinga stable repositories.
558It is advised to configure both Icinga repositories, stable and snapshot and selectively
559choose the repository with the `-t` flag on `apt-get install`.
560
561```bash
562apt-get update
563apt-get -y install apt-transport-https wget gnupg
564
565wget -O - https://packages.icinga.com/icinga.key | apt-key add -
566
567DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
568 echo "deb https://packages.icinga.com/debian icinga-${DIST} main" > \
569 /etc/apt/sources.list.d/${DIST}-icinga.list
570 echo "deb-src https://packages.icinga.com/debian icinga-${DIST} main" >> \
571 /etc/apt/sources.list.d/${DIST}-icinga.list
572
573DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
574 echo "deb http://packages.icinga.com/debian icinga-${DIST}-snapshots main" > \
575 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list
576 echo "deb-src http://packages.icinga.com/debian icinga-${DIST}-snapshots main" >> \
577 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list
578
579apt-get update
580```
581
582On Debian Stretch, you'll also need to add Debian Backports.
583
584```bash
585DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
586 echo "deb https://deb.debian.org/debian ${DIST}-backports main" > \
587 /etc/apt/sources.list.d/${DIST}-backports.list
588
589apt-get update
590```
591
592Then install the snapshot packages.
593
594```bash
595DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
596apt-get install -t icinga-${DIST}-snapshots icinga2
597```
598
599#### Ubuntu <a id="development-tests-snapshot-packages-ubuntu"></a>
600
601```bash
602apt-get update
603apt-get -y install apt-transport-https wget gnupg
604
605wget -O - https://packages.icinga.com/icinga.key | apt-key add -
606
607. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \
608 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST} main" > \
609 /etc/apt/sources.list.d/${DIST}-icinga.list
610 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST} main" >> \
611 /etc/apt/sources.list.d/${DIST}-icinga.list
612
613. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \
614 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST}-snapshots main" > \
615 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list
616 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST}-snapshots main" >> \
617 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list
618
619apt-get update
620```
621
622Then install the snapshot packages.
623
624```bash
625. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \
626apt-get install -t icinga-${DIST}-snapshots icinga2
627```
628
629#### SLES <a id="development-tests-snapshot-packages-sles"></a>
630
631The required Boost packages are provided with the stable release repository.
632
633```bash
634rpm --import https://packages.icinga.com/icinga.key
635
636zypper ar https://packages.icinga.com/SUSE/ICINGA-release.repo
637zypper ref
638
639zypper ar https://packages.icinga.com/SUSE/ICINGA-snapshot.repo
640zypper ref
641```
642
643Selectively install the snapshot packages using the `-r` parameter.
644
645```bash
646zypper in -r icinga-snapshot-builds icinga2
647```
648
649
650### Unit Tests <a id="development-tests-unit"></a>
651
652Build the binaries and run the tests.
653
654
655```bash
656make -j4 -C debug
657make test -C debug
658```
659
660Run a specific boost test:
661
662```bash
663debug/Bin/Debug/boosttest-test-base --run_test=remote_url
664```
665
666
667
668## Develop Icinga 2 <a id="development-develop"></a>
669
670Icinga 2 can be built on many platforms such as Linux, Unix and Windows.
671There are limitations in terms of support, e.g. Windows is only supported for agents,
672not a full-featured master or satellite.
673
674Before you start with actual development, there is a couple of pre-requisites.
675
676### Preparations <a id="development-develop-prepare"></a>
677
678#### Choose your Editor <a id="development-develop-choose-editor"></a>
679
680Icinga 2 can be developed with your favorite editor. Icinga developers prefer
681these tools:
682
683- vim
684- CLion (macOS, Linux)
685- MS Visual Studio (Windows)
686- Atom
687
688Editors differ on the functionality. The more helpers you get for C++ development,
689the faster your development workflow will be.
690
691#### Get to know the architecture <a id="development-develop-get-to-know-the-architecture"></a>
692
693Icinga 2 can run standalone or in distributed environments. It contains a whole lot
694more than a simple check execution engine.
695
696Read more about it in the [Technical Concepts](19-technical-concepts.md#technical-concepts) chapter.
697
698#### Get to know the code <a id="development-develop-get-to-know-the-code"></a>
699
700First off, you really need to know C++ and portions of C++11 and the boost libraries.
701Best is to start with a book or online tutorial to get into the basics.
702Icinga developers gained their knowledge through studies, training and self-teaching
703code by trying it out and asking senior developers for guidance.
704
705Here's a few books we can recommend:
706
707* [Accelerated C++: Practical Programming by Example](https://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X) (Andrew Koenig, Barbara E. Moo)
708* [Effective C++](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876) (Scott Meyers)
709* [Boost C++ Application Development Cookbook - Second Edition: Recipes to simplify your application development](https://www.amazon.com/dp/1787282244/ref=cm_sw_em_r_mt_dp_U_dN1OCbERS00EQ) (Antony Polukhin)
710* [Der C++ Programmierer](https://www.amazon.de/Programmierer-lernen-Professionell-anwenden-L%C3%B6sungen/dp/3446416447), German (Ulrich Breymann)
711* [C++11 programmieren](https://www.amazon.de/gp/product/3836217325/), German (Torsten T. Will)
712
713In addition, it is a good bet to also know SQL when diving into backend development.
714
715* [SQL Performance Explained](https://www.amazon.de/gp/product/3950307826/) (Markus Winand)
716
717Last but not least, if you are developing on Windows, get to know the internals about services and the Win32 API.
718
719### Design Patterns <a id="development-develop-design-patterns"></a>
720
721Icinga 2 heavily relies on object-oriented programming and encapsulates common
722functionality into classes and objects. It also uses modern programming techniques
723to e.g. work with shared pointer memory management.
724
725Icinga 2 consists of libraries bundled into the main binary. Therefore you'll
726find many code parts in the `lib/` directory wheras the actual application is
727built from `icinga-app/`. Accompanied with Icinga 2, there's the Windows plugins
728which are standalone and compiled from `plugins/`.
729
730Library        | Description
731---------------|------------------------------------
732base           | Objects, values, types, streams, tockets, TLS, utilities, etc.
733config         | Configuration compiler, expressions, etc.
734cli            | CLI (sub) commands and helpers.
735icinga         | Icinga specific objects and event handling.
736remote         | Cluster and HTTP client/server and REST API related code.
737checker        | Checker feature, check scheduler.
738notification   | Notification feature, notification scheduler.
739methods        | Command execution methods, plugins and built-in checks.
740perfdata       | Performance data related, including Graphite, Elastic, etc.
741db\_ido        | IDO database abstraction layer.
742db\_ido\_mysql | IDO database driver for MySQL.
743db\_ido\_pgsql | IDO database driver for PgSQL.
744mysql\_shin    | Library stub for linking against the MySQL client libraries.
745pgsql\_shim    | Library stub for linking against the PgSQL client libraries.
746
747#### Class Compiler <a id="development-develop-design-patterns-class-compiler"></a>
748
749Another thing you will recognize are the `.ti` files which are compiled
750by our own class compiler into actual source code. The meta language allows
751developers to easily add object attributes and specify their behaviour.
752
753Some object attributes need to be stored over restarts in the state file
754and therefore have the `state` attribute set. Others are treated as `config`
755attribute and automatically get configuration validation functions created.
756Hidden or read-only REST API attributes are marked with `no_user_view` and
757`no_user_modify`.
758
759The most beneficial thing are getters and setters being generated. The actual object
760inherits from `ObjectImpl<TYPE>` and therefore gets them "for free".
761
762Example:
763
764```
765vim lib/perfdata/gelfwriter.ti
766
767  [config] enable_tls;
768
769vim lib/perfdata/gelfwriter.cpp
770
771    if (GetEnableTls()) {
772```
773
774The logic is hidden in `tools/mkclass/` in case you want to learn more about it.
775The first steps during CMake & make also tell you about code generation.
776
777### Build Tools <a id="development-develop-builds-tools"></a>
778
779#### CMake <a id="development-develop-builds-cmake"></a>
780
781In its early development stages in 2012, Icinga 2 was built with autoconf/automake
782and separate Windows project files. We've found this very fragile, and have changed
783this into CMake as our build tool.
784
785The most common benefits:
786
787* Everything is described in CMakeLists.txt in each directory
788* CMake only needs to know that a sub directory needs to be included.
789* The global CMakeLists.txt acts as main entry point for requirement checks and library/header includes.
790* Separate binary build directories, the actual source tree stays clean.
791* CMake automatically generates a Visual Studio project file `icinga2.sln` on Windows.
792
793#### Unity Builds <a id="development-develop-builds-unity-builds"></a>
794
795Another thing you should be aware of: Unity builds on and off.
796
797Typically, we already use caching mechanisms to reduce recompile time with ccache.
798For release builds, there's always a new build needed as the difference is huge compared
799to a previous (major) release.
800
801Therefore we've invented the Unity builds, which basically concatenates all source files
802into one big library source code file. The compiler then doesn't need to load the many small
803files but compiles and links this huge one.
804
805Unity builds require more memory which is why you should disable them for development
806builds in small sized VMs (Linux, Windows) and also Docker containers.
807
808There's a couple of header files which are included everywhere. If you touch/edit them,
809the cache is invalidated and you need to recompile a lot more files then. `base/utility.hpp`
810and `remote/zone.hpp` are good candidates for this.
811
812### Unit Tests <a id="development-develop-tests"></a>
813
814New functions and classes must implement new unit tests. Whenever
815you decide to add new functions, ensure that you don't need a complex
816mock or runtime attributes in order to test them. Better isolate
817code into function interfaces which can be invoked in the Boost tests
818framework.
819
820Look into the existing tests in the [test/](https://github.com/Icinga/icinga2/tree/master/test) directory
821and adopt new test cases.
822
823Specific tests require special time windows, they are only
824enabled in debug builds for developers. This is the case e.g.
825for testing the flapping algorithm with expected state change
826detection at a specific point from now.
827
828
829### Style Guide <a id="development-develop-styleguide"></a>
830
831Overview of project files:
832
833File Type      | File Name/Extension | Description
834---------------|---------------------|-----------------------------
835Header         | .hpp                | Classes, enums, typedefs inside the icinga Namespace.
836Source         | .cpp                | Method implementation for class functions, static/global variables.
837CMake          | CMakeLists.txt      | Build configuration, source and header file references.
838CMake Source   | .cmake              | Source/Header files generated from CMake placeholders.
839ITL/conf.d     | .conf               | Template library and example files as configuration
840Class Compiler | .ti                 | Object classes in our own language, generates source code as `<filename>-ti.{c,h}pp`.
841Lexer/Parser   | .ll, .yy            | Flex/Bison code generated into source code from CMake builds.
842Docs           | .md                 | Markdown docs and READMEs.
843
844Anything else are additional tools and scripts for developers and build systems.
845
846All files must include the copyright header. We don't use the
847current year as this implies yearly updates we don't want.
848
849Depending on the file type, this must be a comment.
850
851```cpp
852/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
853```
854
855```bash
856# Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+
857```
858
859#### Code Formatting <a id="development-develop-code-formatting"></a>
860
861**Tabs instead of spaces.** Inside Visual Studio, choose to keep tabs instead of
862spaces. Tabs should use 4 spaces indent by default, depending on your likings.
863
864We follow the clang format, with some exceptions.
865
866- Curly braces for functions and classes always start at a new line.
867
868```cpp
869String ConfigObjectUtility::EscapeName(const String& name)
870{
871//...
872}
873
874String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName,
875	bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs)
876{
877//...
878}
879```
880
881- Too long lines break at a parameter, the new line needs a tab indent.
882
883```cpp
884	static String CreateObjectConfig(const Type::Ptr& type, const String& fullName,
885		bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs);
886```
887
888- Conditions require curly braces if it is not a single if with just one line.
889
890
891```cpp
892	if (s == "OK") {
893		//...
894	} else {
895		//...
896	}
897
898	if (!n)
899		return;
900```
901
902- There's a space between `if` and the opening brace `(`. Also after the closing brace `)` and opening curly brace `{`.
903- Negation with `!` doesn't need an extra space.
904- Else branches always start in the same line after the closing curly brace.
905
906
907#### Code Comments <a id="development-develop-code-comments"></a>
908
909Add comments wherever you think that another developer will have a hard
910time to understand the complex algorithm. Or you might have forgotten
911it in a year and struggle again. Also use comments to highlight specific
912stages in a function. Generally speaking, make things easier for the
913team and external contributors.
914
915Comments can also be used to mark additional references and TODOs.
916If there is a specific GitHub issue or discussion going on,
917use that information as a summary and link over to it on purpose.
918
919- Single line comments may use `//` or `/* ... */`
920- Multi line comments must use this format:
921
922```cpp
923/* Ensure to check for XY
924 * This relies on the fact that ABC has been set before.
925 */
926```
927
928#### Function Docs <a id="development-develop-function-docs"></a>
929
930Function header documentation must be added. The current code basis
931needs rework, future functions must provide this.
932
933Editors like CLion or Visual Studio allow you to type `/**` followed
934by Enter and generate the skeleton from the implemented function.
935
936Add a short summary in the first line about the function's purpose.
937Edit the param section with short description on their intention.
938The `return` value should describe the value type and additional details.
939
940Example:
941
942```cpp
943/**
944 * Reads a message from the connected peer.
945 *
946 * @param stream ASIO TLS Stream
947 * @param yc Yield Context for ASIO
948 * @param maxMessageLength maximum size of bytes read.
949 *
950 * @return A JSON string
951 */
952String JsonRpc::ReadMessage(const std::shared_ptr<AsioTlsStream>& stream, boost::asio::yield_context yc, ssize_t maxMessageLength)
953```
954
955While we can generate code docs from it, the main idea behind it is
956to provide on-point docs to fully understand all parameters and the
957function's purpose in the same spot.
958
959
960#### Header <a id="development-develop-styleguide-header"></a>
961
962Only include other headers which are mandatory for the header definitions.
963If the source file requires additional headers, add them there to avoid
964include loops.
965
966The included header order is important.
967
968- First, include the library header `i2-<libraryname>.hpp`, e.g. `i2-base.hpp`.
969- Second, include all headers from Icinga itself, e.g. `remote/apilistener.hpp`. `base` before `icinga` before `remote`, etc.
970- Third, include third-party and external library headers, e.g. openssl and boost.
971- Fourth, include STL headers.
972
973#### Source <a id="development-develop-styleguide-source"></a>
974
975The included header order is important.
976
977- First, include the header whose methods are implemented.
978- Second, include all headers from Icinga itself, e.g. `remote/apilistener.hpp`. `base` before `icinga` before `remote`, etc.
979- Third, include third-party and external library headers, e.g. openssl and boost.
980- Fourth, include STL headers.
981
982Always use an empty line after the header include parts.
983
984#### Namespace <a id="development-develop-styleguide-namespace"></a>
985
986The icinga namespace is used globally, as otherwise we would need to write `icinga::Utility::FormatDateTime()`.
987
988```cpp
989using namespace icinga;
990```
991
992Other namespaces must be declared in the scope they are used. Typically
993this is inside the function where `boost::asio` and variants would
994complicate the code.
995
996```cpp
997	namespace ssl = boost::asio::ssl;
998
999	auto context (std::make_shared<ssl::context>(ssl::context::sslv23));
1000```
1001
1002#### Functions <a id="development-develop-styleguide-functions"></a>
1003
1004Ensure to pass values and pointers as const reference. By default, all
1005values will be copied into the function scope, and we want to avoid this
1006wherever possible.
1007
1008```cpp
1009std::vector<EventQueue::Ptr> EventQueue::GetQueuesForType(const String& type)
1010```
1011
1012C++ only allows to return a single value. This can be abstracted with
1013returning a specific class object, or with using a map/set. Array and
1014Dictionary objects increase the memory footprint, use them only where needed.
1015
1016A common use case for Icinga value types is where a function can return
1017different values - an object, an array, a boolean, etc. This happens in the
1018inner parts of the config compiler expressions, or config validation.
1019
1020The function caller is responsible to determine the correct value type
1021and handle possible errors.
1022
1023Specific algorithms may require to populate a list, which can be passed
1024by reference to the function. The inner function can then append values.
1025Do not use a global shared resource here, unless this is locked by the caller.
1026
1027
1028#### Conditions and Cases <a id="development-develop-styleguide-conditions"></a>
1029
1030Prefer if-else-if-else branches. When integers are involved,
1031switch-case statements increase readability. Don't forget about `break` though!
1032
1033Avoid using ternary operators where possible. Putting a condition
1034after an assignment complicates reading the source. The compiler
1035optimizes this anyways.
1036
1037Wrong:
1038
1039```cpp
1040	int res = s == "OK" ? 0 : s == "WARNING" ? 1;
1041
1042	return res;
1043```
1044
1045Better:
1046
1047```cpp
1048	int res = 3;
1049
1050	if (s == "OK") {
1051		res = 0;
1052	} else if (s == "WARNING") {
1053		res = 1;
1054	}
1055```
1056
1057Even better: Create a lookup map instead of if branches. The complexity
1058is reduced to O(log(n)).
1059
1060```cpp
1061	std::map<String, unsigned int> stateMap = {
1062		{ "OK", 1 },
1063		{ "WARNING", 2 }
1064	}
1065
1066	auto it = stateMap.find(s);
1067
1068	if (it == stateMap.end()) {
1069		return 3
1070	}
1071
1072	return it.second;
1073```
1074
1075The code is not as short as with a ternary operator, but one can re-use
1076this design pattern for other generic definitions with e.g. moving the
1077lookup into a utility class.
1078
1079Once a unit test is written, everything works as expected in the future.
1080
1081#### Locks and Guards <a id="development-develop-locks-guards"></a>
1082
1083Lock access to resources where multiple threads can read and write.
1084Icinga objects can be locked with the `ObjectLock` class.
1085
1086Object locks and guards must be limited to the scope where they are needed. Otherwise we could create dead locks.
1087
1088```cpp
1089	{
1090		ObjectLock olock(frame.Locals);
1091		for (const Dictionary::Pair& kv : frame.Locals) {
1092			AddSuggestion(matches, word, kv.first);
1093		}
1094	}
1095```
1096
1097#### Objects and Pointers <a id="development-develop-objects-pointers"></a>
1098
1099Use shared pointers for objects. Icinga objects implement the `Ptr`
1100typedef returning an `intrusive_ptr` for the class object (object.hpp).
1101This also ensures reference counting for the object's lifetime.
1102
1103Use raw pointers with care!
1104
1105Some methods and classes require specific shared pointers, especially
1106when interacting with the Boost library.
1107
1108#### Value Types <a id="development-develop-styleguide-value-types"></a>
1109
1110Icinga has its own value types. These provide methods to allow
1111generic serialization into JSON for example, and other type methods
1112which are made available in the DSL too.
1113
1114- Always use `String` instead of `std::string`. If you need a C-string, use the `CStr()` method.
1115- Avoid casts and rather use the `Convert` class methods.
1116
1117```cpp
1118	double s = static_cast<double>(v); //Wrong
1119
1120	double s = Convert::ToDouble(v);   //Correct, ToDouble also provides overloads with different value types
1121```
1122
1123- Prefer STL containers for internal non-user interfaces. Icinga value types add a small overhead which may decrease performance if e.g. the function is called 100k times.
1124- `Array::FromVector` and variants implement conversions, use them.
1125
1126#### Utilities <a id="development-develop-styleguide-utilities"></a>
1127
1128Don't re-invent the wheel. The `Utility` class provides
1129many helper functions which allow you e.g. to format unix timestamps,
1130search in filesystem paths.
1131
1132Also inspect the Icinga objects, they also provide helper functions
1133for formatting, splitting strings, joining arrays into strings, etc.
1134
1135#### Libraries <a id="development-develop-styleguide-libraries"></a>
1136
11372.11 depends on [Boost 1.66](https://www.boost.org/doc/libs/1_66_0/).
1138Use the existing libraries and header-only includes
1139for this specific version.
1140
1141Note: Prefer C++11 features where possible, e.g. std::atomic and lambda functions.
1142
1143General:
1144
1145- [exception](https://www.boost.org/doc/libs/1_66_0/libs/exception/doc/boost-exception.html) (header only)
1146- [algorithm](https://www.boost.org/doc/libs/1_66_0/libs/algorithm/doc/html/index.html) (header only)
1147- [lexical_cast](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_lexical_cast.html) (header only)
1148- [regex](https://www.boost.org/doc/libs/1_66_0/libs/regex/doc/html/index.html)
1149- [uuid](https://www.boost.org/doc/libs/1_66_0/libs/uuid/doc/uuid.html) (header only)
1150- [range](https://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/index.html) (header only)
1151- [variant](https://www.boost.org/doc/libs/1_66_0/doc/html/variant.html) (header only)
1152- [multi_index](https://www.boost.org/doc/libs/1_66_0/libs/multi_index/doc/index.html) (header only)
1153- [function_types](https://www.boost.org/doc/libs/1_66_0/libs/function_types/doc/html/index.html) (header only)
1154- [circular_buffer](https://www.boost.org/doc/libs/1_66_0/doc/html/circular_buffer.html) (header only)
1155- [math](https://www.boost.org/doc/libs/1_66_0/libs/math/doc/html/index.html) (header only)
1156- [stacktrace](https://www.boost.org/doc/libs/1_66_0/doc/html/stacktrace.html) (header only)
1157
1158Events and Runtime:
1159
1160- [system](https://www.boost.org/doc/libs/1_66_0/libs/system/doc/index.html)
1161- [thread](https://www.boost.org/doc/libs/1_66_0/doc/html/thread.html)
1162- [signals2](https://www.boost.org/doc/libs/1_66_0/doc/html/signals2.html) (header only)
1163- [program_options](https://www.boost.org/doc/libs/1_66_0/doc/html/program_options.html)
1164- [date_time](https://www.boost.org/doc/libs/1_66_0/doc/html/date_time.html)
1165- [filesystem](https://www.boost.org/doc/libs/1_66_0/libs/filesystem/doc/index.htm)
1166
1167Network I/O:
1168
1169- [asio](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio.html) (header only)
1170- [beast](https://www.boost.org/doc/libs/1_66_0/libs/beast/doc/html/index.html) (header only)
1171- [coroutine](https://www.boost.org/doc/libs/1_66_0/libs/coroutine/doc/html/index.html)
1172- [context](https://www.boost.org/doc/libs/1_66_0/libs/context/doc/html/index.html)
1173
1174Consider abstracting their usage into `*utility.{c,h}pp` files with
1175wrapping existing Icinga types. That also allows later changes without
1176rewriting large code parts.
1177
1178> **Note**
1179>
1180> A new Boost library should be explained in a PR and discussed with the team.
1181>
1182> This requires package dependency changes.
1183
1184If you consider an external library or code to be included with Icinga, the following
1185requirements must be fulfilled:
1186
1187- License is compatible with GPLv2+. Boost license, MIT works, Apache is not.
1188- C++11 is supported, C++14 or later doesn't work
1189- Header only implementations are preferred, external libraries require packages on every distribution.
1190- No additional frameworks, Boost is the only allowed.
1191- The code is proven to be robust and the GitHub repository is alive, or has 1k+ stars. Good libraries also provide a user list, if e.g. Ceph is using it, this is a good candidate.
1192
1193
1194#### Log <a id="development-develop-styleguide-log"></a>
1195
1196Icinga allows the user to configure logging backends, e.g. syslog or file.
1197
1198Any log message inside the code must use the `Log()` function.
1199
1200- The first parameter is the severity level, use them with care.
1201- The second parameter defines the location/scope where the log
1202happened. Typically we use the class name here, to better analyse
1203the logs the user provide in GitHub issues and on the community
1204channels.
1205- The third parameter takes a log message string
1206
1207If the message string needs to be computed from existing values,
1208everything must be converted to the String type beforehand.
1209This conversion for every value is very expensive which is why
1210we try to avoid it.
1211
1212Instead, use Log() with the shift operator where everything is written
1213on the stream and conversions are explicitly done with templates
1214in the background.
1215
1216The trick here is that the Log object is destroyed immediately
1217after being constructed once. The destructor actually
1218evaluates the values and sends it to registers loggers.
1219
1220Since flushing the stream every time a log entry occurs is
1221very expensive, a timer takes care of flushing the stream
1222every second.
1223
1224> **Tip**
1225>
1226> If logging stopped, the flush timer thread may be dead.
1227> Inspect that with gdb/lldb.
1228
1229Avoid log messages which could irritate the user. During
1230implementation, developers can change log levels to better
1231see what's going one, but remember to change this back to `debug`
1232or remove it entirely.
1233
1234
1235#### Goto <a id="development-develop-styleguide-goto"></a>
1236
1237Avoid using `goto` statements. There are rare occasions where
1238they are allowed:
1239
1240- The code would become overly complicated within nested loops and conditions.
1241- Event processing and C interfaces.
1242- Question/Answer loops within interactive CLI commands.
1243
1244#### Typedef and Auto Keywords <a id="development-develop-styleguide-typedef-auto"></a>
1245
1246Typedefs allow developers to use shorter names for specific types,
1247classes and structs.
1248
1249```cpp
1250	typedef std::map<String, std::shared_ptr<NamespaceValue> >::iterator Iterator;
1251```
1252
1253These typedefs should be part of the Class definition in the header,
1254or may be defined in the source scope where they are needed.
1255
1256Avoid declaring global typedefs, unless necessary.
1257
1258Using the `auto` keyword allows to ignore a specific value type.
1259This comes in handy with maps/sets where no specific access
1260is required.
1261
1262The following example iterates over a map returned from `GetTypes()`.
1263
1264```cpp
1265	for (const auto& kv : GetTypes()) {
1266		result.insert(kv.second);
1267	}
1268```
1269
1270The long example would require us to define a map iterator, and a slightly
1271different algorithm.
1272
1273```cpp
1274	typedef std::map<String, DbType::Ptr> TypeMap;
1275	typedef std::map<String, DbType::Ptr>::const_iterator TypeMapIterator;
1276
1277	TypeMap types = GetTypes();
1278
1279	for (TypeMapIterator it = types.begin(); it != types.end(); it++) {
1280		result.insert(it.second);
1281	}
1282```
1283
1284We could also use a pair here, but requiring to know
1285the specific types of the map keys and values.
1286
1287```cpp
1288	typedef std::pair<String, DbType::Ptr> kv_pair;
1289
1290	for (const kv_pair& kv : GetTypes()) {
1291		result.insert(kv.second);
1292	}
1293```
1294
1295After all, `auto` shortens the code and one does not always need to know
1296about the specific types. Function documentation for `GetTypes()` is
1297required though.
1298
1299
1300
1301#### Whitespace Cleanup <a id="development-develop-choose-editor-whitespaces"></a>
1302
1303Patches must be cleaned up and follow the indent style (tabs instead of spaces).
1304You should also remove any trailing whitespaces.
1305
1306`git diff` allows to highlight such.
1307
1308```
1309vim $HOME/.gitconfig
1310
1311[color "diff"]
1312        whitespace = red reverse
1313[core]
1314        whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol
1315```
1316
1317`vim` also can match these and visually alert you to remove them.
1318
1319```
1320vim $HOME/.vimrc
1321
1322highlight ExtraWhitespace ctermbg=red guibg=red
1323match ExtraWhitespace /\s\+$/
1324autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
1325autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
1326autocmd InsertLeave * match ExtraWhitespace /\s\+$/
1327autocmd BufWinLeave * call clearmatches()
1328```
1329
1330
1331## Development Environment <a id="development-environment"></a>
1332
1333### Linux Dev Environment <a id="development-linux-dev-env"></a>
1334
1335Based on CentOS 7, we have an early draft available inside the Icinga Vagrant boxes:
1336[centos7-dev](https://github.com/Icinga/icinga-vagrant/tree/master/centos7-dev).
1337
1338If you're compiling Icinga 2 natively without any virtualization layer in between,
1339this usually is faster. This is also the reason why developers on macOS prefer native builds
1340over Linux or Windows VMs. Don't forget to test the actual code on Linux later! Socket specific
1341stuff like `epoll` is not available on Unix kernels.
1342
1343Depending on your workstation and environment, you may either develop and run locally,
1344use a container deployment pipeline or put everything in a high end resource remote VM.
1345
1346Fork https://github.com/Icinga/icinga2 into your own repository, e.g. `https://github.com/dnsmichi/icinga2`.
1347
1348Create two build directories for different binary builds.
1349
1350* `debug` contains the debug build binaries. They contain more debug information and run tremendously slower than release builds from packages. Don't use them for benchmarks.
1351* `release` contains the release build binaries, as you would install them on a live system. This helps comparing specific scenarios for race conditions and more.
1352
1353```bash
1354mkdir -p release debug
1355```
1356
1357Proceed with the specific distribution examples below. Keep in mind that these instructions
1358are best effort and sometimes out-of-date. Git Master may contain updates.
1359
1360* [CentOS 7](21-development.md#development-linux-dev-env-centos)
1361* [Debian 10 Buster](21-development.md#development-linux-dev-env-debian)
1362* [Ubuntu 18 Bionic](21-development.md#development-linux-dev-env-ubuntu)
1363
1364
1365#### CentOS 7 <a id="development-linux-dev-env-centos"></a>
1366
1367```bash
1368yum -y install gdb vim git bash-completion htop
1369
1370yum -y install rpmdevtools ccache \
1371 cmake make gcc-c++ flex bison \
1372 openssl-devel boost169-devel systemd-devel \
1373 mysql-devel postgresql-devel libedit-devel \
1374 libstdc++-devel
1375
1376groupadd icinga
1377groupadd icingacmd
1378useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga
1379
1380ln -s /bin/ccache /usr/local/bin/gcc
1381ln -s /bin/ccache /usr/local/bin/g++
1382
1383git clone https://github.com/icinga/icinga2.git && cd icinga2
1384```
1385
1386The debug build binaries contain specific code which runs
1387slower but allows for better debugging insights.
1388
1389For benchmarks, change `CMAKE_BUILD_TYPE` to `RelWithDebInfo` and
1390build inside the `release` directory.
1391
1392First, off export some generics for Boost.
1393
1394```bash
1395export I2_BOOST="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib64/boost169 -DBOOST_INCLUDEDIR=/usr/include/boost169 -DBoost_ADDITIONAL_VERSIONS='1.69;1.69.0'"
1396```
1397
1398Second, add the prefix path to it.
1399
1400```bash
1401export I2_GENERIC="$I2_BOOST -DCMAKE_INSTALL_PREFIX=/usr/local/icinga2"
1402```
1403
1404Third, define the two build types with their specific CMake variables.
1405
1406```bash
1407export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC"
1408export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC"
1409```
1410
1411Fourth, depending on your likings, you may add a bash alias for building,
1412or invoke the commands inside:
1413
1414```bash
1415alias i2_debug="cd /root/icinga2; mkdir -p debug; cd debug; cmake $I2_DEBUG ..; make -j2; sudo make -j2 install; cd .."
1416alias i2_release="cd /root/icinga2; mkdir -p release; cd release; cmake $I2_RELEASE ..; make -j2; sudo make -j2 install; cd .."
1417```
1418
1419This is taken from the [centos7-dev](https://github.com/Icinga/icinga-vagrant/tree/master/centos7-dev) Vagrant box.
1420
1421
1422The source installation doesn't set proper permissions, this is
1423handled in the package builds which are officially supported.
1424
1425```bash
1426chown -R icinga:icinga /usr/local/icinga2/var/
1427
1428/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2
1429/usr/local/icinga2/sbin/icinga2 api setup
1430vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf
1431
1432/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon
1433```
1434
1435#### Debian 10 <a id="development-linux-dev-env-debian"></a>
1436
1437Debian Buster doesn't need updated Boost packages from packages.icinga.com,
1438the distribution already provides 1.66+. For older versions such as Stretch,
1439include the release repository for packages.icinga.com as shown in the [setup instructions](02-installation.md#package-repositories-debian-ubuntu-raspbian).
1440
1441```bash
1442docker run -ti debian:buster bash
1443
1444apt-get update
1445apt-get -y install apt-transport-https wget gnupg
1446
1447apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev bison flex default-libmysqlclient-dev libpq-dev libedit-dev monitoring-plugins
1448apt-get -y install libboost-all-dev
1449```
1450
1451```bash
1452ln -s /usr/bin/ccache /usr/local/bin/gcc
1453ln -s /usr/bin/ccache /usr/local/bin/g++
1454
1455groupadd icinga
1456groupadd icingacmd
1457useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga
1458
1459git clone https://github.com/icinga/icinga2.git && cd icinga2
1460
1461mkdir debug release
1462
1463export I2_DEB="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib/x86_64-linux-gnu -DBOOST_INCLUDEDIR=/usr/include -DCMAKE_INSTALL_RPATH=/usr/lib/x86_64-linux-gnu"
1464export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin"
1465export I2_DEBUG="$I2_DEB $I2_GENERIC -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF"
1466
1467cd debug
1468cmake .. $I2_DEBUG
1469cd ..
1470
1471make -j2 install -C debug
1472```
1473
1474
1475The source installation doesn't set proper permissions, this is
1476handled in the package builds which are officially supported.
1477
1478```bash
1479chown -R icinga:icinga /usr/local/icinga2/var/
1480
1481/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2
1482/usr/local/icinga2/sbin/icinga2 api setup
1483vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf
1484
1485/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon
1486```
1487
1488
1489#### Ubuntu 18 Bionic <a id="development-linux-dev-env-ubuntu"></a>
1490
1491Requires Boost packages from packages.icinga.com.
1492
1493```bash
1494docker run -ti ubuntu:bionic bash
1495
1496apt-get update
1497apt-get -y install apt-transport-https wget gnupg
1498
1499wget -O - https://packages.icinga.com/icinga.key | apt-key add -
1500
1501. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \
1502 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST} main" > \
1503 /etc/apt/sources.list.d/${DIST}-icinga.list
1504 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST} main" >> \
1505 /etc/apt/sources.list.d/${DIST}-icinga.list
1506
1507apt-get update
1508```
1509
1510```bash
1511apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev bison flex default-libmysqlclient-dev libpq-dev libedit-dev monitoring-plugins
1512
1513apt-get install -y libboost1.67-icinga-all-dev
1514
1515ln -s /usr/bin/ccache /usr/local/bin/gcc
1516ln -s /usr/bin/ccache /usr/local/bin/g++
1517
1518groupadd icinga
1519groupadd icingacmd
1520useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga
1521
1522git clone https://github.com/icinga/icinga2.git && cd icinga2
1523
1524mkdir debug release
1525
1526export I2_DEB="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib/x86_64-linux-gnu/icinga-boost -DBOOST_INCLUDEDIR=/usr/include/icinga-boost -DCMAKE_INSTALL_RPATH=/usr/lib/x86_64-linux-gnu/icinga-boost"
1527export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin"
1528export I2_DEBUG="$I2_DEB $I2_GENERIC -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF"
1529
1530cd debug
1531cmake .. $I2_DEBUG
1532cd ..
1533```
1534
1535```bash
1536make -j2 install -C debug
1537```
1538
1539The source installation doesn't set proper permissions, this is
1540handled in the package builds which are officially supported.
1541
1542```bash
1543chown -R icinga:icinga /usr/local/icinga2/var/
1544
1545/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2
1546/usr/local/icinga2/sbin/icinga2 api setup
1547vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf
1548
1549/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon
1550```
1551
1552### macOS Dev Environment <a id="development-macos-dev-env"></a>
1553
1554It is advised to use Homebrew to install required build dependencies.
1555Macports have been reported to work as well, typically you'll get more help
1556with Homebrew from Icinga developers.
1557
1558The idea is to run Icinga with the current user, avoiding root permissions.
1559This requires at least v2.11.
1560
1561> **Note**
1562>
1563> This is a pure development setup for Icinga developers reducing the compile
1564> time in contrast to VMs. There are no packages, startup scripts or dependency management involved.
1565>
1566> **macOS agents are not officially supported.**
1567>
1568> macOS uses its own TLS implementation, Icinga relies on extra OpenSSL packages
1569> requiring updates apart from vendor security updates.
1570
1571#### Requirements
1572
1573Explicitly use OpenSSL 1.1.x, older versions are out of support.
1574
1575```bash
1576brew install ccache boost cmake bison flex openssl@1.1 mysql-connector-c++ postgresql libpq
1577```
1578
1579##### ccache
1580
1581```bash
1582sudo mkdir /opt/ccache
1583
1584sudo ln -s `which ccache` /opt/ccache/clang
1585sudo ln -s `which ccache` /opt/ccache/clang++
1586
1587vim $HOME/.bash_profile
1588
1589# ccache is managed with symlinks to avoid collision with cgo
1590export PATH="/opt/ccache:$PATH"
1591
1592source $HOME/.bash_profile
1593```
1594
1595#### Builds
1596
1597Icinga is built as release (optimized build for packages) and debug (more symbols and details for debugging). Debug builds
1598typically run slower than release builds and must not be used for performance benchmarks.
1599
1600The preferred installation prefix is `/usr/local/icinga/icinga2`. This allows to put e.g. Icinga Web 2 into the `/usr/local/icinga` directory as well.
1601
1602```bash
1603mkdir -p release debug
1604
1605export I2_USER=$(id -u -n)
1606export I2_GROUP=$(id -g -n)
1607export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga/icinga2 -DICINGA2_USER=$I2_USER -DICINGA2_GROUP=$I2_GROUP -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib -DICINGA2_PLUGINDIR=/usr/local/sbin -DICINGA2_WITH_PGSQL=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
1608export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC"
1609export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC"
1610
1611cd debug
1612cmake $I2_DEBUG ..
1613cd ..
1614
1615make -j4 -C debug
1616make -j4 install -C debug
1617```
1618
1619In order to run Icinga without any path prefix, and also use Bash completion it is advised to source additional
1620things into the local dev environment.
1621
1622```bash
1623export PATH=/usr/local/icinga/icinga2/sbin/:$PATH
1624
1625test -f /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 && source /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2
1626```
1627
1628##### Build Aliases
1629
1630This is derived from [dnsmichi's flavour](https://github.com/dnsmichi/dotfiles) and not generally best practice.
1631
1632```bash
1633vim $HOME/.bash_profile
1634
1635export I2_USER=$(id -u -n)
1636export I2_GROUP=$(id -g -n)
1637export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga/icinga2 -DICINGA2_USER=$I2_USER -DICINGA2_GROUP=$I2_GROUP -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib -DICINGA2_PLUGINDIR=/usr/local/sbin -DICINGA2_WITH_PGSQL=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
1638
1639export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC"
1640export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC"
1641
1642alias i2_debug="mkdir -p debug; cd debug; cmake $I2_DEBUG ..; make -j4; make -j4 install; cd .."
1643alias i2_release="mkdir -p release; cd release; cmake $I2_RELEASE ..; make -j4; make -j4 install; cd .."
1644
1645export PATH=/usr/local/icinga/icinga2/sbin/:$PATH
1646test -f /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 && source /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2
1647
1648
1649source $HOME/.bash_profile
1650```
1651
1652#### Permissions
1653
1654`make install` doesn't set all required permissions, override this.
1655
1656```bash
1657chown -R $I2_USER:$I2_GROUP /usr/local/icinga/icinga2
1658```
1659
1660#### Run
1661
1662Start Icinga in foreground.
1663
1664```bash
1665icinga2 daemon
1666```
1667
1668Reloads triggered with HUP or cluster syncs just put the process into background.
1669
1670#### Plugins
1671
1672```bash
1673brew install monitoring-plugins
1674
1675sudo vim /usr/local/icinga/icinga2/etc/icinga2/constants.conf
1676```
1677
1678```
1679const PluginDir = "/usr/local/sbin"
1680```
1681
1682#### Backends: Redis
1683
1684```bash
1685brew install redis
1686brew services start redis
1687```
1688
1689#### Databases: MariaDB
1690
1691```bash
1692brew install mariadb
1693mkdir -p /usr/local/etc/my.cnf.d
1694brew services start mariadb
1695
1696mysql_secure_installation
1697```
1698
1699```
1700vim $HOME/.my.cnf
1701
1702[client]
1703user = root
1704password = supersecurerootpassword
1705
1706sudo -i
1707ln -s /Users/michi/.my.cnf $HOME/.my.cnf
1708exit
1709```
1710
1711```bash
1712mysql -e 'create database icinga;'
1713mysql -e "grant all on icinga.* to 'icinga'@'localhost' identified by 'icinga';"
1714mysql icinga < $HOME/dev/icinga/icinga2/lib/db_ido_mysql/schema/mysql.sql
1715```
1716
1717#### API
1718
1719```bash
1720icinga2 api setup
1721cd /usr/local/icinga/icinga2/var/lib/icinga2/certs
1722HOST_NAME=mbpmif.int.netways.de
1723icinga2 pki new-cert --cn ${HOST_NAME} --csr ${HOST_NAME}.csr --key ${HOST_NAME}.key
1724icinga2 pki sign-csr --csr ${HOST_NAME}.csr --cert ${HOST_NAME}.crt
1725echo "const NodeName = \"${HOST_NAME}\"" >> /usr/local/icinga/icinga2/etc/icinga2/constants.conf
1726```
1727
1728#### Web
1729
1730While it is recommended to use Docker or the Icinga Web 2 development VM pointing to the shared IDO database resource/REST API, you can also install it locally on macOS.
1731
1732The required steps are described in [this script](https://github.com/dnsmichi/dotfiles/blob/master/icingaweb2.sh).
1733
1734
1735
1736### Windows Dev Environment <a id="development-windows-dev-env"></a>
1737
1738The following sections explain how to setup the required build tools
1739and how to run and debug the code.
1740
1741#### TL;DR
1742
1743If you're going to setup a dev environment on a fresh Windows machine
1744and don't care for the details,
1745
17461. ensure there are 35 GB free space on C:
17472. run the following in an administrative Powershell:
1748  1. `Enable-WindowsOptionalFeature -FeatureName "NetFx3" -Online`
1749     (reboot when asked!)
1750  2. `powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-Expression (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/Icinga/icinga2/master/doc/win-dev.ps1')"`
1751    (will take some time)
1752
1753This installs everything needed for cloning and building Icinga 2
1754on the command line (Powershell) as follows:
1755
1756(Don't forget to open a new Powershell window
1757to be able to use the newly installed Git.)
1758
1759```
1760git clone https://github.com/Icinga/icinga2.git
1761cd .\icinga2\
1762mkdir build
1763cd .\build\
1764
1765& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" `
1766  -DBoost_INCLUDE_DIR=C:\local\boost_1_76_0-Win64 `
1767  -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_bison.exe `
1768  -DFLEX_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_flex.exe `
1769  -DICINGA2_WITH_MYSQL=OFF -DICINGA2_WITH_PGSQL=OFF ..
1770
1771& "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" .\icinga2.sln
1772```
1773
1774Building icinga2.sln via Visual Studio itself seems to require a reboot
1775after installing the build tools and building once via command line.
1776
1777#### Chocolatey
1778
1779Open an administrative command prompt (Win key, type “cmd”, right-click and “run as administrator”) and paste the following instructions:
1780
1781```
1782@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
1783```
1784
1785#### Git, Posh and Vim
1786
1787In case you are used to `vim`, start a new administrative Powershell:
1788
1789```
1790choco install -y vim
1791```
1792
1793The same applies for Git integration in Powershell:
1794
1795```
1796choco install -y poshgit
1797```
1798
1799![Powershell Posh Git](images/development/windows_powershell_posh_git.png)
1800
1801In order to fix the colors for commands like `git status` or `git diff`,
1802edit `$HOME/.gitconfig` in your Powershell and add the following lines:
1803
1804```
1805vim $HOME/.gitconfig
1806
1807[color "status"]
1808    changed = cyan bold
1809    untracked = yellow bold
1810    added = green bold
1811    branch = cyan bold
1812    unmerged = red bold
1813
1814[color "diff"]
1815    frag = cyan
1816    new = green bold
1817    commit = yellow
1818    old = red white
1819
1820[color "branch"]
1821  current = yellow reverse
1822  local = yellow
1823  remote = green bold
1824  remote = red bold
1825```
1826
1827#### Visual Studio
1828
1829Thanks to Microsoft they’ll now provide their Professional Edition of Visual Studio
1830as community version, free for use for open source projects such as Icinga.
1831The installation requires ~9GB disk space. [Download](https://www.visualstudio.com/downloads/)
1832the web installer and start the installation.
1833
1834Note: Only Visual Studio 2019 is covered here. Older versions are not supported.
1835
1836You need a free Microsoft account to download and also store your preferences.
1837
1838Install the following complete workloads:
1839
1840* C++ Desktop Development
1841* .NET Desktop Development
1842
1843In addition also choose these individual components on Visual Studio:
1844
1845* .NET
1846    * .NET Framework 4.x targeting packs
1847    * .NET Framework 4.x.y SDKs
1848* Code tools
1849    * Git for Windows
1850    * GitHub Extension for Visual Studio
1851    * NuGet package manager
1852* Compilers, build tools and runtimes
1853    * C# and Visual Basic Roslyn compilers
1854    * C++ 2019 Redistributable Update
1855    * C++ CMake tools for Windows
1856    * C++/CLI Support for v142 build tools (14.22)
1857    * MSBuild
1858    * MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.22)
1859* Debugging and testing
1860    * .NET profiling tools
1861    * C++ profiling tools
1862    * Just-in-Time debugger
1863* Development activities
1864    * C# and Visual Basic
1865    * C++ core features
1866    * IntelliCode
1867    * Live Share
1868* Games and Graphics
1869    * Graphics debugger and GPU profiler for DirectX (required by C++ profiling tools)
1870* SDKs, libraries and frameworks
1871    * Windows 10 SDK (10.0.18362.0 or later)
1872    * Windows Universal C Runtime
1873
1874![Visual Studio Installer](images/development/windows_visual_studio_installer_01.png)
1875![Visual Studio Installer](images/development/windows_visual_studio_installer_02.png)
1876![Visual Studio Installer](images/development/windows_visual_studio_installer_03.png)
1877
1878After a while, Visual Studio will be ready.
1879
1880##### Style Guide for Visual Studio
1881
1882Navigate into `Tools > Options > Text Editor` and repeat the following for
1883
1884- C++
1885- C#
1886
1887Navigate into `Tabs` and set:
1888
1889- Indenting: Smart (default)
1890- Tab size: 4
1891- Indent size: 4
1892- Keep tabs (instead of spaces)
1893
1894![Visual Studio Tabs](images/development/windows_visual_studio_tabs_c++.png)
1895
1896
1897#### Flex and Bison
1898
1899Install it using [chocolatey](https://www.wireshark.org/docs/wsdg_html_chunked/ChSetupWin32.html):
1900
1901```
1902choco install -y winflexbison
1903```
1904
1905Chocolatey installs these tools into the hidden directory `C:\ProgramData\chocolatey\lib\winflexbison\tools`.
1906
1907#### OpenSSL
1908
1909Icinga 2 requires the OpenSSL library. [Download](https://slproweb.com/products/Win32OpenSSL.html) the Win64 package
1910and install it into `c:\local\OpenSSL-Win64`.
1911
1912Once asked for `Copy OpenSSLs DLLs to` select `The Windows system directory`. That way CMake/Visual Studio
1913will automatically detect them for builds and packaging.
1914
1915> **Note**
1916>
1917> We cannot use the chocolatey package as this one does not provide any development headers.
1918>
1919> Choose 1.1.1 LTS from manual downloads for best compatibility.
1920
1921#### Boost
1922
1923Icinga needs the development header and library files from the Boost library.
1924
1925Visual Studio translates into the following compiler versions:
1926
1927- `msvc-14.2` = Visual Studio 2019
1928
1929##### Pre-built Binaries
1930
1931Prefer the pre-built package over self-compiling, if the newest version already exists.
1932
1933Download the [boost-binaries](https://sourceforge.net/projects/boost/files/boost-binaries/) for
1934
1935- msvc-14.2 is Visual Studio 2019
1936- 64 for 64 bit builds
1937
1938```
1939https://sourceforge.net/projects/boost/files/boost-binaries/1.76.0/boost_1_76_0-msvc-14.2-64.exe/download
1940```
1941
1942Run the installer and leave the default installation path in `C:\local\boost_1_76_0`.
1943
1944
1945##### Source & Compile
1946
1947In order to use the boost development header and library files you need to [download](https://www.boost.org/users/download/)
1948Boost and then extract it to e.g. `C:\local\boost_1_76_0`.
1949
1950> **Note**
1951>
1952> Just use `C:\local`, the zip file already contains the sub folder. Extraction takes a while,
1953> the archive contains more than 70k files.
1954
1955In order to integrate Boost into Visual Studio, open the `Developer Command Prompt` from the start menu,
1956and navigate to `C:\local\boost_1_76_0`.
1957
1958Execute `bootstrap.bat` first.
1959
1960```
1961cd C:\local\boost_1_76_0
1962bootstrap.bat
1963```
1964
1965Once finished, specify the required `toolset` to compile boost against Visual Studio.
1966This takes quite some time in a Windows VM. Boost Context uses Assembler code,
1967which isn't treated as exception safe by the VS compiler. Therefore set the
1968additional compilation flag according to [this entry](https://lists.boost.org/Archives/boost/2015/08/224570.php).
1969
1970```
1971b2 --toolset=msvc-14.2 link=static threading=multi runtime-link=static address-model=64 asmflags=\safeseh
1972```
1973
1974![Windows Boost Build in VS Development Console](images/development/windows_boost_build_dev_cmd.png)
1975
1976#### TortoiseGit
1977
1978TortoiseGit provides a graphical integration into the Windows explorer. This makes it easier to checkout, commit
1979and whatnot.
1980
1981[Download](https://tortoisegit.org/download/) TortoiseGit on your system.
1982
1983In order to clone via Git SSH you also need to create a new directory called `.ssh`
1984inside your user's home directory.
1985Therefore open a command prompt (win key, type `cmd`, enter) and run `mkdir .ssh`.
1986Add your `id_rsa` private key and `id_rsa.pub` public key files into that directory.
1987
1988Start the setup routine and choose `OpenSSH` as default secure transport when asked.
1989
1990Open a Windows Explorer window and navigate into
1991
1992```
1993cd %HOMEPATH%\source\repos
1994```
1995
1996Right click and select `Git Clone` from the context menu.
1997
1998Use `ssh://git@github.com/icinga/icinga2.git` for SSH clones, `https://github.com/icinga/icinga2.git` otherwise.
1999
2000#### Packages
2001
2002CMake uses CPack and NSIS to create the setup executable including all binaries and libraries
2003in addition to setup dialogues and configuration. Therefore we’ll need to install [NSIS](http://nsis.sourceforge.net/Download)
2004first.
2005
2006We also need to install the Windows Installer XML (WIX) toolset. This has .NET 3.5 as a dependency which might need a
2007reboot of the system which is not handled properly by Chocolatey. Therefore install it first and reboot when asked.
2008
2009```
2010Enable-WindowsOptionalFeature -FeatureName "NetFx3" -Online
2011choco install -y wixtoolset
2012```
2013
2014#### CMake
2015
2016Icinga 2 uses CMake to manage the build environment. You can generate the Visual Studio project files
2017using CMake. [Download](https://cmake.org/download/) and install CMake. Select to add it to PATH for all users
2018when asked.
2019
2020> **Note**
2021>
2022> In order to properly detect the Boost libraries and VS 2019, install CMake 3.15.2+.
2023>
2024> **Tip**
2025>
2026> Cheatsheet: https://www.brianlheim.com/2018/04/09/cmake-cheat-sheet.html
2027
2028Once setup is completed, open a command prompt and navigate to
2029
2030```
2031cd %HOMEPATH%\source\repos
2032```
2033
2034Build Icinga with specific CMake variables. This generates a new Visual Studio project file called `icinga2.sln`.
2035
2036Visual Studio translates into the following:
2037
2038- `msvc-14.2` = Visual Studio 2019
2039
2040You need to specify the previously installed component paths.
2041
2042Variable              | Value                                                                | Description
2043----------------------|----------------------------------------------------------------------|-------------------------------------------------------
2044`BOOST_ROOT`          | `C:\local\boost_1_76_0`                                                    | Root path where you've extracted and compiled Boost.
2045`BOOST_LIBRARYDIR`    | Binary: `C:\local\boost_1_76_0\lib64-msvc-14.2`, Source: `C:\local\boost_1_76_0\stage` | Path to the static compiled Boost libraries, directory must contain `lib`.
2046`BISON_EXECUTABLE`    | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe`     | Path to the Bison executable.
2047`FLEX_EXECUTABLE`     | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe`      | Path to the Flex executable.
2048`ICINGA2_WITH_MYSQL`  | OFF                                                                  | Requires extra setup for MySQL if set to `ON`. Not supported for client setups.
2049`ICINGA2_WITH_PGSQL`  | OFF                                                                  | Requires extra setup for PgSQL if set to `ON`. Not supported for client setups.
2050`ICINGA2_UNITY_BUILD` | OFF                                                                  | Disable unity builds for development environments.
2051
2052Tip: If you have previously opened a terminal, run `refreshenv` to re-read updated PATH variables.
2053
2054##### Build Scripts
2055
2056Icinga provides the build scripts inside the Git repository.
2057
2058Open a new Powershell and navigate into the cloned Git repository. Set
2059specific environment variables and run the build scripts.
2060
2061```
2062cd %HOMEPATH%\source\repos\icinga2
2063
2064.\tools\win32\configure-dev.ps1
2065.\tools\win32\build.ps1
2066.\tools\win32\test.ps1
2067```
2068
2069The debug MSI package is located in the `debug` directory.
2070
2071If you did not follow the above steps with Boost binaries and OpenSSL
2072paths, you can still modify the environment variables.
2073
2074```
2075$env:CMAKE_GENERATOR='Visual Studio 16 2019'
2076$env:CMAKE_GENERATOR_PLATFORM='x64'
2077
2078$env:ICINGA2_INSTALLPATH = 'C:\Program Files\Icinga2-debug'
2079$env:ICINGA2_BUILDPATH='debug'
2080$env:CMAKE_BUILD_TYPE='Debug'
2081$env:OPENSSL_ROOT_DIR='C:\OpenSSL-Win64'
2082$env:BOOST_ROOT='C:\local\boost_1_76_0'
2083$env:BOOST_LIBRARYDIR='C:\local\boost_1_76_0\lib64-msvc-14.2'
2084```
2085
2086#### Icinga 2 in Visual Studio
2087
2088This requires running the configure script once.
2089
2090Navigate to
2091
2092```
2093cd %HOMEPATH%\source\repos\icinga2\debug
2094```
2095
2096Open `icinga2.sln`. Log into Visual Studio when asked.
2097
2098On the right panel, select to build the `Bin/icinga-app` solution.
2099
2100The executable binaries are located in `Bin\Release\Debug` in your `icinga2`
2101project directory.
2102
2103Navigate there and run `icinga2.exe --version`.
2104
2105```
2106cd %HOMEPATH%\source\repos\icinga2\Bin\Release\Debug
2107icinga2.exe --version
2108```
2109
2110
2111#### Release Package
2112
2113This is part of the build process script. Override the build type and pick a different
2114build directory.
2115
2116```
2117cd %HOMEPATH%\source\repos\icinga2
2118
2119$env:ICINGA2_BUILDPATH='release'
2120$env:CMAKE_BUILD_TYPE='RelWithDebInfo'
2121
2122.\tools\win32\configure-dev.ps1
2123.\tools\win32\build.ps1
2124.\tools\win32\test.ps1
2125```
2126
2127The release MSI package is located in the `release` directory.
2128
2129
2130### Embedded Dev Env: Pi <a id="development-embedded-dev-env"></a>
2131
2132> **Note**
2133>
2134> This isn't officially supported yet, just a few hints how you can do it yourself.
2135
2136The following examples source from armhf on Raspberry Pi.
2137
2138#### ccache
2139
2140```bash
2141apt install -y ccache
2142
2143/usr/sbin/update-ccache-symlinks
2144
2145echo 'export PATH="/usr/lib/ccache:$PATH"' | tee -a ~/.bashrc
2146
2147source ~/.bashrc && echo $PATH
2148```
2149
2150#### Build
2151
2152Copy the icinga2 source code into `$HOME/icinga2`. Clone the `deb-icinga2` repository into `debian/`.
2153
2154```bash
2155git clone https://github.com/Icinga/icinga2 $HOME/icinga2
2156git clone https://github.com/Icinga/deb-icinga2 $HOME/icinga2/debian
2157```
2158
2159Then build a Debian package and install it like normal.
2160
2161```bash
2162dpkg-buildpackage -uc -us
2163```
2164
2165## Package Builds <a id="development-package-builds"></a>
2166
2167This documentation is explicitly meant for packagers and the Icinga
2168build infrastructure.
2169
2170The following requirements need to be fulfilled in order to build the
2171Icinga application using a dist tarball (including notes for distributions):
2172
2173* cmake >= 2.6
2174* GNU make (make) or ninja-build
2175* C++ compiler which supports C++11
2176    * RHEL/Fedora/SUSE: gcc-c++ >= 4.7 (extra Developer Tools on RHEL5/6 see below)
2177    * Debian/Ubuntu: build-essential
2178    * Alpine: build-base
2179    * you can also use clang++
2180* pkg-config
2181* OpenSSL library and header files >= 1.0.1
2182    * RHEL/Fedora: openssl-devel
2183    * SUSE: libopenssl-devel
2184    * Debian/Ubuntu: libssl-dev
2185    * Alpine: libressl-dev
2186* Boost library and header files >= 1.66.0
2187    * RHEL/Fedora: boost166-devel
2188    * Debian/Ubuntu: libboost-all-dev
2189    * Alpine: boost-dev
2190* GNU bison (bison)
2191* GNU flex (flex) >= 2.5.35
2192* systemd headers
2193    * Only required when using systemd
2194    * Debian/Ubuntu: libsystemd-dev
2195    * RHEL/Fedora: systemd-devel
2196
2197### Optional features <a id="development-package-builds-optional-features"></a>
2198
2199* MySQL (disable with CMake variable `ICINGA2_WITH_MYSQL` to `OFF`)
2200    * RHEL/Fedora: mysql-devel
2201    * SUSE: libmysqlclient-devel
2202    * Debian/Ubuntu: default-libmysqlclient-dev | libmysqlclient-dev
2203    * Alpine: mariadb-dev
2204* PostgreSQL (disable with CMake variable `ICINGA2_WITH_PGSQL` to `OFF`)
2205    * RHEL/Fedora: postgresql-devel
2206    * Debian/Ubuntu: libpq-dev
2207    * postgresql-dev on Alpine
2208* libedit (CLI console)
2209    * RHEL/Fedora: libedit-devel on CentOS (RHEL requires rhel-7-server-optional-rpms)
2210    * Debian/Ubuntu/Alpine: libedit-dev
2211* Termcap (only required if libedit doesn't already link against termcap/ncurses)
2212    * RHEL/Fedora: libtermcap-devel
2213    * Debian/Ubuntu: (not necessary)
2214
2215### Special requirements <a id="development-package-builds-special-requirements"></a>
2216
2217**FreeBSD**: libexecinfo (automatically used when Icinga 2 is installed via port or package)
2218
2219**RHEL6**: Requires a newer boost version which is available on packages.icinga.com
2220with a version suffixed name.
2221
2222### Runtime user environment <a id="development-package-builds-runtime-user-env"></a>
2223
2224By default Icinga will run as user `icinga` and group `icinga`. Additionally the
2225external command pipe and livestatus features require a dedicated command group
2226`icingacmd`. You can choose your own user/group names and pass them to CMake
2227using the `ICINGA2_USER`, `ICINGA2_GROUP` and `ICINGA2_COMMAND_GROUP` variables.
2228
2229```bash
2230groupadd icinga
2231groupadd icingacmd
2232useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga
2233```
2234
2235On Alpine (which uses ash busybox) you can run:
2236
2237```bash
2238addgroup -S icinga
2239addgroup -S icingacmd
2240adduser -S -D -H -h /var/spool/icinga2 -s /sbin/nologin -G icinga -g icinga icinga
2241adduser icinga icingacmd
2242```
2243
2244Add the web server user to the icingacmd group in order to grant it write
2245permissions to the external command pipe and livestatus socket:
2246
2247```bash
2248usermod -a -G icingacmd www-data
2249```
2250
2251Make sure to replace "www-data" with the name of the user your web server
2252is running as.
2253
2254### Building Icinga 2: Example <a id="development-package-builds-example"></a>
2255
2256Once you have installed all the necessary build requirements you can build
2257Icinga 2 using the following commands:
2258
2259```bash
2260mkdir release && cd release
2261cmake ..
2262cd ..
2263make -C release
2264make install -C release
2265```
2266
2267You can specify an alternative installation prefix using `-DCMAKE_INSTALL_PREFIX`:
2268
2269```bash
2270cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/icinga2
2271```
2272
2273### CMake Variables <a id="development-package-builds-cmake-variables"></a>
2274
2275In addition to `CMAKE_INSTALL_PREFIX` here are most of the supported Icinga-specific cmake variables.
2276
2277For all variables regarding defaults paths on in CMake, see
2278[GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html).
2279
2280Also see `CMakeLists.txt` for details.
2281
2282#### System Environment
2283
2284* `CMAKE_INSTALL_SYSCONFDIR`: The configuration directory; defaults to `CMAKE_INSTALL_PREFIX/etc`
2285* `CMAKE_INSTALL_LOCALSTATEDIR`: The state directory; defaults to `CMAKE_INSTALL_PREFIX/var`
2286* `ICINGA2_CONFIGDIR`: Main config directory; defaults to `CMAKE_INSTALL_SYSCONFDIR/icinga2` usually `/etc/icinga2`
2287* `ICINGA2_CACHEDIR`: Directory for cache files; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/cache/icinga2` usually `/var/cache/icinga2`
2288* `ICINGA2_DATADIR`: Data directory  for the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/lib/icinga2` usually `/var/lib/icinga2`
2289* `ICINGA2_LOGDIR`: Logfiles of the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/log/icinga2 usually `/var/log/icinga2`
2290* `ICINGA2_SPOOLDIR`: Spooling directory ; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/spool/icinga2` usually `/var/spool/icinga2`
2291* `ICINGA2_INITRUNDIR`: Runtime data for the init system; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/run/icinga2` usually `/run/icinga2`
2292* `ICINGA2_GIT_VERSION_INFO`: Whether to use Git to determine the version number; defaults to `ON`
2293* `ICINGA2_USER`: The user Icinga 2 should run as; defaults to `icinga`
2294* `ICINGA2_GROUP`: The group Icinga 2 should run as; defaults to `icinga`
2295* `ICINGA2_COMMAND_GROUP`: The command group Icinga 2 should use; defaults to `icingacmd`
2296* `ICINGA2_SYSCONFIGFILE`: Where to put the config file the initscript/systemd pulls it's dirs from;
2297* defaults to `CMAKE_INSTALL_PREFIX/etc/sysconfig/icinga2`
2298* `ICINGA2_PLUGINDIR`: The path for the Monitoring Plugins project binaries; defaults to `/usr/lib/nagios/plugins`
2299
2300#### Build Optimization
2301
2302* `ICINGA2_UNITY_BUILD`: Whether to perform a unity build; defaults to `ON`. Note: This requires additional memory and is not advised for building VMs, Docker for Mac and embedded hardware.
2303* `ICINGA2_LTO_BUILD`: Whether to use link time optimization (LTO); defaults to `OFF`
2304
2305#### Init System
2306
2307* `USE_SYSTEMD=ON|OFF`: Use systemd or a classic SysV initscript; defaults to `OFF`
2308* `INSTALL_SYSTEMD_SERVICE_AND_INITSCRIPT=ON|OFF` Force install both the systemd service definition file
2309  and the SysV initscript in parallel, regardless of how `USE_SYSTEMD` is set.
2310  Only use this for special packaging purposes and if you know what you are doing.
2311  Defaults to `OFF`.
2312
2313#### Features
2314
2315* `ICINGA2_WITH_CHECKER`: Determines whether the checker module is built; defaults to `ON`
2316* `ICINGA2_WITH_COMPAT`: Determines whether the compat module is built; defaults to `ON`
2317* `ICINGA2_WITH_LIVESTATUS`: Determines whether the Livestatus module is built; defaults to `ON`
2318* `ICINGA2_WITH_NOTIFICATION`: Determines whether the notification module is built; defaults to `ON`
2319* `ICINGA2_WITH_PERFDATA`: Determines whether the perfdata module is built; defaults to `ON`
2320* `ICINGA2_WITH_TESTS`: Determines whether the unit tests are built; defaults to `ON`
2321
2322#### MySQL or MariaDB
2323
2324The following settings can be tuned for the MySQL / MariaDB IDO feature.
2325
2326* `ICINGA2_WITH_MYSQL`: Determines whether the MySQL IDO module is built; defaults to `ON`
2327* `MYSQL_CLIENT_LIBS`: Client implementation used (mysqlclient / mariadbclient); defaults searches for `mysqlclient` and `mariadbclient`
2328* `MYSQL_INCLUDE_DIR`: Directory containing include files for the mysqlclient; default empty -
2329  checking multiple paths like `/usr/include/mysql`
2330
2331See [FindMySQL.cmake](https://github.com/Icinga/icinga2/blob/master/third-party/cmake/FindMySQL.cmake)
2332for implementation details.
2333
2334#### PostgreSQL
2335
2336The following settings can be tuned for the PostgreSQL IDO feature.
2337
2338* `ICINGA2_WITH_PGSQL`: Determines whether the PostgreSQL IDO module is built; defaults to `ON`
2339* `PostgreSQL_INCLUDE_DIR`: Top-level directory containing the PostgreSQL include directories
2340* `PostgreSQL_LIBRARY`: File path to PostgreSQL library : libpq.so (or libpq.so.[ver] file)
2341
2342See [FindPostgreSQL.cmake](https://github.com/Icinga/icinga2/blob/master/third-party/cmake/FindPostgreSQL.cmake)
2343for implementation details.
2344
2345#### Version detection
2346
2347CMake determines the Icinga 2 version number using `git describe` if the
2348source directory is contained in a Git repository. Otherwise the version number
2349is extracted from the [ICINGA2_VERSION](ICINGA2_VERSION) file. This behavior can be
2350overridden by creating a file called `icinga-version.h.force` in the source
2351directory. Alternatively the `-DICINGA2_GIT_VERSION_INFO=OFF` option for CMake
2352can be used to disable the usage of `git describe`.
2353
2354
2355### Building RPMs <a id="development-package-builds-rpms"></a>
2356
2357#### Build Environment on RHEL, CentOS, Fedora, Amazon Linux
2358
2359Setup your build environment:
2360
2361```bash
2362yum -y install rpmdevtools
2363```
2364
2365#### Build Environment on SuSE/SLES
2366
2367SLES:
2368
2369```bash
2370zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP4/devel:tools.repo
2371zypper refresh
2372zypper install rpmdevtools spectool
2373```
2374
2375OpenSuSE:
2376
2377```bash
2378zypper addrepo http://download.opensuse.org/repositories/devel:tools/openSUSE_Leap_15.0/devel:tools.repo
2379zypper refresh
2380zypper install rpmdevtools spectool
2381```
2382
2383#### Package Builds <a id="development-package-builds-rpms-package-builds"></a>
2384
2385Prepare the rpmbuild directory tree:
2386
2387```bash
2388cd $HOME
2389rpmdev-setuptree
2390```
2391
2392Snapshot builds:
2393
2394```bash
2395curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o $HOME/rpmbuild/SPECS/icinga2.spec
2396```
2397
2398> **Note**
2399>
2400> The above command builds snapshot packages. Change to the `release` branch
2401> for release package builds.
2402
2403Copy the tarball to `rpmbuild/SOURCES` e.g. by using the `spectool` binary
2404provided with `rpmdevtools`:
2405
2406```bash
2407cd $HOME/rpmbuild/SOURCES
2408spectool -g ../SPECS/icinga2.spec
2409
2410cd $HOME/rpmbuild
2411```
2412
2413Install the build dependencies. Example for CentOS 7:
2414
2415```bash
2416yum -y install libedit-devel ncurses-devel gcc-c++ libstdc++-devel openssl-devel \
2417cmake flex bison boost-devel systemd mysql-devel postgresql-devel httpd \
2418selinux-policy-devel checkpolicy selinux-policy selinux-policy-doc
2419```
2420
2421Note: If you are using Amazon Linux, systemd is not required.
2422
2423A shorter way is available using the `yum-builddep` command on RHEL based systems:
2424
2425```bash
2426yum-builddep SPECS/icinga2.spec
2427```
2428
2429Build the RPM:
2430
2431```bash
2432rpmbuild -ba SPECS/icinga2.spec
2433```
2434
2435#### Additional Hints <a id="development-package-builds-rpms-additional-hints"></a>
2436
2437##### SELinux policy module
2438
2439The following packages are required to build the SELinux policy module:
2440
2441* checkpolicy
2442* selinux-policy (selinux-policy on CentOS 6, selinux-policy-devel on CentOS 7)
2443* selinux-policy-doc
2444
2445##### RHEL/CentOS 6
2446
2447The RedHat Developer Toolset is required for building Icinga 2 beforehand.
2448This contains a modern version of flex and a C++ compiler which supports
2449C++11 features.
2450
2451```bash
2452cat >/etc/yum.repos.d/devtools-2.repo <<REPO
2453[testing-devtools-2-centos-\$releasever]
2454name=testing 2 devtools for CentOS $releasever
2455baseurl=https://people.centos.org/tru/devtools-2/\$releasever/\$basearch/RPMS
2456gpgcheck=0
2457REPO
2458```
2459
2460Dependencies to devtools-2 are used in the RPM SPEC, so the correct tools
2461should be used for building.
2462
2463As an alternative, you can use newer Boost packages provided on
2464[packages.icinga.com](https://packages.icinga.com/epel).
2465
2466```bash
2467cat >$HOME/.rpmmacros <<MACROS
2468%build_icinga_org 1
2469MACROS
2470```
2471
2472##### Amazon Linux
2473
2474If you prefer to build packages offline, a suitable Vagrant box is located
2475[here](https://atlas.hashicorp.com/mvbcoding/boxes/awslinux/).
2476
2477### Build Debian/Ubuntu packages <a id="development-package-builds-deb"></a>
2478
2479Setup your build environment on Debian/Ubuntu, copy the 'debian' directory from
2480the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2)
2481into your source tree and run the following command:
2482
2483```bash
2484dpkg-buildpackage -uc -us
2485```
2486
2487### Build Alpine Linux packages <a id="development-package-builds-alpine"></a>
2488
2489A simple way to setup a build environment is installing Alpine in a chroot.
2490In this way, you can set up an Alpine build environment in a chroot under a
2491different Linux distro.
2492There is a script that simplifies these steps with just two commands, and
2493can be found [here](https://github.com/alpinelinux/alpine-chroot-install).
2494
2495Once the build environment is installed, you can setup the system to build
2496the packages by following [this document](https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package).
2497
2498### Build Post Install Tasks <a id="development-package-builds-post-install-tasks"></a>
2499
2500After building Icinga 2 yourself, your package build system should at least run the following post
2501install requirements:
2502
2503* enable the `checker`, `notification` and `mainlog` feature by default
2504* run 'icinga2 api setup' in order to enable the `api` feature and generate TLS certificates for the node
2505
2506### Run Icinga 2 <a id="development-package-builds-run-icinga"></a>
2507
2508Icinga 2 comes with a binary that takes care of loading all the relevant
2509components (e.g. for check execution, notifications, etc.):
2510
2511```
2512icinga2 daemon
2513
2514[2016-12-08 16:44:24 +0100] information/cli: Icinga application loader (version: v2.5.4-231-gb10a6b7; debug)
2515[2016-12-08 16:44:24 +0100] information/cli: Loading configuration file(s).
2516[2016-12-08 16:44:25 +0100] information/ConfigItem: Committing config item(s).
2517...
2518```
2519
2520#### Init Script <a id="development-package-builds-init-script"></a>
2521
2522Icinga 2 can be started as a daemon using the provided init script:
2523
2524```
2525/etc/init.d/icinga2
2526Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status}
2527```
2528
2529#### Systemd <a id="development-package-builds-systemd"></a>
2530
2531If your distribution uses systemd:
2532
2533```
2534systemctl {start|stop|reload|status|enable|disable} icinga2
2535```
2536
2537In case the distribution is running systemd >227, you'll also
2538need to package and install the `etc/initsystem/icinga2.service.limits.conf`
2539file into `/etc/systemd/system/icinga2.service.d`.
2540
2541#### openrc <a id="development-package-builds-openrc"></a>
2542
2543Or if your distribution uses openrc (like Alpine):
2544
2545```
2546rc-service icinga2
2547Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status}
2548```
2549
2550Note: the openrc's init.d is not shipped by default.
2551A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup.
2552Those few steps can be followed:
2553
2554```bash
2555wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd
2556mv icinga2.initd /etc/init.d/icinga2
2557chmod +x /etc/init.d/icinga2
2558```
2559
2560Icinga 2 reads a single configuration file which is used to specify all
2561configuration settings (global settings, hosts, services, etc.). The
2562configuration format is explained in detail in the [doc/](doc/) directory.
2563
2564By default `make install` installs example configuration files in
2565`/usr/local/etc/icinga2` unless you have specified a different prefix or
2566sysconfdir.
2567
2568
2569### Windows Builds <a id="development-package-builds-windows"></a>
2570
2571The Windows MSI packages are located at https://packages.icinga.com/windows/
2572
2573The build infrastructure is based on GitLab CI and an Ansible provisioned
2574Windows VM running in OpenStack.
2575
2576The runner uses the scripts located in `tools/win32` to configure, build
2577and test the packages. Uploading them to the package repository is a
2578separate step. For manual package creation, please refer to [this chapter](21-development.md#development-windows-dev-env).
2579
2580![Windows build pipeline in GitLab](images/development/windows_builds_gitlab_pipeline.png)
2581
2582
2583## Continuous Integration <a id="development-ci"></a>
2584
2585Icinga uses the integrated CI capabilities on GitHub in the development workflow.
2586This ensures that incoming pull requests and branches are built on create/push events.
2587Contributors and developers can immediately see whether builds fail or succeed and
2588help the final reviews.
2589
2590* For Linux, we are currently using Travis CI.
2591* For Windows, AppVeyor has been integrated.
2592
2593Future plans involve making use of GitHub Actions.
2594
2595In addition to our development platform on GitHub,
2596we are using GitLab's CI platform to build binary packages for
2597all supported operating systems and distributions.
2598These CI pipelines provide even more detailed insights into
2599specific platform failures and developers can react faster.
2600
2601### CI: Travis CI
2602
2603[Travis CI](https://travis-ci.org/Icinga/icinga2) provides Ubuntu as base
2604distribution where Icinga is compiled from sources followed by running the
2605unit tests and a config validation check.
2606
2607For details, please refer to the [.travis.yml](https://github.com/Icinga/icinga2/blob/master/.travis.yml)
2608configuration file.
2609
2610### CI: AppVeyor
2611
2612[AppVeyor](https://ci.appveyor.com/project/icinga/icinga2) provides Windows
2613as platform where Visual Studio and Boost libraries come pre-installed.
2614
2615Icinga is built using the Powershell scripts located in `tools/win32`.
2616In addition to that, the unit tests are run.
2617
2618Please check the [appveyor.yml](https://github.com/Icinga/icinga2/blob/master/appveyor.yml) configuration
2619file for details.
2620
2621
2622## Advanced Development Tips <a id="development-advanced"></a>
2623
2624### GDB Pretty Printers <a id="development-advanced-gdb-pretty-printer"></a>
2625
2626Install the `boost`, `python` and `icinga2` pretty printers. Absolute paths are required,
2627so please make sure to update the installation paths accordingly (`pwd`).
2628
2629```bash
2630mkdir -p ~/.gdb_printers && cd ~/.gdb_printers
2631```
2632
2633Boost Pretty Printers compatible with Python 3:
2634
2635```
2636$ git clone https://github.com/mateidavid/Boost-Pretty-Printer.git && cd Boost-Pretty-Printer
2637$ git checkout python-3
2638$ pwd
2639/home/michi/.gdb_printers/Boost-Pretty-Printer
2640```
2641
2642Python Pretty Printers:
2643
2644```bash
2645cd ~/.gdb_printers
2646svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
2647```
2648
2649Icinga 2 Pretty Printers:
2650
2651```bash
2652mkdir -p ~/.gdb_printers/icinga2 && cd ~/.gdb_printers/icinga2
2653wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/icingadbg.py
2654```
2655
2656Now you'll need to modify/setup your `~/.gdbinit` configuration file.
2657You can download the one from Icinga 2 and modify all paths.
2658
2659Example on Fedora 22:
2660
2661```
2662$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/gdbinit -O ~/.gdbinit
2663$ vim ~/.gdbinit
2664
2665set print pretty on
2666
2667python
2668import sys
2669sys.path.insert(0, '/home/michi/.gdb_printers/icinga2')
2670from icingadbg import register_icinga_printers
2671register_icinga_printers()
2672end
2673
2674python
2675import sys
2676sys.path.insert(0, '/home/michi/.gdb_printers/python')
2677from libstdcxx.v6.printers import register_libstdcxx_printers
2678try:
2679    register_libstdcxx_printers(None)
2680except:
2681    pass
2682end
2683
2684python
2685import sys
2686sys.path.insert(0, '/home/michi/.gdb_printers/Boost-Pretty-Printer')
2687import boost_print
2688boost_print.register_printers()
2689end
2690```
2691
2692If you are getting the following error when running gdb, the `libstdcxx`
2693printers are already preloaded in your environment and you can remove
2694the duplicate import in your `~/.gdbinit` file.
2695
2696```
2697RuntimeError: pretty-printer already registered: libstdc++-v6
2698```
2699
2700