Skip to content
GitLab
Explore
Sign in
Register
Commits on Source (4)
New upstream version 2.9.2
· e36992a0
Bas Couwenberg
authored
Sep 28, 2018
e36992a0
Merge tag 'upstream/2.9.2'
· 505e0188
Bas Couwenberg
authored
Sep 28, 2018
Upstream version 2.9.2
505e0188
New upstream release.
· 4c44bb6f
Bas Couwenberg
authored
Sep 28, 2018
4c44bb6f
Set distribution to unstable.
· 4e5ea9e2
Bas Couwenberg
authored
Sep 28, 2018
4e5ea9e2
Show whitespace changes
Inline
Side-by-side
AUTHORS
View file @
4e5ea9e2
...
...
@@ -31,6 +31,7 @@ Christian Jonak <christian@jonak.org>
Christian Lehmann <christian_lehmann@gmx.de>
Christian Loos <cloos@netsandbox.de>
Christian Schmidt <github@chsc.dk>
Christopher Schirner <schinken@bamberg.ccc.de>
Claudio Bilotta <bilottalove@gmail.com>
Claudio Kuenzler <ck@claudiokuenzler.com>
Conrad Clement <cclement@printeron.com>
...
...
CHANGELOG.md
View file @
4e5ea9e2
# Icinga 2.x CHANGELOG
## 2.9.2 (2018-09-26)
### Enhancement
*
[
#6602
](
https://github.com/icinga/icinga2/issues/6602
)
(
API,
Cluster, PR): Improve TLS handshake exception logging
*
[
#6568
](
https://github.com/icinga/icinga2/issues/6568
)
(
Configuration,
PR): Ensure that config object types are committed in dependent load order
*
[
#6497
](
https://github.com/icinga/icinga2/issues/6497
)
(
Configuration,
PR): Improve error logging for match/regex/cidr
\_
match functions and unsupported dictionary usage
### Bug
*
[
#6596
](
https://github.com/icinga/icinga2/issues/6596
)
(
Crash,
PR): Fix crash on API queries with Fedora 28 hardening and GCC 8
*
[
#6581
](
https://github.com/icinga/icinga2/issues/6581
)
(
Configuration,
PR): Shuffle items before config validation
*
[
#6569
](
https://github.com/icinga/icinga2/issues/6569
)
(
DB
IDO): Custom Vars not updated after upgrade
*
[
#6533
](
https://github.com/icinga/icinga2/issues/6533
)
(
Crash
)
: Icinga2 crashes after using some api-commands on Fedora 28
*
[
#6505
](
https://github.com/icinga/icinga2/issues/6505
)
(
Cluster,
PR): Fix clusterzonecheck if not connected
*
[
#6498
](
https://github.com/icinga/icinga2/issues/6498
)
(
Configuration,
PR): Fix regression with MatchAny false conditions on match/regex/cidr
\_
match
*
[
#6496
](
https://github.com/icinga/icinga2/issues/6496
)
(
Configuration
)
: error with match and type matchany
### Documentation
*
[
#6590
](
https://github.com/icinga/icinga2/issues/6590
)
(
DB
IDO, Documentation, PR): Update workaround for custom vars
*
[
#6572
](
https://github.com/icinga/icinga2/issues/6572
)
(
Documentation,
PR): Add note about workaround for broken custom vars
### Support
*
[
#6540
](
https://github.com/icinga/icinga2/issues/6540
)
(
Configuration
)
: Evaluate a fixed config compiler commit order
*
[
#6486
](
https://github.com/icinga/icinga2/issues/6486
)
(
Configuration
)
: Configuration validation w/ ScheduledDowntimes performance decreased in 2.9
*
[
#6442
](
https://github.com/icinga/icinga2/issues/6442
)
(
Configuration
)
: Error while evaluating "assign where match" expression: std::bad
\_
cast
## 2.9.1 (2018-07-24)
### Bug
...
...
RELEASE.md
View file @
4e5ea9e2
...
...
@@ -26,7 +26,7 @@
Specify the release version.
```
VERSION=2.9.
0
VERSION=2.9.
2
```
Add your signing key to your Git configuration file, if not already there.
...
...
@@ -60,10 +60,11 @@ git log --use-mailmap | grep '^Author:' | cut -f2- -d' ' | sort | uniq > AUTHORS
## Version <a id="version"></a>
Update the version
in the version file
:
Update the version:
```
sed -i "s/Version: .*/Version: $VERSION/g" VERSION
sed -i "s/VERSION=.*/VERSION=$VERSION/g" RELEASE.md
```
## Changelog <a id="changelog"></a>
...
...
VERSION
View file @
4e5ea9e2
Version: 2.9.
1
Version: 2.9.
2
Revision: 1
debian/changelog
View file @
4e5ea9e2
icinga2 (2.9.
1-2) UNRELEASED
; urgency=medium
icinga2 (2.9.
2-1) unstable
; urgency=medium
* Team upload.
* New upstream release.
* Bump Standards-Version to 4.2.1, no changes.
-- Bas Couwenberg <sebastic@debian.org>
Sun, 05 Aug 2018 21:09:23
+0200
-- Bas Couwenberg <sebastic@debian.org>
Fri, 28 Sep 2018 07:32:37
+0200
icinga2 (2.9.1-1) unstable; urgency=medium
...
...
doc/16-upgrading-icinga-2.md
View file @
4e5ea9e2
...
...
@@ -97,6 +97,24 @@ With the removal of RHEL 5 as supported platform, we can finally use real unique
This is reflected in generating names for e.g. API stage names. Previously it was a handcrafted
mix of local FQDN, timestamps and random numbers.
### Custom Vars not updating <a id="upgrading-to-2-9-custom-vars-not-updating"></a>
A rare issue preventing the custom vars of objects created prior to 2.9.0 being updated when changed may occur. To
remedy this, truncate the customvar tables and restart Icinga 2. The following is an example of how to do this with mysql:
```
$ mysql -uroot -picinga icinga
MariaDB [icinga]> truncate icinga_customvariables;
Query OK, 0 rows affected (0.05 sec)
MariaDB [icinga]> truncate icinga_customvariablestatus;
Query OK, 0 rows affected (0.03 sec)
MariaDB [icinga]> exit
Bye
$ sudo systemctl restart icinga2
```
Custom vars should now stay up to date.
## Upgrading to v2.8.2 <a id="upgrading-to-2-8-2"></a>
...
...
lib/base/scriptutils.cpp
View file @
4e5ea9e2
...
...
@@ -108,10 +108,14 @@ bool ScriptUtils::CastBool(const Value& value)
bool
ScriptUtils
::
Regex
(
const
std
::
vector
<
Value
>&
args
)
{
if
(
args
.
size
()
<
2
)
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Regular expression and text must be specified."
));
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Regular expression and text must be specified
for regex()
."
));
String
pattern
=
args
[
0
];
const
Value
&
argTexts
=
args
[
1
];
if
(
argTexts
.
IsObjectType
<
Dictionary
>
())
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Dictionaries are not supported by regex()."
));
MatchType
mode
;
if
(
args
.
size
()
>
2
)
...
...
@@ -147,7 +151,8 @@ bool ScriptUtils::Regex(const std::vector<Value>& args)
return
false
;
}
return
true
;
/* MatchAny: Nothing matched. MatchAll: Everything matched. */
return
mode
==
MatchAll
;
}
else
{
String
text
=
argTexts
;
boost
::
smatch
what
;
...
...
@@ -158,10 +163,14 @@ bool ScriptUtils::Regex(const std::vector<Value>& args)
bool
ScriptUtils
::
Match
(
const
std
::
vector
<
Value
>&
args
)
{
if
(
args
.
size
()
<
2
)
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Pattern and text must be specified."
));
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Pattern and text must be specified
for match()
."
));
String
pattern
=
args
[
0
];
const
Value
&
argTexts
=
args
[
1
];
if
(
argTexts
.
IsObjectType
<
Dictionary
>
())
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Dictionaries are not supported by match()."
));
MatchType
mode
;
if
(
args
.
size
()
>
2
)
...
...
@@ -189,7 +198,8 @@ bool ScriptUtils::Match(const std::vector<Value>& args)
return
false
;
}
return
true
;
/* MatchAny: Nothing matched. MatchAll: Everything matched. */
return
mode
==
MatchAll
;
}
else
{
String
text
=
argTexts
;
return
Utility
::
Match
(
pattern
,
argTexts
);
...
...
@@ -199,10 +209,14 @@ bool ScriptUtils::Match(const std::vector<Value>& args)
bool
ScriptUtils
::
CidrMatch
(
const
std
::
vector
<
Value
>&
args
)
{
if
(
args
.
size
()
<
2
)
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"CIDR and IP address must be specified."
));
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"CIDR and IP address must be specified
for cidr_match()
."
));
String
pattern
=
args
[
0
];
const
Value
&
argIps
=
args
[
1
];
if
(
argIps
.
IsObjectType
<
Dictionary
>
())
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Dictionaries are not supported by cidr_match()."
));
MatchType
mode
;
if
(
args
.
size
()
>
2
)
...
...
@@ -230,7 +244,8 @@ bool ScriptUtils::CidrMatch(const std::vector<Value>& args)
return
false
;
}
return
true
;
/* MatchAny: Nothing matched. MatchAll: Everything matched. */
return
mode
==
MatchAll
;
}
else
{
String
ip
=
argIps
;
return
Utility
::
CidrMatch
(
pattern
,
ip
);
...
...
lib/config/configitem.cpp
View file @
4e5ea9e2
...
...
@@ -38,6 +38,8 @@
#include
"base/function.hpp"
#include
<sstream>
#include
<fstream>
#include
<algorithm>
#include
<random>
using
namespace
icinga
;
...
...
@@ -428,26 +430,77 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
if
(
items
.
empty
())
return
true
;
// Shuffle all items to evenly distribute them over the threads of the workqueue. This increases perfomance
// noticably in environments with lots of objects and available threads.
std
::
shuffle
(
std
::
begin
(
items
),
std
::
end
(
items
),
std
::
default_random_engine
{});
#ifdef I2_DEBUG
Log
(
LogDebug
,
"configitem"
)
<<
"Committing "
<<
items
.
size
()
<<
" new items."
;
#endif
/* I2_DEBUG */
for
(
const
auto
&
ip
:
items
)
newItems
.
push_back
(
ip
.
first
);
upq
.
ParallelFor
(
items
,
[](
const
ItemPair
&
ip
)
{
std
::
set
<
Type
::
Ptr
>
types
;
std
::
set
<
Type
::
Ptr
>
completed_types
;
for
(
const
Type
::
Ptr
&
type
:
Type
::
GetAllTypes
())
{
if
(
ConfigObject
::
TypeInstance
->
IsAssignableFrom
(
type
))
types
.
insert
(
type
);
}
while
(
types
.
size
()
!=
completed_types
.
size
())
{
for
(
const
Type
::
Ptr
&
type
:
types
)
{
if
(
completed_types
.
find
(
type
)
!=
completed_types
.
end
())
continue
;
bool
unresolved_dep
=
false
;
/* skip this type (for now) if there are unresolved load dependencies */
for
(
const
String
&
loadDep
:
type
->
GetLoadDependencies
())
{
Type
::
Ptr
pLoadDep
=
Type
::
GetByName
(
loadDep
);
if
(
types
.
find
(
pLoadDep
)
!=
types
.
end
()
&&
completed_types
.
find
(
pLoadDep
)
==
completed_types
.
end
())
{
unresolved_dep
=
true
;
break
;
}
}
if
(
unresolved_dep
)
continue
;
int
committed_items
=
0
;
upq
.
ParallelFor
(
items
,
[
&
type
,
&
committed_items
](
const
ItemPair
&
ip
)
{
const
ConfigItem
::
Ptr
&
item
=
ip
.
first
;
if
(
item
->
m_Type
!=
type
)
return
;
ip
.
first
->
Commit
(
ip
.
second
);
committed_items
++
;
});
upq
.
Join
();
if
(
upq
.
HasExceptions
())
return
false
;
completed_types
.
insert
(
type
);
std
::
set
<
Type
::
Ptr
>
types
;
#ifdef I2_DEBUG
if
(
committed_items
>
0
)
Log
(
LogDebug
,
"configitem"
)
<<
"Committed "
<<
committed_items
<<
" items of type '"
<<
type
->
GetName
()
<<
"'."
;
#endif
/* I2_DEBUG */
for
(
const
Type
::
Ptr
&
type
:
Type
::
GetAllType
s
())
{
if
(
ConfigObject
::
TypeInstance
->
IsAssignableFrom
(
type
))
types
.
insert
(
type
);
if
(
upq
.
HasException
s
())
return
false
;
}
}
std
::
set
<
Type
::
Ptr
>
completed_types
;
#ifdef I2_DEBUG
Log
(
LogDebug
,
"configitem"
)
<<
"Committed "
<<
items
.
size
()
<<
" items."
;
#endif
/* I2_DEBUG */
completed_types
.
clear
();
while
(
types
.
size
()
!=
completed_types
.
size
())
{
for
(
const
Type
::
Ptr
&
type
:
types
)
{
...
...
@@ -468,7 +521,8 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
if
(
unresolved_dep
)
continue
;
upq
.
ParallelFor
(
items
,
[
&
type
](
const
ItemPair
&
ip
)
{
int
notified_items
=
0
;
upq
.
ParallelFor
(
items
,
[
&
type
,
&
notified_items
](
const
ItemPair
&
ip
)
{
const
ConfigItem
::
Ptr
&
item
=
ip
.
first
;
if
(
!
item
->
m_Object
||
item
->
m_Type
!=
type
)
...
...
@@ -476,6 +530,7 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
try
{
item
->
m_Object
->
OnAllConfigLoaded
();
notified_items
++
;
}
catch
(
const
std
::
exception
&
ex
)
{
if
(
!
item
->
m_IgnoreOnError
)
throw
;
...
...
@@ -496,11 +551,18 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
upq
.
Join
();
#ifdef I2_DEBUG
if
(
notified_items
>
0
)
Log
(
LogDebug
,
"configitem"
)
<<
"Sent OnAllConfigLoaded to "
<<
notified_items
<<
" items of type '"
<<
type
->
GetName
()
<<
"'."
;
#endif
/* I2_DEBUG */
if
(
upq
.
HasExceptions
())
return
false
;
notified_items
=
0
;
for
(
const
String
&
loadDep
:
type
->
GetLoadDependencies
())
{
upq
.
ParallelFor
(
items
,
[
loadDep
,
&
type
](
const
ItemPair
&
ip
)
{
upq
.
ParallelFor
(
items
,
[
loadDep
,
&
type
,
&
notified_items
](
const
ItemPair
&
ip
)
{
const
ConfigItem
::
Ptr
&
item
=
ip
.
first
;
if
(
!
item
->
m_Object
||
item
->
m_Type
->
GetName
()
!=
loadDep
)
...
...
@@ -508,14 +570,22 @@ bool ConfigItem::CommitNewItems(const ActivationContext::Ptr& context, WorkQueue
ActivationScope
ascope
(
item
->
m_ActivationContext
);
item
->
m_Object
->
CreateChildObjects
(
type
);
notified_items
++
;
});
}
upq
.
Join
();
#ifdef I2_DEBUG
if
(
notified_items
>
0
)
Log
(
LogDebug
,
"configitem"
)
<<
"Sent CreateChildObjects to "
<<
notified_items
<<
" items of type '"
<<
type
->
GetName
()
<<
"'."
;
#endif
/* I2_DEBUG */
if
(
upq
.
HasExceptions
())
return
false
;
// Make sure to activate any additionally generated items
if
(
!
CommitNewItems
(
context
,
upq
,
newItems
))
return
false
;
}
...
...
lib/methods/clusterzonechecktask.cpp
View file @
4e5ea9e2
...
...
@@ -122,13 +122,9 @@ void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const Che
bytesReceivedPerSecond
+=
endpoint
->
GetBytesReceivedPerSecond
();
}
if
(
!
connected
)
{
cr
->
SetState
(
ServiceCritical
);
cr
->
SetOutput
(
"Zone '"
+
zoneName
+
"' is not connected. Log lag: "
+
Utility
::
FormatDuration
(
zoneLag
));
}
else
{
if
(
connected
)
{
cr
->
SetState
(
ServiceOK
);
cr
->
SetOutput
(
"Zone '"
+
zoneName
+
"' is connected. Log lag: "
+
Utility
::
FormatDuration
(
zoneLag
));
}
/* Check whether the thresholds have been resolved and compare them */
if
(
missingLagCritical
.
IsEmpty
()
&&
zoneLag
>
lagCritical
)
{
...
...
@@ -140,6 +136,10 @@ void ClusterZoneCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const Che
cr
->
SetOutput
(
"Zone '"
+
zoneName
+
"' is connected. Log lag: "
+
Utility
::
FormatDuration
(
zoneLag
)
+
" greater than warning threshold: "
+
Utility
::
FormatDuration
(
lagWarning
));
}
}
else
{
cr
->
SetState
(
ServiceCritical
);
cr
->
SetOutput
(
"Zone '"
+
zoneName
+
"' is not connected. Log lag: "
+
Utility
::
FormatDuration
(
zoneLag
));
}
cr
->
SetPerformanceData
(
new
Array
({
new
PerfdataValue
(
"slave_lag"
,
zoneLag
,
false
,
"s"
,
lagWarning
,
lagCritical
),
...
...
lib/perfdata/elasticsearchwriter.cpp
View file @
4e5ea9e2
...
...
@@ -434,7 +434,7 @@ void ElasticsearchWriter::SendRequest(const String& body)
stream
=
Connect
();
}
catch
(
const
std
::
exception
&
ex
)
{
Log
(
LogWarning
,
"ElasticsearchWriter"
)
<<
"Flush failed, cannot connect to Elasticsearch
."
;
<<
"Flush failed, cannot connect to Elasticsearch
: "
<<
DiagnosticInformation
(
ex
,
false
)
;
return
;
}
...
...
lib/perfdata/influxdbwriter.cpp
View file @
4e5ea9e2
...
...
@@ -425,7 +425,7 @@ void InfluxdbWriter::Flush()
stream
=
Connect
();
}
catch
(
const
std
::
exception
&
ex
)
{
Log
(
LogWarning
,
"InfluxDbWriter"
)
<<
"Flush failed, cannot connect to InfluxDB
."
;
<<
"Flush failed, cannot connect to InfluxDB
: "
<<
DiagnosticInformation
(
ex
,
false
)
;
return
;
}
...
...
lib/remote/apilistener.cpp
View file @
4e5ea9e2
...
...
@@ -454,9 +454,9 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
try
{
tlsStream
->
Handshake
();
}
catch
(
const
std
::
exception
&
)
{
}
catch
(
const
std
::
exception
&
ex
)
{
Log
(
LogCritical
,
"ApiListener"
)
<<
"Client TLS handshake failed ("
<<
conninfo
<<
")
"
;
<<
"Client TLS handshake failed ("
<<
conninfo
<<
")
: "
<<
DiagnosticInformation
(
ex
,
false
)
;
tlsStream
->
Close
();
return
;
}
...
...
lib/remote/filterutility.cpp
View file @
4e5ea9e2
...
...
@@ -127,7 +127,7 @@ static void FilteredAddTarget(ScriptFrame& permissionFrame, Expression *permissi
ScriptFrame
&
frame
,
Expression
*
ufilter
,
std
::
vector
<
Value
>&
result
,
const
String
&
variableName
,
const
Object
::
Ptr
&
target
)
{
if
(
FilterUtility
::
EvaluateFilter
(
permissionFrame
,
permissionFilter
,
target
,
variableName
)
&&
FilterUtility
::
EvaluateFilter
(
frame
,
ufilter
,
target
,
variableName
))
result
.
emplace_back
(
target
);
result
.
emplace_back
(
std
::
move
(
target
)
)
;
}
void
FilterUtility
::
CheckPermission
(
const
ApiUser
::
Ptr
&
user
,
const
String
&
permission
,
Expression
**
permissionFilter
)
...
...
@@ -206,7 +206,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
if
(
attr
==
"type"
)
attr
=
"name"
;
if
(
query
->
Contains
(
attr
))
{
if
(
query
&&
query
->
Contains
(
attr
))
{
String
name
=
HttpUtility
::
GetLastParameter
(
query
,
attr
);
Object
::
Ptr
target
=
provider
->
GetTargetByName
(
type
,
name
);
...
...
@@ -219,7 +219,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
attr
=
provider
->
GetPluralName
(
type
);
boost
::
algorithm
::
to_lower
(
attr
);
if
(
query
->
Contains
(
attr
))
{
if
(
query
&&
query
->
Contains
(
attr
))
{
Array
::
Ptr
names
=
query
->
Get
(
attr
);
if
(
names
)
{
ObjectLock
olock
(
names
);
...
...
@@ -235,7 +235,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
}
}
if
(
query
->
Contains
(
"filter"
)
||
result
.
empty
())
{
if
(
(
query
&&
query
->
Contains
(
"filter"
)
)
||
result
.
empty
())
{
if
(
!
query
->
Contains
(
"type"
))
BOOST_THROW_EXCEPTION
(
std
::
invalid_argument
(
"Type must be specified when using a filter."
));
...
...
@@ -251,12 +251,9 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
frame
.
Sandboxed
=
true
;
Dictionary
::
Ptr
uvars
=
new
Dictionary
();
std
::
unique_ptr
<
Expression
>
ufilter
;
if
(
query
->
Contains
(
"filter"
))
{
String
filter
=
HttpUtility
::
GetLastParameter
(
query
,
"filter"
);
ufilter
=
ConfigCompiler
::
CompileText
(
"<API query>"
,
filter
);
}
std
::
unique_ptr
<
Expression
>
ufilter
=
ConfigCompiler
::
CompileText
(
"<API query>"
,
filter
);
Dictionary
::
Ptr
filter_vars
=
query
->
Get
(
"filter_vars"
);
if
(
filter_vars
)
{
...
...
@@ -271,6 +268,14 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
provider
->
FindTargets
(
type
,
std
::
bind
(
&
FilteredAddTarget
,
std
::
ref
(
permissionFrame
),
permissionFilter
,
std
::
ref
(
frame
),
&*
ufilter
,
std
::
ref
(
result
),
variableName
,
_1
));
}
else
{
/* Ensure to pass a nullptr as filter expression.
* GCC 8.1.1 on F28 causes problems, see GH #6533.
*/
provider
->
FindTargets
(
type
,
std
::
bind
(
&
FilteredAddTarget
,
std
::
ref
(
permissionFrame
),
permissionFilter
,
std
::
ref
(
frame
),
nullptr
,
std
::
ref
(
result
),
variableName
,
_1
));
}
}
return
result
;
...
...
lib/remote/pkiutility.cpp
View file @
4e5ea9e2
...
...
@@ -187,8 +187,9 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
try
{
stream
->
Handshake
();
}
catch
(
const
std
::
exception
&
)
{
Log
(
LogCritical
,
"cli"
,
"Client TLS handshake failed."
);
}
catch
(
const
std
::
exception
&
ex
)
{
Log
(
LogCritical
,
"cli"
)
<<
"Client TLS handshake failed: "
<<
DiagnosticInformation
(
ex
,
false
);
return
1
;
}
...
...
lib/remote/pkiutility.hpp
View file @
4e5ea9e2
...
...
@@ -21,6 +21,7 @@
#define PKIUTILITY_H
#include
"remote/i2-remote.hpp"
#include
"base/exception.hpp"
#include
"base/dictionary.hpp"
#include
"base/string.hpp"
#include
<openssl/x509v3.h>
...
...