summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Sartori <alberto.sartori@huawei.com>2025-02-24 14:16:42 +0100
committerAlberto Sartori <alberto.sartori@huawei.com>2025-02-25 11:27:16 +0100
commit455003d0e924414db339395e8367166e7820c5da (patch)
tree54d117565ea7edf059f4a18ebb1aaceca764ec5c
parente61131b18ad90e9fc067e6036cbcd6c64b28c986 (diff)
downloadjustbuild-455003d0e924414db339395e8367166e7820c5da.tar.gz
just serve: allow clients to access execution endpoint with a different address
To properly use `just serve`, both the client and the serve instance must talk to the very same execution endpoint. Typically, both the client and serve can reach out to the execution endpoint via the same IP address. However, it might be possible that the client and a serve instance know the same execution endpoint by means of differnet IP addresses. For example, the client knows the execution endpoint address through an _external_ IP address, while the serve instance, deployed within the same network infrastructure, only knows the _internal_ IP address. This patch adds the subkey `"client address"` -- of the key `"execution endpoint"` -- in the serve configuration file, to specify the alternative pair `address:port` used by the client.
-rw-r--r--CHANGELOG.md8
-rw-r--r--share/man/just-serve-config.5.md3
-rw-r--r--src/buildtool/common/cli.hpp2
-rw-r--r--src/buildtool/main/main.cpp1
-rw-r--r--src/buildtool/main/serve.cpp16
-rw-r--r--src/buildtool/serve_api/remote/config.hpp28
-rw-r--r--src/buildtool/serve_api/serve_service/TARGETS1
-rw-r--r--src/buildtool/serve_api/serve_service/configuration.cpp8
-rw-r--r--src/buildtool/serve_api/serve_service/configuration.hpp10
-rw-r--r--src/buildtool/serve_api/serve_service/serve_server_implementation.cpp3
10 files changed, 72 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfdeaf3c..e9c2635d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,14 @@ A feature release on top of `1.4.0`, backwards compatible.
defines how special entries (e.g., symlinks) are to be handled when
adding directories to CAS.
+- `just serve` accepts a new subkey `"client address"` for the key
+ `"execution endpoint"` in the configuration file. It informs the
+ `serve` instance that the client will access the remote-execution
+ endpoint via the given `"client address"` and not using the one
+ listed in the subkey `"address"`. This feature allows to position
+ `just serve` next to the remote-execution endpoint behind some
+ form of address translation.
+
### Fixes
- `just-import-git` now correctly inherits pragmas for imported
diff --git a/share/man/just-serve-config.5.md b/share/man/just-serve-config.5.md
index a21adf03..f890cd6a 100644
--- a/share/man/just-serve-config.5.md
+++ b/share/man/just-serve-config.5.md
@@ -82,6 +82,9 @@ The configuration file is given by a JSON object.
**`serve`**.
For subkey *`"address"`* the value is a string specifying the remote
execution address in a NAME:PORT format.
+ For subkey *`"client address"`* the value is a string specifying
+ the remote execution address used by the client in a NAME:PORT
+ format. If not provided, it defaults to *`"address"`*.
For subkey *`"compatible"`* the value is a flag which specifies whether
the remote endpoint uses the original remote execution protocol.
If the key *`"execution endpoint"`* is given, the following three keys will
diff --git a/src/buildtool/common/cli.hpp b/src/buildtool/common/cli.hpp
index f486a5fd..ef6c043c 100644
--- a/src/buildtool/common/cli.hpp
+++ b/src/buildtool/common/cli.hpp
@@ -186,6 +186,8 @@ struct ServeArguments {
std::optional<std::string> remote_serve_address;
// repositories populated from just-serve config file
std::vector<std::filesystem::path> repositories;
+ // remote execution endpoint as seen by the client
+ std::optional<std::string> client_remote_address;
};
struct GcArguments {
diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp
index 72a5b060..5acba963 100644
--- a/src/buildtool/main/main.cpp
+++ b/src/buildtool/main/main.cpp
@@ -192,6 +192,7 @@ void SetupLogging(LogArguments const& clargs) {
-> std::optional<RemoteServeConfig> {
RemoteServeConfig::Builder builder;
builder.SetRemoteAddress(srvargs.remote_serve_address)
+ .SetClientExecutionAddress(srvargs.client_remote_address)
.SetKnownRepositories(srvargs.repositories)
.SetJobs(cargs.jobs)
.SetActionTimeout(bargs.timeout)
diff --git a/src/buildtool/main/serve.cpp b/src/buildtool/main/serve.cpp
index 531074c3..5d5f49fb 100644
--- a/src/buildtool/main/serve.cpp
+++ b/src/buildtool/main/serve.cpp
@@ -415,6 +415,22 @@ void ReadJustServeConfig(gsl::not_null<CommandLineArguments*> const& clargs) {
}
clargs->endpoint.remote_execution_address = address->String();
}
+ // read the address used by the client
+ auto client_address =
+ exec_endpoint->Get("client address", Expression::none_t{});
+ if (client_address.IsNotNull()) {
+ if (not client_address->IsString()) {
+ Logger::Log(
+ LogLevel::Error,
+ "In serve service config file {}:\nValue for execution "
+ "endpoint key \"client address\" has to be a string, but "
+ "found {}",
+ clargs->serve.config.string(),
+ client_address->ToString());
+ std::exit(kExitFailure);
+ }
+ clargs->serve.client_remote_address = client_address->String();
+ }
if (not ParseRetryCliOptions(serve_config, &clargs->retry)) {
std::exit(kExitFailure);
}
diff --git a/src/buildtool/serve_api/remote/config.hpp b/src/buildtool/serve_api/remote/config.hpp
index 582727e0..82119828 100644
--- a/src/buildtool/serve_api/remote/config.hpp
+++ b/src/buildtool/serve_api/remote/config.hpp
@@ -34,9 +34,12 @@
struct RemoteServeConfig final {
class Builder;
- // Server address of remote execution.
+ // Server address of the serve endpoint.
std::optional<ServerAddress> const remote_address;
+ // Execution endpoint used by the client.
+ std::optional<ServerAddress> const client_execution_address;
+
// Known Git repositories to serve server.
std::vector<std::filesystem::path> const known_repositories;
@@ -56,6 +59,13 @@ struct RemoteServeConfig final {
class RemoteServeConfig::Builder final {
public:
// Set remote execution and cache address, unsets if parsing `address` fails
+ auto SetClientExecutionAddress(std::optional<std::string> value) noexcept
+ -> Builder& {
+ client_execution_address_ = std::move(value);
+ return *this;
+ }
+
+ // Set remote execution and cache address, unsets if parsing `address` fails
auto SetRemoteAddress(std::optional<std::string> value) noexcept
-> Builder& {
remote_address_ = std::move(value);
@@ -110,7 +120,15 @@ class RemoteServeConfig::Builder final {
*remote_address_)};
}
}
-
+ auto client_execution_address = default_config.client_execution_address;
+ if (client_execution_address_.has_value()) {
+ client_execution_address = ParseAddress(*client_execution_address_);
+ if (not client_execution_address) {
+ return unexpected{
+ fmt::format("Setting client execution address '{}' failed.",
+ *client_execution_address_)};
+ }
+ }
auto known_repositories = default_config.known_repositories;
if (known_repositories_.has_value()) {
try {
@@ -154,6 +172,7 @@ class RemoteServeConfig::Builder final {
return RemoteServeConfig{
.remote_address = std::move(remote_address),
+ .client_execution_address = std::move(client_execution_address),
.known_repositories = std::move(known_repositories),
.jobs = jobs,
.build_jobs = build_jobs,
@@ -162,9 +181,12 @@ class RemoteServeConfig::Builder final {
}
private:
- // Server address of remote execution.
+ // Server address of the serve endpoint.
std::optional<std::string> remote_address_;
+ // Execution endpoint used by the client.
+ std::optional<std::string> client_execution_address_;
+
// Known Git repositories to serve server.
std::optional<std::vector<std::filesystem::path>> known_repositories_;
diff --git a/src/buildtool/serve_api/serve_service/TARGETS b/src/buildtool/serve_api/serve_service/TARGETS
index 7b459f60..2a2928e5 100644
--- a/src/buildtool/serve_api/serve_service/TARGETS
+++ b/src/buildtool/serve_api/serve_service/TARGETS
@@ -170,6 +170,7 @@
, ["@", "gsl", "", "gsl"]
, ["src/buildtool/crypto", "hash_function"]
, ["src/buildtool/execution_api/remote", "config"]
+ , ["src/buildtool/serve_api/remote", "config"]
]
, "stage": ["src", "buildtool", "serve_api", "serve_service"]
, "private-deps":
diff --git a/src/buildtool/serve_api/serve_service/configuration.cpp b/src/buildtool/serve_api/serve_service/configuration.cpp
index 2c1a14e4..503267f9 100644
--- a/src/buildtool/serve_api/serve_service/configuration.cpp
+++ b/src/buildtool/serve_api/serve_service/configuration.cpp
@@ -27,7 +27,13 @@ auto ConfigurationService::RemoteExecutionEndpoint(
const ::justbuild::just_serve::RemoteExecutionEndpointRequest* /*request*/,
::justbuild::just_serve::RemoteExecutionEndpointResponse* response)
-> ::grpc::Status {
- auto address = remote_config_.remote_address;
+ std::optional<ServerAddress> address;
+ if (serve_config_.client_execution_address.has_value()) {
+ address = serve_config_.client_execution_address;
+ }
+ else {
+ address = remote_config_.remote_address;
+ }
response->set_address(address ? address->ToJson().dump() : std::string());
return ::grpc::Status::OK;
}
diff --git a/src/buildtool/serve_api/serve_service/configuration.hpp b/src/buildtool/serve_api/serve_service/configuration.hpp
index 35431b7f..ce37c31d 100644
--- a/src/buildtool/serve_api/serve_service/configuration.hpp
+++ b/src/buildtool/serve_api/serve_service/configuration.hpp
@@ -22,6 +22,7 @@
#include "justbuild/just_serve/just_serve.pb.h"
#include "src/buildtool/crypto/hash_function.hpp"
#include "src/buildtool/execution_api/remote/config.hpp"
+#include "src/buildtool/serve_api/remote/config.hpp"
// This service can be used by the client to double-check the server
// configuration.
@@ -30,9 +31,11 @@ class ConfigurationService final
public:
explicit ConfigurationService(
HashFunction::Type hash_type,
- gsl::not_null<RemoteExecutionConfig const*> const&
- remote_config) noexcept
- : hash_type_{hash_type}, remote_config_{*remote_config} {};
+ gsl::not_null<RemoteExecutionConfig const*> const& remote_config,
+ gsl::not_null<RemoteServeConfig const*> const& serve_config) noexcept
+ : hash_type_{hash_type},
+ remote_config_{*remote_config},
+ serve_config_{*serve_config} {}
// Returns the address of the associated remote endpoint, if set,
// or an empty string signaling that the serve endpoint acts also
@@ -58,6 +61,7 @@ class ConfigurationService final
private:
HashFunction::Type hash_type_;
RemoteExecutionConfig const& remote_config_;
+ RemoteServeConfig const& serve_config_;
};
#endif // INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_CONFIGURATION_HPP
diff --git a/src/buildtool/serve_api/serve_service/serve_server_implementation.cpp b/src/buildtool/serve_api/serve_service/serve_server_implementation.cpp
index f6405651..c8426469 100644
--- a/src/buildtool/serve_api/serve_service/serve_server_implementation.cpp
+++ b/src/buildtool/serve_api/serve_service/serve_server_implementation.cpp
@@ -138,7 +138,8 @@ auto ServeServerImpl::Run(
&apis,
lock_,
serve ? &*serve : nullptr};
- ConfigurationService cs{hash_type, remote_context->exec_config};
+ ConfigurationService cs{
+ hash_type, remote_context->exec_config, &serve_config};
// For the SourceTreeService we need to always have access to a native
// storage. In compatible mode, this requires creating a second local