Commit 88ce7159 authored by Marcin Siodelski's avatar Marcin Siodelski

[master] Merge branch 'trac5107'

parents 1d94a83e 9035d06e
......@@ -1601,7 +1601,7 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/bin/Makefile
src/bin/agent/Makefile
src/bin/agent/tests/Makefile
src/bin/agent/tests/ctrl_agent_process_tests.sh
src/bin/agent/tests/ca_process_tests.sh
src/bin/d2/Makefile
src/bin/d2/tests/Makefile
src/bin/d2/tests/d2_process_tests.sh
......
/kea-ctrl-agent
/ctrl_agent_messages.cc
/ctrl_agent_messages.h
/ca_messages.cc
/ca_messages.h
/s-messages
/kea-ctrl-agent.8
......@@ -9,7 +9,7 @@ if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = *.gcno *.gcda ctrl_agent_messages.h ctrl_agent_messages.cc s-messages
CLEANFILES = *.gcno *.gcda ca_messages.h ca_messages.cc s-messages
man_MANS = kea-ctrl-agent.8
DISTCLEANFILES = $(man_MANS)
......@@ -29,29 +29,35 @@ $(man_MANS):
endif
ctrl_agent_messages.h ctrl_agent_messages.cc: s-messages
ca_messages.h ca_messages.cc: s-messages
s-messages: ctrl_agent_messages.mes
$(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/bin/agent/ctrl_agent_messages.mes
s-messages: ca_messages.mes
$(top_builddir)/src/lib/log/compiler/kea-msg-compiler $(top_srcdir)/src/bin/agent/ca_messages.mes
touch $@
BUILT_SOURCES = ctrl_agent_messages.h ctrl_agent_messages.cc
BUILT_SOURCES = ca_messages.h ca_messages.cc
# convenience archive
noinst_LTLIBRARIES = libagent.la
libagent_la_SOURCES = ctrl_agent_cfg_mgr.cc ctrl_agent_cfg_mgr.h
libagent_la_SOURCES += ctrl_agent_controller.cc ctrl_agent_controller.h
libagent_la_SOURCES += ctrl_agent_log.cc ctrl_agent_log.h
libagent_la_SOURCES += ctrl_agent_process.cc ctrl_agent_process.h
libagent_la_SOURCES += agent_parser.cc agent_parser.h
libagent_la_SOURCES = agent_parser.cc agent_parser.h
libagent_la_SOURCES += agent_lexer.cc
libagent_la_SOURCES += ca_cfg_mgr.cc ca_cfg_mgr.h
libagent_la_SOURCES += ca_controller.cc ca_controller.h
libagent_la_SOURCES += ca_command_mgr.cc ca_command_mgr.h
libagent_la_SOURCES += ca_log.cc ca_log.h
libagent_la_SOURCES += ca_process.cc ca_process.h
libagent_la_SOURCES += ca_response_creator.cc ca_response_creator.h
libagent_la_SOURCES += ca_response_creator_factory.h
libagent_la_SOURCES += parser_context.cc parser_context.h parser_context_decl.h
libagent_la_SOURCES += agent_lexer.ll location.hh position.hh stack.hh
nodist_libagent_la_SOURCES = ctrl_agent_messages.h ctrl_agent_messages.cc
EXTRA_DIST += ctrl_agent_messages.mes
nodist_libagent_la_SOURCES = ca_messages.h ca_messages.cc
EXTRA_DIST += ca_messages.mes
EXTRA_DIST += agent_lexer.ll
EXTRA_DIST += agent_parser.yy
sbin_PROGRAMS = kea-ctrl-agent
......@@ -66,6 +72,7 @@ kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/http/libkea-http.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
kea_ctrl_agent_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
......
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <agent/ctrl_agent_cfg_mgr.h>
#include <agent/ca_cfg_mgr.h>
using namespace isc::dhcp;
using namespace isc::process;
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <agent/ca_command_mgr.h>
#include <cc/data.h>
#include <boost/pointer_cast.hpp>
using namespace isc::data;
namespace isc {
namespace agent {
CtrlAgentCommandMgr&
CtrlAgentCommandMgr::instance() {
static CtrlAgentCommandMgr command_mgr;
return (command_mgr);
}
CtrlAgentCommandMgr::CtrlAgentCommandMgr()
: HookedCommandMgr() {
}
ConstElementPtr
CtrlAgentCommandMgr::handleCommand(const std::string& cmd_name,
const isc::data::ConstElementPtr& params) {
ElementPtr answer_list = Element::createList();
answer_list->add(boost::const_pointer_cast<
Element>(HookedCommandMgr::handleCommand(cmd_name, params)));
return (answer_list);
}
} // end of namespace isc::agent
} // end of namespace isc
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CTRL_AGENT_COMMAND_MGR_H
#define CTRL_AGENT_COMMAND_MGR_H
#include <config/hooked_command_mgr.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace agent {
/// @brief Command Manager for Control Agent.
///
/// This is an implementation of the Command Manager within Control Agent.
/// In addition to the standard capabilities of the @ref HookedCommandMgr
/// it is also intended to forward commands to the respective Kea servers
/// when the command is not supported directly by the Control Agent.
///
/// @todo This Command Manager doesn't yet support forwarding commands.
///
/// The @ref CtrlAgentCommandMgr is implemented as a singleton. The commands
/// are registered using @c CtrlAgentCommandMgr::instance().registerCommand().
/// The @ref CtrlAgentResponseCreator uses the sole instance of the Command
/// Manager to handle incoming commands.
class CtrlAgentCommandMgr : public config::HookedCommandMgr,
public boost::noncopyable {
public:
/// @brief Returns sole instance of the Command Manager.
static CtrlAgentCommandMgr& instance();
/// @brief Handles the command having a given name and arguments.
///
/// This method extends the base implementation with the ability to forward
/// commands to Kea servers if the Control Agent failed to handle it itself.
///
/// @todo Currently this method only wraps an answer within a list Element.
/// This will be later used to include multiple answers within this list.
/// For now it is just a single answer from the Control Agent.
///
/// @param cmd_name Command name.
/// @param params Command arguments.
///
/// @return Pointer to the const data element representing response
/// to a command.
virtual isc::data::ConstElementPtr
handleCommand(const std::string& cmd_name,
const isc::data::ConstElementPtr& params);
private:
/// @brief Private constructor.
///
/// The instance should be created using @ref CtrlAgentCommandMgr::instance,
/// thus the constructor is private.
CtrlAgentCommandMgr();
};
} // end of namespace isc::agent
} // end of namespace isc
#endif
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -6,8 +6,8 @@
#include <config.h>
#include <agent/ctrl_agent_controller.h>
#include <agent/ctrl_agent_process.h>
#include <agent/ca_controller.h>
#include <agent/ca_process.h>
using namespace isc::process;
......@@ -16,7 +16,7 @@ namespace agent {
/// @brief Defines the application name, this is passed into base class
/// it may be used to locate configuration data and appears in log statement.
const char* CtrlAgentController::agent_app_name_ = "CtrlAgent";
const char* CtrlAgentController::agent_app_name_ = "Control-agent";
/// @brief Defines the executable name. This is passed into the base class
const char* CtrlAgentController::agent_bin_name_ = "kea-ctrl-agent";
......
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <agent/ctrl_agent_log.h>
#include <agent/ca_log.h>
namespace isc {
namespace agent {
......
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -9,7 +9,7 @@
#include <log/logger_support.h>
#include <log/macros.h>
#include <agent/ctrl_agent_messages.h>
#include <agent/ca_messages.h>
namespace isc {
namespace agent {
......
# Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -6,6 +6,11 @@
$NAMESPACE isc::agent
% CTRL_AGENT_HTTP_SERVICE_STARTED HTTP service bound to address %1:%2
This informational message indicates that the server has started HTTP service
on the specified address and port. All control commands should be sent to this
address and port.
% CTRL_AGENT_FAILED application experienced a fatal error: %1
This is a debug message issued when the Control Agent application
encounters an unrecoverable error from within the event loop.
......
......@@ -5,13 +5,28 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <agent/ctrl_agent_process.h>
#include <agent/ctrl_agent_log.h>
#include <agent/ca_process.h>
#include <agent/ca_response_creator_factory.h>
#include <agent/ca_log.h>
#include <asiolink/io_address.h>
#include <cc/command_interpreter.h>
#include <http/listener.h>
#include <boost/pointer_cast.hpp>
using namespace isc::asiolink;
using namespace isc::http;
using namespace isc::process;
// Temporarily hardcoded configuration.
/// @todo: remove once 5134 is merged.
namespace {
const IOAddress SERVER_ADDRESS("127.0.0.1");
const unsigned short SERVER_PORT = 8081;
const long REQUEST_TIMEOUT = 10000;
}
namespace isc {
namespace agent {
......@@ -32,6 +47,27 @@ CtrlAgentProcess::run() {
LOG_INFO(agent_logger, CTRL_AGENT_STARTED).arg(VERSION);
try {
// Create response creator factory first. It will be used to generate
// response creators. Each response creator will be used to generate
// answer to specific request.
HttpResponseCreatorFactoryPtr rcf(new CtrlAgentResponseCreatorFactory());
// Create http listener. It will open up a TCP socket and be prepared
// to accept incoming connection.
HttpListener http_listener(*getIoService(), SERVER_ADDRESS,
SERVER_PORT, rcf, REQUEST_TIMEOUT);
// Instruct the http listener to actually open socket, install callback
// and start listening.
http_listener.start();
// Ok, seems we're good to go.
LOG_INFO(agent_logger, CTRL_AGENT_HTTP_SERVICE_STARTED)
.arg(SERVER_ADDRESS.toText()).arg(SERVER_PORT);
// Let's process incoming data or expiring timers in a loop until
// shutdown condition is detected.
while (!shouldShutdown()) {
getIoService()->run_one();
}
......
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -7,7 +7,7 @@
#ifndef CTRL_AGENT_PROCESS_H
#define CTRL_AGENT_PROCESS_H
#include <agent/ctrl_agent_cfg_mgr.h>
#include <agent/ca_cfg_mgr.h>
#include <process/d_process.h>
namespace isc {
......
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <agent/ca_command_mgr.h>
#include <agent/ca_response_creator.h>
#include <cc/data.h>
#include <http/post_request_json.h>
#include <http/response_json.h>
#include <boost/pointer_cast.hpp>
using namespace isc::data;
using namespace isc::http;
namespace isc {
namespace agent {
HttpRequestPtr
CtrlAgentResponseCreator::createNewHttpRequest() const {
return (HttpRequestPtr(new PostHttpRequestJson()));
}
HttpResponsePtr
CtrlAgentResponseCreator::
createStockHttpResponse(const ConstHttpRequestPtr& request,
const HttpStatusCode& status_code) const {
// The request hasn't been finalized so the request object
// doesn't contain any information about the HTTP version number
// used. But, the context should have this data (assuming the
// HTTP version is parsed ok).
HttpVersion http_version(request->context()->http_version_major_,
request->context()->http_version_minor_);
// We only accept HTTP version 1.0 or 1.1. If other version number is found
// we fall back to HTTP/1.0.
if ((http_version < HttpVersion(1, 0)) || (HttpVersion(1, 1) < http_version)) {
http_version.major_ = 1;
http_version.minor_ = 0;
}
// This will generate the response holding JSON content.
HttpResponsePtr response(new HttpResponseJson(http_version, status_code));
return (response);
}
HttpResponsePtr
CtrlAgentResponseCreator::
createDynamicHttpResponse(const ConstHttpRequestPtr& request) {
// The request is always non-null, because this is verified by the
// createHttpResponse method. Let's try to convert it to the
// ConstPostHttpRequestJson type as this is the type generated by the
// createNewHttpRequest. If the conversion result is null it means that
// the caller did not use createNewHttpRequest method to create this
// instance. This is considered an error in the server logic.
ConstPostHttpRequestJsonPtr request_json = boost::dynamic_pointer_cast<
const PostHttpRequestJson>(request);
if (!request_json) {
// Notify the client that we have a problem with our server.
return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
}
// We have already checked that the request is finalized so the call
// to getBodyAsJson must not trigger an exception.
ConstElementPtr command = request_json->getBodyAsJson();
// Process command doesn't generate exceptions but can possibly return
// null response, if the handler is not implemented properly. This is
// again an internal server issue.
ConstElementPtr response = CtrlAgentCommandMgr::instance().processCommand(command);
if (!response) {
// Notify the client that we have a problem with our server.
return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR));
}
// The response is ok, so let's create new HTTP response with the status OK.
HttpResponseJsonPtr http_response = boost::dynamic_pointer_cast<
HttpResponseJson>(createStockHttpResponse(request, HttpStatusCode::OK));
http_response->setBodyAsJson(response);
return (http_response);
}
} // end of namespace isc::agent
} // end of namespace isc
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CTRL_AGENT_RESPONSE_CREATOR_H
#define CTRL_AGENT_RESPONSE_CREATOR_H
#include <agent/ca_command_mgr.h>
#include <http/response_creator.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace agent {
class CtrlAgentResponseCreator;
/// @brief Pointer to the @ref CtrlAgentResponseCreator.
typedef boost::shared_ptr<CtrlAgentResponseCreator> CtrlAgentResponseCreatorPtr;
/// @brief Concrete implementation of the HTTP response crator used
/// by the Control Agent.
///
/// See the documentation of the @ref HttpResponseCreator for the basic
/// information how HTTP response creators are utilized by the libkea-http
/// library to generate HTTP responses.
///
/// This creator expects that received requests are encapsulated in the
/// @ref PostHttpRequestJson objects. The generated responses are
/// encapsulated in the HttpResponseJson objects.
///
/// This class uses @ref CtrlAgentCommandMgr singleton to process commands
/// conveyed in the HTTP body. The JSON responses returned by the manager
/// are placed in the body of the generated HTTP responses.
class CtrlAgentResponseCreator : public http::HttpResponseCreator {
public:
/// @brief Create a new request.
///
/// This method creates a bare instance of the @ref PostHttpRequestJson.
///
/// @return Pointer to the new instance of the @ref PostHttpRequestJson.
virtual http::HttpRequestPtr createNewHttpRequest() const;
/// @brief Creates stock HTTP response.
///
/// @param request Pointer to an object representing HTTP request.
/// @param status_code Status code of the response.
/// @return Pointer to an @ref HttpResponseJson object representing stock
/// HTTP response.
virtual http::HttpResponsePtr
createStockHttpResponse(const http::ConstHttpRequestPtr& request,
const http::HttpStatusCode& status_code) const;
private:
/// @brief Creates implementation specific HTTP response.
///
/// @param request Pointer to an object representing HTTP request.
/// @return Pointer to an object representing HTTP response.
virtual http::HttpResponsePtr
createDynamicHttpResponse(const http::ConstHttpRequestPtr& request);
};
} // end of namespace isc::agent
} // end of namespace isc
#endif
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CTRL_AGENT_RESPONSE_CREATOR_FACTORY_H
#define CTRL_AGENT_RESPONSE_CREATOR_FACTORY_H
#include <agent/ca_response_creator.h>
#include <http/response_creator_factory.h>
namespace isc {
namespace agent {
/// @brief HTTP response creator factory for Control Agent.
///
/// See the documentation of the @ref HttpResponseCreatorFactory for
/// the details how the response factory object is used by the
/// @ref HttpListener.
///
/// This class always returns the same instance of the
/// @ref CtrlAgentResponseCreator which @ref HttpListener and
/// @ref HttpConnection classes use to generate HTTP response messages
/// which comply with the formats required by the Control Agent.
class CtrlAgentResponseCreatorFactory : public http::HttpResponseCreatorFactory {
public:
/// @brief Constructor.
///
/// Creates sole instance of the @ref CtrlAgentResponseCreator object
/// returned by the @ref CtrlAgentResponseCreatorFactory::create.
CtrlAgentResponseCreatorFactory()
: sole_creator_(new CtrlAgentResponseCreator()) {
}
/// @brief Returns an instance of the @ref CtrlAgentResponseCreator which
/// is used by HTTP server to generate responses to commands.
///
/// @return Pointer to the @ref CtrlAgentResponseCreator object.
virtual http::HttpResponseCreatorPtr create() const {
return (sole_creator_);
}
private:
/// @brief Instance of the @ref CtrlAgentResponseCreator returned.
http::HttpResponseCreatorPtr sole_creator_;
};
} // end of namespace isc::agent
} // end of namespace isc
#endif
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <agent/ctrl_agent_controller.h>
#include <agent/ca_controller.h>
#include <exceptions/exceptions.h>
#include <cstdlib>
#include <iostream>
......
/ctrl_agent_unittest
/ctrl_agent_process_tests.sh
/ca_unittests
/ca_process_tests.sh
SHTESTS =
# The test of dynamic reconfiguration based on signals will work only
# if we are using file based configuration approach.
SHTESTS += ctrl_agent_process_tests.sh
SHTESTS += ca_process_tests.sh
noinst_SCRIPTS = ctrl_agent_process_tests.sh
noinst_SCRIPTS = ca_process_tests.sh
EXTRA_DIST = ctrl_agent_process_tests.sh.in
EXTRA_DIST = ca_process_tests.sh.in
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
......@@ -26,7 +26,7 @@ AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/agent\"
CLEANFILES = $(builddir)/interfaces.txt $(builddir)/logger_lockfile
DISTCLEANFILES = ctrl_agent_process_tests.sh
DISTCLEANFILES = ca_process_tests.sh
AM_CXXFLAGS = $(KEA_CXXFLAGS)
......@@ -40,39 +40,43 @@ TESTS_ENVIRONMENT = \
TESTS =
if HAVE_GTEST
TESTS += ctrl_agent_unittest
ctrl_agent_unittest_SOURCES = ctrl_agent_cfg_mgr_unittest.cc
ctrl_agent_unittest_SOURCES += ctrl_agent_controller_unittest.cc
ctrl_agent_unittest_SOURCES += parser_unittest.cc
ctrl_agent_unittest_SOURCES += ctrl_agent_process_unittest.cc
ctrl_agent_unittest_SOURCES += ctrl_agent_unittest.cc
ctrl_agent_unittest_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
ctrl_agent_unittest_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
ctrl_agent_unittest_LDADD = $(top_builddir)/src/bin/agent/libagent.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/process/testutils/libprocesstest.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/cfgrpt/libcfgrpt.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
ctrl_agent_unittest_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
ctrl_agent_unittest_LDADD += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS)
ctrl_agent_unittest_LDADD += $(BOOST_LIBS) $(GTEST_LDADD)
TESTS += ca_unittests