Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,7 @@ const auto response = influxdb->execute("SHOW DATABASES");

## Transports

An underlying transport is fully configurable by passing an URI:
```
[protocol]://[username:password@]host:port[?db=database]

# Auth token:
[protocol]://[token@]host:port[?db=database]
```
<br>
List of supported transport is following:
Supported transports:

| Name | Dependency | URI protocol | Sample URI |
| ----------- |:-----------:|:--------------:| -------------------------------------:|
Expand All @@ -137,9 +129,36 @@ List of supported transport is following:
| UDP | boost | `udp` | `udp://localhost:8094` |
| Unix socket | boost | `unix` | `unix:///tmp/telegraf.sock` |


<sup>i)</sup> boost is needed to support queries.

### Configuration by URI

An underlying transport is configurable by passing an URI. `[protocol]` determines the actual transport type:

```cpp
auto influxdb = influxdb::InfluxDBFactory::Get("http://localhost:8086?db=test");
```

URI Format:

```
[protocol]://[username:password@]host:port[?db=database]

# Auth token:
[protocol]://[token@]host:port[?db=database]
```

### Additional transport configuration *(HTTP only)*

The HTTP transport supports additional configurations beyond the limited URI parameters:

```cpp
auto influxdb = InfluxDBBuilder::http("http://localhost:8086?db=test")
.setTimeout(std::chrono::seconds{20})
.setAuthToken("<token>")
.connect();
```


## InfluxDB v2.x compatibility

Expand Down
54 changes: 54 additions & 0 deletions include/InfluxDBBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// MIT License
//
// Copyright (c) 2020-2024 offa
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef INFLUXDATA_INFLUXDBBUILDER_H
#define INFLUXDATA_INFLUXDBBUILDER_H

#include "InfluxDB.h"
#include "Transport.h"
#include "Proxy.h"
#include "influxdb_export.h"
#include <chrono>

namespace influxdb
{
class INFLUXDB_EXPORT InfluxDBBuilder
{
public:
std::unique_ptr<InfluxDB> connect();

InfluxDBBuilder&& setBasicAuthentication(const std::string& user, const std::string& pass);
InfluxDBBuilder&& setAuthToken(const std::string& token);
InfluxDBBuilder&& setProxy(const Proxy& proxy);
InfluxDBBuilder&& setTimeout(std::chrono::milliseconds timeout);
InfluxDBBuilder&& setVerifyCertificate(bool verify);

static InfluxDBBuilder http(const std::string& url);

private:
explicit InfluxDBBuilder(std::unique_ptr<Transport> impl);

std::unique_ptr<Transport> transport;
};
}

#endif // INFLUXDATA_INFLUXDBBUILDER_H
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_library(InfluxDB-Core OBJECT
InfluxDB.cxx
Point.cxx
InfluxDBFactory.cxx
InfluxDBBuilder.cxx
Proxy.cxx
)
target_include_directories(InfluxDB-Core PUBLIC
Expand Down
11 changes: 11 additions & 0 deletions src/HTTP.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ namespace influxdb::transports
}
}

void HTTP::setVerifyCertificate(bool verify)
{
session.SetVerifySsl(verify);
}

void HTTP::setTimeout(std::chrono::milliseconds timeout)
{
session.SetTimeout(timeout);
session.SetConnectTimeout(timeout);
}

std::string HTTP::execute(const std::string& cmd)
{
session.SetUrl(cpr::Url{endpointUrl + "/query"});
Expand Down
4 changes: 4 additions & 0 deletions src/HTTP.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "Transport.h"
#include <memory>
#include <string>
#include <chrono>
#include <cpr/cpr.h>

namespace influxdb::transports
Expand Down Expand Up @@ -71,6 +72,9 @@ namespace influxdb::transports
/// Sets proxy
void setProxy(const Proxy& proxy) override;

void setVerifyCertificate(bool verify);
void setTimeout(std::chrono::milliseconds timeout);

private:
std::string endpointUrl;
std::string databaseName;
Expand Down
74 changes: 74 additions & 0 deletions src/InfluxDBBuilder.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// MIT License
//
// Copyright (c) 2020-2024 offa
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "InfluxDBBuilder.h"
#include "HTTP.h"

namespace influxdb
{
InfluxDBBuilder::InfluxDBBuilder(std::unique_ptr<Transport> impl)
: transport(std::move(impl))
{
}

std::unique_ptr<InfluxDB> InfluxDBBuilder::connect()
{
return std::make_unique<InfluxDB>(std::move(transport));
}

InfluxDBBuilder&& InfluxDBBuilder::setBasicAuthentication(const std::string& user, const std::string& pass)
{
dynamic_cast<transports::HTTP&>(*transport).setBasicAuthentication(user, pass);
return std::move(*this);
}

InfluxDBBuilder&& InfluxDBBuilder::setAuthToken(const std::string& token)
{
dynamic_cast<transports::HTTP&>(*transport).setAuthToken(token);
return std::move(*this);
}

InfluxDBBuilder&& InfluxDBBuilder::setProxy(const Proxy& proxy)
{
dynamic_cast<transports::HTTP&>(*transport).setProxy(proxy);
return std::move(*this);
}

InfluxDBBuilder&& InfluxDBBuilder::setTimeout(std::chrono::milliseconds timeout)
{
dynamic_cast<transports::HTTP&>(*transport).setTimeout(timeout);
return std::move(*this);
}

InfluxDBBuilder&& InfluxDBBuilder::setVerifyCertificate(bool verify)
{
dynamic_cast<transports::HTTP&>(*transport).setVerifyCertificate(verify);
return std::move(*this);
}

InfluxDBBuilder InfluxDBBuilder::http(const std::string& url)
{
return InfluxDBBuilder{std::make_unique<transports::HTTP>(url)};
}


}
21 changes: 21 additions & 0 deletions test/HttpTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,27 @@ namespace influxdb::test
http.setProxy(Proxy{"https://auth-proxy-server:1234", Proxy::Auth{"abc", "def"}});
}

TEST_CASE("Set certificate verification", "[HttpTest]")
{
auto http = createHttp();

REQUIRE_CALL(sessionMock, SetVerifySsl(_)).WITH(bool{_1} == false);
http.setVerifyCertificate(false);

REQUIRE_CALL(sessionMock, SetVerifySsl(_)).WITH(bool{_1} == true);
http.setVerifyCertificate(true);
}

TEST_CASE("Set timeout sets timeouts", "[HttpTest]")
{
constexpr std::chrono::seconds timeout{3};
auto http = createHttp();

REQUIRE_CALL(sessionMock, SetTimeout(_)).WITH(_1.ms == timeout);
REQUIRE_CALL(sessionMock, SetConnectTimeout(_)).WITH(_1.ms == timeout);
http.setTimeout(timeout);
}

TEST_CASE("Execute sets parameters", "[HttpTest]")
{
auto http = createHttp();
Expand Down
5 changes: 5 additions & 0 deletions test/mock/CprMock.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ namespace cpr
influxdb::test::sessionMock.SetProxyAuth(std::move(proxy_auth));
}

void Session::SetVerifySsl(const VerifySsl& verify)
{
influxdb::test::sessionMock.SetVerifySsl(verify);
}

void Session::SetParameters(Parameters&& parameters)
{
influxdb::test::sessionMock.SetParameters(ParametersSpy::toMap(parameters));
Expand Down
1 change: 1 addition & 0 deletions test/mock/CprMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace influxdb::test
MAKE_MOCK1(SetAuth, void(const cpr::Authentication&));
MAKE_MOCK1(SetProxies, void(cpr::Proxies&&));
MAKE_MOCK1(SetProxyAuth, void(cpr::ProxyAuthentication&&));
MAKE_MOCK1(SetVerifySsl, void(const cpr::VerifySsl&));
};

extern SessionMock sessionMock;
Expand Down
26 changes: 26 additions & 0 deletions test/system/HttpAuthST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// SOFTWARE.

#include "SystemTest.h"
#include "InfluxDBBuilder.h"

namespace influxdb::test
{
Expand All @@ -43,4 +44,29 @@ namespace influxdb::test
CHECK_THAT(response, ContainsSubstring(user.name));
}
}

TEST_CASE("Http authentication methods", "[HttpAuthTest]")
{
using Catch::Matchers::ContainsSubstring;

const auto user = getUserFromEnv();

SECTION("Authenticate through factory")
{
auto db = InfluxDBFactory::Get("http://" + (user.name + ":" + user.pass + "@") + getHostFromEnv() + ":8086?db=ignore");

const auto response = db->execute("show users");
CHECK_THAT(response, ContainsSubstring(user.name));
}

SECTION("Authenticate through builder")
{
auto db = InfluxDBBuilder::http("http://" + getHostFromEnv() + ":8086?db=ignore")
.setBasicAuthentication(user.name, user.pass)
.connect();

const auto response = db->execute("show users");
CHECK_THAT(response, ContainsSubstring(user.name));
}
}
}
22 changes: 22 additions & 0 deletions test/system/InfluxDBST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// SOFTWARE.

#include "SystemTest.h"
#include "InfluxDBBuilder.h"

namespace influxdb::test
{
Expand All @@ -38,6 +39,27 @@ namespace influxdb::test
}
}

TEST_CASE("Connection configuration", "[InfluxDBST]")
{
using namespace Catch::Matchers;

SECTION("Connect through factory")
{
auto db = InfluxDBFactory::Get("http://" + getHostFromEnv() + ":8086?db=ignore");
const auto response = db->execute("show databases");
CHECK(response.empty() == false);
}

SECTION("Connect through builder")
{
auto db = InfluxDBBuilder::http("http://" + getHostFromEnv() + ":8086?db=ignore")
.setTimeout(std::chrono::seconds{5})
.connect();
const auto response = db->execute("show databases");
CHECK(response.empty() == false);
}
}

TEST_CASE("InfluxDB system test", "[InfluxDBST]")
{
using namespace Catch::Matchers;
Expand Down
8 changes: 6 additions & 2 deletions test/system/SystemTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ namespace influxdb::test
return {*user, *pass};
}

inline std::string getHostFromEnv()
{
return getEnv("INFLUXDBCXX_SYSTEMTEST_HOST").value_or("localhost");
}

inline std::unique_ptr<InfluxDB> configure(const std::string& db, std::optional<User> user = {})
{
const auto host = getEnv("INFLUXDBCXX_SYSTEMTEST_HOST").value_or("localhost");
const std::string authString{user ? (user->name + ":" + user->pass + "@") : ""};
return InfluxDBFactory::Get("http://" + authString + host + ":8086?db=" + db);
return InfluxDBFactory::Get("http://" + authString + getHostFromEnv() + ":8086?db=" + db);
}
}